Deprecate (and emit message) AdminTokenAuthMiddleware

Officially deprecate the admin_token_auth in the paste-ini. The
functionality has been merged into auth_context_middleware. This allows
for a smoother removal of the admin-token functionality down the line.

The AdminTokenAuthMiddleware now does nothing if in the pipeline
except emitting a log.error.

This also removes the ADMIN token from the paste-pipeline itself

implements bp: removed-as-of-pike
Co-authored-by: Morgan Fainberg <morgan.fainberg@gmail.com>
Change-Id: I57586ccfa0ad1309cc806d95377dc1ecad015914
This commit is contained in:
Adam Young 2017-02-01 14:39:27 -05:00 committed by David Stanek
parent 66d3c3493c
commit 4981da8fb0
6 changed files with 57 additions and 63 deletions

View File

@ -12,11 +12,6 @@ use = egg:keystone#build_auth_context
[filter:token_auth] [filter:token_auth]
use = egg:keystone#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] [filter:json_body]
use = egg:keystone#json_body use = egg:keystone#json_body
@ -60,17 +55,17 @@ use = egg:keystone#admin_service
[pipeline:public_api] [pipeline:public_api]
# The last item in this pipeline must be public_service or an equivalent # The last item in this pipeline must be public_service or an equivalent
# application. It cannot be a filter. # 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] [pipeline:admin_api]
# The last item in this pipeline must be admin_service or an equivalent # The last item in this pipeline must be admin_service or an equivalent
# application. It cannot be a filter. # 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] [pipeline:api_v3]
# The last item in this pipeline must be service_v3 or an equivalent # The last item in this pipeline must be service_v3 or an equivalent
# application. It cannot be a filter. # 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] [app:public_version_service]
use = egg:keystone#public_version_service use = egg:keystone#public_version_service

View File

@ -137,6 +137,21 @@ class AuthContextMiddleware(auth_token.BaseAuthProtocol):
@wsgi.middleware_exceptions @wsgi.middleware_exceptions
def process_request(self, request): def process_request(self, request):
context_env = request.environ.get(core.CONTEXT_ENV, {}) 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): if not context_env.get('is_admin', False):
resp = super(AuthContextMiddleware, self).process_request(request) resp = super(AuthContextMiddleware, self).process_request(request)

View File

@ -13,12 +13,13 @@
# under the License. # under the License.
from oslo_log import log from oslo_log import log
from oslo_log import versionutils
from oslo_serialization import jsonutils from oslo_serialization import jsonutils
from keystone.common import wsgi from keystone.common import wsgi
import keystone.conf import keystone.conf
from keystone import exception from keystone import exception
from keystone.i18n import _LW from keystone.i18n import _LE
CONF = keystone.conf.CONF CONF = keystone.conf.CONF
@ -51,26 +52,26 @@ class TokenAuthMiddleware(wsgi.Middleware):
class AdminTokenAuthMiddleware(wsgi.Middleware): class AdminTokenAuthMiddleware(wsgi.Middleware):
"""A trivial filter that checks for a pre-defined admin token. # NOTE(notmorgan): DEPRECATED FOR REMOVAL does nothing but warn to remove
# from pipeline
Sets 'is_admin' to true in the context, expected to be checked by
methods that are admin-only.
"""
@versionutils.deprecated(
as_of=versionutils.deprecated.PIKE,
what='AdminTokenAuthMiddleware in the paste-ini pipeline.',
remove_in=+1)
def __init__(self, application): def __init__(self, application):
super(AdminTokenAuthMiddleware, self).__init__(application) super(AdminTokenAuthMiddleware, self).__init__(application)
LOG.warning(_LW("The admin_token_auth middleware presents a security " # NOTE(notmorgan): This is deprecated and emits a significant error
"risk and should be removed from the " # message to make sure deployers update their deployments so in the
"[pipeline:api_v3], [pipeline:admin_api], and " # future release upgrade the deployment does not break.
"[pipeline:public_api] sections of your paste ini " LOG.error(_LE('The admin_token_auth middleware functionality has been '
"file.")) 'merged into the main auth middleware '
'(keystone.middleware.auth.AuthContextMiddleware). '
def process_request(self, request): '`admin_token_auth` must be removed from the '
token = request.headers.get(AUTH_TOKEN_HEADER) '[pipeline:api_v3], [pipeline:admin_api], and '
context = request.environ.get(CONTEXT_ENV, {}) '[pipeline:public_api] sections of your paste ini '
context['is_admin'] = CONF.admin_token and (token == CONF.admin_token) 'file. The [filter:admin_token_auth] block will also '
request.environ[CONTEXT_ENV] = context 'need to be removed from your paste ini file. '))
class JsonBodyMiddleware(wsgi.Middleware): class JsonBodyMiddleware(wsgi.Middleware):

View File

@ -111,26 +111,6 @@ class TokenAuthMiddlewareTest(MiddlewareRequestTestBase):
self.assertEqual('MAGIC', context['token_id']) 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): class JsonBodyMiddlewareTest(MiddlewareRequestTestBase):
MIDDLEWARE_CLASS = middleware.JsonBodyMiddleware MIDDLEWARE_CLASS = middleware.JsonBodyMiddleware
@ -768,6 +748,14 @@ class AuthContextMiddlewareTest(test_backend_sql.SqlTests,
self.config_fixture.config(admin_token='ADMIN') self.config_fixture.config(admin_token='ADMIN')
log_fix = self.useFixture(fixtures.FakeLogger()) log_fix = self.useFixture(fixtures.FakeLogger())
headers = {middleware.AUTH_TOKEN_HEADER: 'ADMIN'} headers = {middleware.AUTH_TOKEN_HEADER: 'ADMIN'}
environ = {middleware.core.CONTEXT_ENV: {'is_admin': True}} req = self._do_middleware_request(headers=headers)
self._do_middleware_request(headers=headers, extra_environ=environ) self.assertTrue(req.environ[middleware.CONTEXT_ENV]['is_admin'])
self.assertNotIn('Invalid user token', log_fix.output) 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)

View File

@ -59,21 +59,6 @@ class IdentityTestCaseStaticAdminToken(test_v3.RestfulTestCase):
self.get('/users', token=CONF.admin_token, self.get('/users', token=CONF.admin_token,
expected_status=exception.Unauthorized.code) 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): class IdentityTestCase(test_v3.RestfulTestCase):
"""Test users and groups.""" """Test users and groups."""

View File

@ -6,3 +6,13 @@ other:
The removed code included ``keystone.common.kvs`` configuration options for the KVS code, 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``. unit tests, and the KVS token persistence driver ``keystone.token.persistence.backends.kvs``.
All associated documentation has been removed. All associated documentation has been removed.
- >
[`blueprint removed-as-of-pike <https://blueprints.launchpad.net/keystone/+spec/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``).