diff --git a/etc/keystone-paste.ini b/etc/keystone-paste.ini index 447cfe60ed..b629b48c97 100644 --- a/etc/keystone-paste.ini +++ b/etc/keystone-paste.ini @@ -12,11 +12,6 @@ use = egg:keystone#build_auth_context [filter:token_auth] use = egg:keystone#token_auth -[filter:admin_token_auth] -# This is deprecated in the M release and will be removed in the O release. -# Use `keystone-manage bootstrap` and remove this from the pipelines below. -use = egg:keystone#admin_token_auth - [filter:json_body] use = egg:keystone#json_body @@ -60,17 +55,17 @@ use = egg:keystone#admin_service [pipeline:public_api] # The last item in this pipeline must be public_service or an equivalent # application. It cannot be a filter. -pipeline = healthcheck cors sizelimit http_proxy_to_wsgi osprofiler url_normalize request_id admin_token_auth build_auth_context token_auth json_body ec2_extension public_service +pipeline = healthcheck cors sizelimit http_proxy_to_wsgi osprofiler url_normalize request_id build_auth_context token_auth json_body ec2_extension public_service [pipeline:admin_api] # The last item in this pipeline must be admin_service or an equivalent # application. It cannot be a filter. -pipeline = healthcheck cors sizelimit http_proxy_to_wsgi osprofiler url_normalize request_id admin_token_auth build_auth_context token_auth json_body ec2_extension s3_extension admin_service +pipeline = healthcheck cors sizelimit http_proxy_to_wsgi osprofiler url_normalize request_id build_auth_context token_auth json_body ec2_extension s3_extension admin_service [pipeline:api_v3] # The last item in this pipeline must be service_v3 or an equivalent # application. It cannot be a filter. -pipeline = healthcheck cors sizelimit http_proxy_to_wsgi osprofiler url_normalize request_id admin_token_auth build_auth_context token_auth json_body ec2_extension_v3 s3_extension service_v3 +pipeline = healthcheck cors sizelimit http_proxy_to_wsgi osprofiler url_normalize request_id build_auth_context token_auth json_body ec2_extension_v3 s3_extension service_v3 [app:public_version_service] use = egg:keystone#public_version_service diff --git a/keystone/middleware/auth.py b/keystone/middleware/auth.py index a994e85888..38d4aa269b 100644 --- a/keystone/middleware/auth.py +++ b/keystone/middleware/auth.py @@ -137,6 +137,21 @@ class AuthContextMiddleware(auth_token.BaseAuthProtocol): @wsgi.middleware_exceptions def process_request(self, request): context_env = request.environ.get(core.CONTEXT_ENV, {}) + + # NOTE(notmorgan): This code is merged over from the admin token + # middleware and now emits the security warning when the + # conf.admin_token value is set. + token = request.headers.get(core.AUTH_TOKEN_HEADER) + if CONF.admin_token and (token == CONF.admin_token): + context_env['is_admin'] = True + LOG.warning( + _LW("The use of the '[DEFAULT] admin_token' configuration" + "option presents a significant security risk and should " + "not be set. This option is deprecated in favor of using " + "'keystone-manage bootstrap' and will be removed in a " + "future release.")) + request.environ[core.CONTEXT_ENV] = context_env + if not context_env.get('is_admin', False): resp = super(AuthContextMiddleware, self).process_request(request) diff --git a/keystone/middleware/core.py b/keystone/middleware/core.py index 5f4c0b9e30..5ef76a69de 100644 --- a/keystone/middleware/core.py +++ b/keystone/middleware/core.py @@ -13,12 +13,13 @@ # under the License. from oslo_log import log +from oslo_log import versionutils from oslo_serialization import jsonutils from keystone.common import wsgi import keystone.conf from keystone import exception -from keystone.i18n import _LW +from keystone.i18n import _LE CONF = keystone.conf.CONF @@ -51,26 +52,26 @@ class TokenAuthMiddleware(wsgi.Middleware): class AdminTokenAuthMiddleware(wsgi.Middleware): - """A trivial filter that checks for a pre-defined admin token. - - Sets 'is_admin' to true in the context, expected to be checked by - methods that are admin-only. - - """ + # NOTE(notmorgan): DEPRECATED FOR REMOVAL does nothing but warn to remove + # from pipeline + @versionutils.deprecated( + as_of=versionutils.deprecated.PIKE, + what='AdminTokenAuthMiddleware in the paste-ini pipeline.', + remove_in=+1) def __init__(self, application): super(AdminTokenAuthMiddleware, self).__init__(application) - LOG.warning(_LW("The admin_token_auth middleware presents a security " - "risk and should be removed from the " - "[pipeline:api_v3], [pipeline:admin_api], and " - "[pipeline:public_api] sections of your paste ini " - "file.")) - - def process_request(self, request): - token = request.headers.get(AUTH_TOKEN_HEADER) - context = request.environ.get(CONTEXT_ENV, {}) - context['is_admin'] = CONF.admin_token and (token == CONF.admin_token) - request.environ[CONTEXT_ENV] = context + # NOTE(notmorgan): This is deprecated and emits a significant error + # message to make sure deployers update their deployments so in the + # future release upgrade the deployment does not break. + LOG.error(_LE('The admin_token_auth middleware functionality has been ' + 'merged into the main auth middleware ' + '(keystone.middleware.auth.AuthContextMiddleware). ' + '`admin_token_auth` must be removed from the ' + '[pipeline:api_v3], [pipeline:admin_api], and ' + '[pipeline:public_api] sections of your paste ini ' + 'file. The [filter:admin_token_auth] block will also ' + 'need to be removed from your paste ini file. ')) class JsonBodyMiddleware(wsgi.Middleware): diff --git a/keystone/tests/unit/test_middleware.py b/keystone/tests/unit/test_middleware.py index e0176edfca..3a04dbcb10 100644 --- a/keystone/tests/unit/test_middleware.py +++ b/keystone/tests/unit/test_middleware.py @@ -111,26 +111,6 @@ class TokenAuthMiddlewareTest(MiddlewareRequestTestBase): self.assertEqual('MAGIC', context['token_id']) -class AdminTokenAuthMiddlewareTest(MiddlewareRequestTestBase): - - MIDDLEWARE_CLASS = middleware.AdminTokenAuthMiddleware - - def config_overrides(self): - super(AdminTokenAuthMiddlewareTest, self).config_overrides() - self.config_fixture.config( - admin_token='ADMIN') - - def test_request_admin(self): - headers = {middleware.AUTH_TOKEN_HEADER: 'ADMIN'} - req = self._do_middleware_request(headers=headers) - self.assertTrue(req.environ[middleware.CONTEXT_ENV]['is_admin']) - - def test_request_non_admin(self): - headers = {middleware.AUTH_TOKEN_HEADER: 'NOT-ADMIN'} - req = self._do_middleware_request(headers=headers) - self.assertFalse(req.environ[middleware.CONTEXT_ENV]['is_admin']) - - class JsonBodyMiddlewareTest(MiddlewareRequestTestBase): MIDDLEWARE_CLASS = middleware.JsonBodyMiddleware @@ -768,6 +748,14 @@ class AuthContextMiddlewareTest(test_backend_sql.SqlTests, self.config_fixture.config(admin_token='ADMIN') log_fix = self.useFixture(fixtures.FakeLogger()) headers = {middleware.AUTH_TOKEN_HEADER: 'ADMIN'} - environ = {middleware.core.CONTEXT_ENV: {'is_admin': True}} - self._do_middleware_request(headers=headers, extra_environ=environ) + req = self._do_middleware_request(headers=headers) + self.assertTrue(req.environ[middleware.CONTEXT_ENV]['is_admin']) self.assertNotIn('Invalid user token', log_fix.output) + + def test_request_non_admin(self): + self.config_fixture.config( + admin_token='ADMIN') + log_fix = self.useFixture(fixtures.FakeLogger()) + headers = {middleware.AUTH_TOKEN_HEADER: 'NOT-ADMIN'} + self._do_middleware_request(headers=headers) + self.assertIn('Invalid user token', log_fix.output) diff --git a/keystone/tests/unit/test_v3_identity.py b/keystone/tests/unit/test_v3_identity.py index 890fe64c49..926300a6a3 100644 --- a/keystone/tests/unit/test_v3_identity.py +++ b/keystone/tests/unit/test_v3_identity.py @@ -59,21 +59,6 @@ class IdentityTestCaseStaticAdminToken(test_v3.RestfulTestCase): self.get('/users', token=CONF.admin_token, expected_status=exception.Unauthorized.code) - def test_create_user_with_admin_token_and_no_domain(self): - """Call ``POST /users`` with admin token but no domain id. - - It should not be possible to use the admin token to create a user - while not explicitly passing the domain in the request body. - - """ - # Passing a valid domain id to new_user_ref() since domain_id is - # not an optional parameter. - ref = unit.new_user_ref(domain_id=self.domain_id) - # Delete the domain id before sending the request. - del ref['domain_id'] - self.post('/users', body={'user': ref}, token=CONF.admin_token, - expected_status=http_client.BAD_REQUEST) - class IdentityTestCase(test_v3.RestfulTestCase): """Test users and groups.""" diff --git a/releasenotes/notes/removed-as-of-pike-deadbeefdeadbeef.yaml b/releasenotes/notes/removed-as-of-pike-deadbeefdeadbeef.yaml index dbea0a7515..aa2f8a2de9 100644 --- a/releasenotes/notes/removed-as-of-pike-deadbeefdeadbeef.yaml +++ b/releasenotes/notes/removed-as-of-pike-deadbeefdeadbeef.yaml @@ -6,3 +6,13 @@ other: The removed code included ``keystone.common.kvs`` configuration options for the KVS code, unit tests, and the KVS token persistence driver ``keystone.token.persistence.backends.kvs``. All associated documentation has been removed. + - > + [`blueprint removed-as-of-pike `_] + The ``admin_token_auth`` filter has been removed from all sample pipelines, + specifically, the following section has been removed from ``keystone-paste.ini``:: + + [filter:admin_token_auth] + use = egg:keystone#admin_token_auth + + The functionality of the ``ADMIN_TOKEN`` remains, but has been incorporated + into the main auth middleware (``keystone.middleware.auth.AuthContextMiddleware``).