Skip to content

Commit

Permalink
Keystone adheres to public_endpoint opt only
Browse files Browse the repository at this point in the history
With the complete removal of the v2.0 API, keystone no longer
differentiates between admin and public endpoints. This change
deprecates the "admin_endpoint" configuration option and converts
keystone over to only using the public endpoint. The "admin" endpoint
was only used for unit testing purposes.

This change does not clean up all code related, it is aimed to make
the most minimal set of changes eliminating the use of the
"admin_endpoint" configuration option.

Partial-Bug: #1776504
Change-Id: I08f6f8ae078d65203bd95c43c80367dd3489be48
  • Loading branch information
tempusfrangit committed Jun 27, 2018
1 parent 925cded commit ecf721a
Show file tree
Hide file tree
Showing 8 changed files with 44 additions and 82 deletions.
2 changes: 1 addition & 1 deletion keystone/common/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
'tenant_id', 'project_id', 'user_id',
'public_bind_host', 'admin_bind_host',
'compute_host', 'admin_port', 'public_port',
'public_endpoint', 'admin_endpoint', ]
'public_endpoint', ]


# NOTE(stevermar): This UUID must stay the same, forever, across
Expand Down
12 changes: 3 additions & 9 deletions keystone/common/wsgi.py
Original file line number Diff line number Diff line change
Expand Up @@ -305,14 +305,8 @@ def _require_attributes(self, ref, attrs):
raise exception.ValidationError(message=msg)

@classmethod
def base_url(cls, context, endpoint_type):
# NOTE(morgan): endpoint type must be "admin" or "public" to lookup
# the relevant value from the config options. Make the error clearer
# if we somehow got here with a different endpoint type.
if endpoint_type not in ('admin', 'public'):
raise ValueError('PROGRAMMING ERROR: Endpoint type must be '
'"admin" or "public".')
url = CONF['%s_endpoint' % endpoint_type]
def base_url(cls, context, endpoint_type=None):
url = CONF['public_endpoint']

if url:
substitutions = dict(
Expand Down Expand Up @@ -764,7 +758,7 @@ def render_exception(error, context=None, request=None, user_locale=None):
local_context = {'environment': request.environ}
elif context and 'environment' in context:
local_context = {'environment': context['environment']}
url = Application.base_url(local_context, 'public')
url = Application.base_url(local_context)

headers.append(('WWW-Authenticate', 'Keystone uri="%s"' % url))
return render_response(status=(error.code, error.title),
Expand Down
6 changes: 6 additions & 0 deletions keystone/conf/default.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,12 @@

admin_endpoint = cfg.URIOpt(
'admin_endpoint',
deprecated_since=versionutils.deprecated.ROCKY,
deprecated_for_removal=True,
deprecated_reason=utils.fmt("""
With the removal of the 2.0 API keystone does not distinguish between admin
and public endpoints.
"""),
help=utils.fmt("""
The base admin endpoint URL for Keystone that is advertised to clients (NOTE:
this does NOT affect how Keystone listens for connections). Defaults to the
Expand Down
10 changes: 5 additions & 5 deletions keystone/server/wsgi.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@
# import core and call it directly, eventually keystone_flask will not
# export all the symbols from keystone.flask.core only specific ones that
# are meant for public consumption
def initialize_admin_application():
return keystone_flask.initialize_application(
name='admin', config_files=flask_core._get_config_files())


def initialize_public_application():
return keystone_flask.initialize_application(
name='public', config_files=flask_core._get_config_files())


# Keystone does not differentiate between "admin" and public with the removal
# of V2.0
initialize_admin_application = initialize_public_application
5 changes: 1 addition & 4 deletions keystone/tests/unit/rest.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,6 @@ def setUp(self, app_conf='keystone', enable_sqlite_foreign_key=False):
self.public_app = webtest.TestApp(
self.loadapp(name='public'))
self.addCleanup(delattr, self, 'public_app')
self.admin_app = webtest.TestApp(
self.loadapp(name='admin'))
self.addCleanup(delattr, self, 'admin_app')

def auth_plugin_config_override(self, methods=None, **method_classes):
self.useFixture(
Expand Down Expand Up @@ -213,7 +210,7 @@ def public_request(self, **kwargs):
return self._request(app=self.public_app, **kwargs)

def admin_request(self, **kwargs):
return self._request(app=self.admin_app, **kwargs)
return self._request(app=self.public_app, **kwargs)

def _get_token_id(self, r):
"""Helper method to return a token ID from a response.
Expand Down
40 changes: 20 additions & 20 deletions keystone/tests/unit/test_v3_auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -2339,8 +2339,8 @@ def test_bind_not_set_with_remote_user(self):
self.config_fixture.config(group='token', bind=[])
auth_data = self.build_authentication_request()
remote_user = self.default_domain_user['name']
self.admin_app.extra_environ.update({'REMOTE_USER': remote_user,
'AUTH_TYPE': 'Negotiate'})
self.public_app.extra_environ.update({'REMOTE_USER': remote_user,
'AUTH_TYPE': 'Negotiate'})
r = self.v3_create_token(auth_data)
token = self.assertValidUnscopedTokenResponse(r)
self.assertNotIn('bind', token)
Expand All @@ -2350,8 +2350,8 @@ def test_verify_with_bound_token(self):
auth_data = self.build_authentication_request(
project_id=self.project['id'])
remote_user = self.default_domain_user['name']
self.admin_app.extra_environ.update({'REMOTE_USER': remote_user,
'AUTH_TYPE': 'Negotiate'})
self.public_app.extra_environ.update({'REMOTE_USER': remote_user,
'AUTH_TYPE': 'Negotiate'})

token = self.get_requested_token(auth_data)
headers = {'X-Subject-Token': token}
Expand All @@ -2365,8 +2365,8 @@ def test_auth_with_bind_token(self):

auth_data = self.build_authentication_request()
remote_user = self.default_domain_user['name']
self.admin_app.extra_environ.update({'REMOTE_USER': remote_user,
'AUTH_TYPE': 'Negotiate'})
self.public_app.extra_environ.update({'REMOTE_USER': remote_user,
'AUTH_TYPE': 'Negotiate'})
r = self.v3_create_token(auth_data)

# the unscoped token should have bind information in it
Expand Down Expand Up @@ -2587,8 +2587,8 @@ def test_verify_with_bound_token(self):
auth_data = self.build_authentication_request(
project_id=self.project['id'])
remote_user = self.default_domain_user['name']
self.admin_app.extra_environ.update({'REMOTE_USER': remote_user,
'AUTH_TYPE': 'Negotiate'})
self.public_app.extra_environ.update({'REMOTE_USER': remote_user,
'AUTH_TYPE': 'Negotiate'})
# Bind not current supported by Fernet, see bug 1433311.
self.v3_create_token(auth_data,
expected_status=http_client.NOT_IMPLEMENTED)
Expand All @@ -2598,8 +2598,8 @@ def test_auth_with_bind_token(self):

auth_data = self.build_authentication_request()
remote_user = self.default_domain_user['name']
self.admin_app.extra_environ.update({'REMOTE_USER': remote_user,
'AUTH_TYPE': 'Negotiate'})
self.public_app.extra_environ.update({'REMOTE_USER': remote_user,
'AUTH_TYPE': 'Negotiate'})
# Bind not current supported by Fernet, see bug 1433311.
self.v3_create_token(auth_data,
expected_status=http_client.NOT_IMPLEMENTED)
Expand Down Expand Up @@ -3645,9 +3645,9 @@ def test_project_id_scoped_with_remote_user(self):
kerberos=self.kerberos)
remote_user = self.user['name']
remote_domain = self.domain['name']
self.admin_app.extra_environ.update({'REMOTE_USER': remote_user,
'REMOTE_DOMAIN': remote_domain,
'AUTH_TYPE': 'Negotiate'})
self.public_app.extra_environ.update({'REMOTE_USER': remote_user,
'REMOTE_DOMAIN': remote_domain,
'AUTH_TYPE': 'Negotiate'})
r = self.v3_create_token(auth_data)
token = self.assertValidProjectScopedTokenResponse(r)
self.assertEqual(self.user['name'], token['bind']['kerberos'])
Expand All @@ -3657,9 +3657,9 @@ def test_unscoped_bind_with_remote_user(self):
auth_data = self.build_authentication_request(kerberos=self.kerberos)
remote_user = self.user['name']
remote_domain = self.domain['name']
self.admin_app.extra_environ.update({'REMOTE_USER': remote_user,
'REMOTE_DOMAIN': remote_domain,
'AUTH_TYPE': 'Negotiate'})
self.public_app.extra_environ.update({'REMOTE_USER': remote_user,
'REMOTE_DOMAIN': remote_domain,
'AUTH_TYPE': 'Negotiate'})
r = self.v3_create_token(auth_data)
token = self.assertValidUnscopedTokenResponse(r)
self.assertEqual(self.user['name'], token['bind']['kerberos'])
Expand Down Expand Up @@ -3703,8 +3703,8 @@ def test_project_id_scoped_with_remote_user(self):
project_id=self.default_domain_project['id'],
kerberos=self.kerberos)
remote_user = self.default_domain_user['name']
self.admin_app.extra_environ.update({'REMOTE_USER': remote_user,
'AUTH_TYPE': 'Negotiate'})
self.public_app.extra_environ.update({'REMOTE_USER': remote_user,
'AUTH_TYPE': 'Negotiate'})
r = self.v3_create_token(auth_data)
token = self.assertValidProjectScopedTokenResponse(r)
self.assertEqual(self.default_domain_user['name'],
Expand All @@ -3714,8 +3714,8 @@ def test_unscoped_bind_with_remote_user(self):
self.config_fixture.config(group='token', bind=['kerberos'])
auth_data = self.build_authentication_request(kerberos=self.kerberos)
remote_user = self.default_domain_user['name']
self.admin_app.extra_environ.update({'REMOTE_USER': remote_user,
'AUTH_TYPE': 'Negotiate'})
self.public_app.extra_environ.update({'REMOTE_USER': remote_user,
'AUTH_TYPE': 'Negotiate'})
r = self.v3_create_token(auth_data)
token = self.assertValidUnscopedTokenResponse(r)
self.assertEqual(self.default_domain_user['name'],
Expand Down
49 changes: 7 additions & 42 deletions keystone/tests/unit/test_versions.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@

from keystone.common import json_home
from keystone.tests import unit
from keystone.tests.unit import utils
from keystone.version import controllers


Expand Down Expand Up @@ -685,14 +684,10 @@ def setUp(self):
super(VersionTestCase, self).setUp()
self.load_backends()
self.public_app = self.loadapp('public')
self.admin_app = self.loadapp('admin')

self.admin_port = random.randint(10000, 30000)
self.public_port = random.randint(40000, 60000)

self.config_fixture.config(
public_endpoint='http://localhost:%d' % self.public_port,
admin_endpoint='http://localhost:%d' % self.admin_port)
public_endpoint='http://localhost:%d' % self.public_port)

def config_overrides(self):
super(VersionTestCase, self).config_overrides()
Expand All @@ -714,22 +709,10 @@ def test_public_versions(self):
version, 'http://localhost:%s/v3/' % self.public_port)
self.assertThat(data, _VersionsEqual(expected))

def test_admin_versions(self):
client = TestClient(self.admin_app)
resp = client.get('/')
self.assertEqual(300, resp.status_int)
data = jsonutils.loads(resp.body)
expected = VERSIONS_RESPONSE
for version in expected['versions']['values']:
if version['id'].startswith('v3'):
self._paste_in_port(
version, 'http://localhost:%s/v3/' % self.admin_port)
self.assertThat(data, _VersionsEqual(expected))

def test_use_site_url_if_endpoint_unset(self):
self.config_fixture.config(public_endpoint=None, admin_endpoint=None)
self.config_fixture.config(public_endpoint=None)

for app in (self.public_app, self.admin_app):
for app in (self.public_app,):
client = TestClient(app)
resp = client.get('/')
self.assertEqual(300, resp.status_int)
Expand All @@ -752,20 +735,9 @@ def test_public_version_v3(self):
'http://localhost:%s/v3/' % self.public_port)
self.assertEqual(expected, data)

@utils.wip('waiting on bug #1381961')
def test_admin_version_v3(self):
client = TestClient(self.admin_app)
resp = client.get('/v3/')
self.assertEqual(http_client.OK, resp.status_int)
data = jsonutils.loads(resp.body)
expected = v3_VERSION_RESPONSE
self._paste_in_port(expected['version'],
'http://localhost:%s/v3/' % self.admin_port)
self.assertEqual(expected, data)

def test_use_site_url_if_endpoint_unset_v3(self):
self.config_fixture.config(public_endpoint=None, admin_endpoint=None)
for app in (self.public_app, self.admin_app):
self.config_fixture.config(public_endpoint=None)
for app in (self.public_app,):
client = TestClient(app)
resp = client.get('/v3/')
self.assertEqual(http_client.OK, resp.status_int)
Expand Down Expand Up @@ -904,12 +876,10 @@ def setUp(self):
super(VersionSingleAppTestCase, self).setUp()
self.load_backends()

self.admin_port = random.randint(10000, 30000)
self.public_port = random.randint(40000, 60000)

self.config_fixture.config(
public_endpoint='http://localhost:%d' % self.public_port,
admin_endpoint='http://localhost:%d' % self.admin_port)
public_endpoint='http://localhost:%d' % self.public_port)

def config_overrides(self):
super(VersionSingleAppTestCase, self).config_overrides()
Expand All @@ -920,11 +890,6 @@ def _paste_in_port(self, response, port):
link['href'] = port

def _test_version(self, app_name):
def app_port():
if app_name == 'admin':
return self.admin_port
else:
return self.public_port
app = self.loadapp(app_name)
client = TestClient(app)
resp = client.get('/')
Expand All @@ -934,7 +899,7 @@ def app_port():
for version in expected['versions']['values']:
if version['id'].startswith('v3'):
self._paste_in_port(
version, 'http://localhost:%s/v3/' % app_port())
version, 'http://localhost:%s/v3/' % self.public_port)
self.assertThat(data, _VersionsEqual(expected))

def test_public(self):
Expand Down
2 changes: 1 addition & 1 deletion keystone/tests/unit/test_wsgi.py
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ def index(self, request):
def test_base_url(self):
class FakeApp(wsgi.Application):
def index(self, request):
return self.base_url(request.context_dict, 'public')
return self.base_url(request.context_dict)
req = self._make_request(url='/')
# NOTE(gyee): according to wsgiref, if HTTP_HOST is present in the
# request environment, it will be used to construct the base url.
Expand Down

0 comments on commit ecf721a

Please sign in to comment.