populate request context with X.509 tokenless cred information

Fixes X.509 tokenless auth by properly populating the request context
with the necessary credential information. Since Stein release, RBAC
has been using the credential information from the Keystone request
context instead of the authentication context. Therefore, we'll need
to populate the request context with the necessary credential
information from the X.509 tokenless authentication context.

Closes-Bug: 1811605
Change-Id: I170a91e9ac36990d1e7ec4165dd0337b8f06a938
This commit is contained in:
Guang Yee 2019-02-08 16:56:40 -08:00
parent 374b03b015
commit 1b261e8bec
3 changed files with 67 additions and 1 deletions

View File

@ -435,7 +435,29 @@ class AuthContextMiddleware(provider_api.ProviderAPIMixin,
elif self._validate_trusted_issuer(request):
auth_context = self._build_tokenless_auth_context(request)
# NOTE(gyee): we are no longer using auth_context when formulating
# the credentials for RBAC. Instead, we are using the (Oslo)
# request context. So we'll need to set all the necessary
# credential attributes in the request context here.
token_attributes = frozenset((
'user_id', 'project_id',
'domain_id', 'user_domain_id',
'project_domain_id', 'user_domain_name',
'project_domain_name', 'roles', 'is_admin',
'project_name', 'domain_name', 'system_scope',
'is_admin_project', 'service_user_id',
'service_user_name', 'service_project_id',
'service_project_name', 'service_user_domain_id'
'service_user_domain_name', 'service_project_domain_id',
'service_project_domain_name', 'service_roles'))
for attr in token_attributes:
if attr in auth_context:
setattr(request_context, attr, auth_context[attr])
# NOTE(gyee): request_context.token_reference is always
# expecting a 'token' key regardless. But in the case of X.509
# tokenless auth, we don't need a token. So setting it to None
# should be suffice.
request_context.token_reference = {'token': None}
else:
# There is either no auth token in the request or the certificate
# issuer is not trusted. No auth context will be set. This

View File

@ -21,6 +21,7 @@ from six.moves import http_client
import webtest
from keystone.common import authorization
from keystone.common import context as keystone_context
from keystone.common import provider_api
from keystone.common import tokenless_auth
import keystone.conf
@ -223,6 +224,14 @@ class AuthContextMiddlewareTest(test_backend_sql.SqlTests,
else:
self.assertEqual(self.user['id'], context['user_id'])
def _assert_tokenless_request_context(self, request_context,
ephemeral_user=False):
self.assertIsNotNone(request_context)
self.assertEqual(self.project_id, request_context.project_id)
self.assertIn(self.role_name, request_context.roles)
if not ephemeral_user:
self.assertEqual(self.user['id'], request_context.user_id)
def test_context_already_exists(self):
stub_value = uuid.uuid4().hex
env = {authorization.AUTH_CONTEXT_ENV: stub_value}
@ -317,6 +326,8 @@ class AuthContextMiddlewareTest(test_backend_sql.SqlTests,
req = self._do_middleware_request(extra_environ=env)
context = req.environ.get(authorization.AUTH_CONTEXT_ENV)
self._assert_tokenless_auth_context(context)
request_context = req.environ.get(keystone_context.REQUEST_CONTEXT_ENV)
self._assert_tokenless_request_context(request_context)
def test_proj_scope_with_proj_id_only_success(self):
env = {}
@ -331,6 +342,8 @@ class AuthContextMiddlewareTest(test_backend_sql.SqlTests,
req = self._do_middleware_request(extra_environ=env)
context = req.environ.get(authorization.AUTH_CONTEXT_ENV)
self._assert_tokenless_auth_context(context)
request_context = req.environ.get(keystone_context.REQUEST_CONTEXT_ENV)
self._assert_tokenless_request_context(request_context)
def test_proj_scope_with_proj_name_and_proj_dom_id_success(self):
env = {}
@ -346,6 +359,8 @@ class AuthContextMiddlewareTest(test_backend_sql.SqlTests,
req = self._do_middleware_request(extra_environ=env)
context = req.environ.get(authorization.AUTH_CONTEXT_ENV)
self._assert_tokenless_auth_context(context)
request_context = req.environ.get(keystone_context.REQUEST_CONTEXT_ENV)
self._assert_tokenless_request_context(request_context)
def test_proj_scope_with_proj_name_and_proj_dom_name_success(self):
env = {}
@ -361,6 +376,8 @@ class AuthContextMiddlewareTest(test_backend_sql.SqlTests,
req = self._do_middleware_request(extra_environ=env)
context = req.environ.get(authorization.AUTH_CONTEXT_ENV)
self._assert_tokenless_auth_context(context)
request_context = req.environ.get(keystone_context.REQUEST_CONTEXT_ENV)
self._assert_tokenless_request_context(request_context)
def test_proj_scope_with_proj_name_only_fail(self):
env = {}
@ -390,6 +407,8 @@ class AuthContextMiddlewareTest(test_backend_sql.SqlTests,
req = self._do_middleware_request(extra_environ=env)
context = req.environ.get(authorization.AUTH_CONTEXT_ENV)
self._assert_tokenless_auth_context(context)
request_context = req.environ.get(keystone_context.REQUEST_CONTEXT_ENV)
self._assert_tokenless_request_context(request_context)
def test_mapping_with_userid_and_domainname_success(self):
env = {}
@ -405,6 +424,8 @@ class AuthContextMiddlewareTest(test_backend_sql.SqlTests,
req = self._do_middleware_request(extra_environ=env)
context = req.environ.get(authorization.AUTH_CONTEXT_ENV)
self._assert_tokenless_auth_context(context)
request_context = req.environ.get(keystone_context.REQUEST_CONTEXT_ENV)
self._assert_tokenless_request_context(request_context)
def test_mapping_with_username_and_domainid_success(self):
env = {}
@ -420,6 +441,8 @@ class AuthContextMiddlewareTest(test_backend_sql.SqlTests,
req = self._do_middleware_request(extra_environ=env)
context = req.environ.get(authorization.AUTH_CONTEXT_ENV)
self._assert_tokenless_auth_context(context)
request_context = req.environ.get(keystone_context.REQUEST_CONTEXT_ENV)
self._assert_tokenless_request_context(request_context)
def test_only_domain_name_fail(self):
env = {}
@ -474,6 +497,8 @@ class AuthContextMiddlewareTest(test_backend_sql.SqlTests,
req = self._do_middleware_request(extra_environ=env)
context = req.environ.get(authorization.AUTH_CONTEXT_ENV)
self._assert_tokenless_auth_context(context)
request_context = req.environ.get(keystone_context.REQUEST_CONTEXT_ENV)
self._assert_tokenless_request_context(request_context)
def test_domain_disable_fail(self):
env = {}
@ -543,6 +568,9 @@ class AuthContextMiddlewareTest(test_backend_sql.SqlTests,
req = self._do_middleware_request(extra_environ=env)
context = req.environ.get(authorization.AUTH_CONTEXT_ENV)
self._assert_tokenless_auth_context(context, ephemeral_user=True)
request_context = req.environ.get(keystone_context.REQUEST_CONTEXT_ENV)
self._assert_tokenless_request_context(request_context,
ephemeral_user=True)
def test_ephemeral_with_default_user_type_success(self):
env = {}
@ -564,6 +592,9 @@ class AuthContextMiddlewareTest(test_backend_sql.SqlTests,
req = self._do_middleware_request(extra_environ=env)
context = req.environ.get(authorization.AUTH_CONTEXT_ENV)
self._assert_tokenless_auth_context(context, ephemeral_user=True)
request_context = req.environ.get(keystone_context.REQUEST_CONTEXT_ENV)
self._assert_tokenless_request_context(request_context,
ephemeral_user=True)
def test_ephemeral_any_user_success(self):
"""Verify ephemeral user does not need a specified user.
@ -585,6 +616,9 @@ class AuthContextMiddlewareTest(test_backend_sql.SqlTests,
req = self._do_middleware_request(extra_environ=env)
context = req.environ.get(authorization.AUTH_CONTEXT_ENV)
self._assert_tokenless_auth_context(context, ephemeral_user=True)
request_context = req.environ.get(keystone_context.REQUEST_CONTEXT_ENV)
self._assert_tokenless_request_context(request_context,
ephemeral_user=True)
def test_ephemeral_invalid_scope_fail(self):
env = {}

View File

@ -0,0 +1,10 @@
---
fixes:
- |
[`bug 1811605 <https://bugs.launchpad.net/keystone/+bug/1811605>`_]
Fixes X.509 tokenless auth by properly populating the request context
with the necessary credential information. Since Stein release, RBAC
has been using the credential information from the Keystone request
context instead of the authentication context. Therefore, we'll need
to populate the request context with the necessary credential
information from the X.509 tokenless authentication context.