Only confirm token binding on one token
When using service tokens and kerberos, the REMOTE_USER will be the service user, and hence the token bind confirmation will always fail to validate the client user's token, making it impossible to use token binding with service tokens. This patch adds a test to expose the issue and fixes the problem by only validating the token binding for the service token when both tokens are in the request. Change-Id: I7ba2283e8e58b89f1e42bc738c7e77284321e3a5 Closes-bug: #1413433
This commit is contained in:
parent
53335aaf49
commit
5ba835f3e1
|
@ -491,7 +491,8 @@ class BaseAuthProtocol(object):
|
|||
try:
|
||||
data, user_auth_ref = self._do_fetch_token(request.user_token)
|
||||
self._validate_token(user_auth_ref)
|
||||
self._confirm_token_bind(user_auth_ref, request)
|
||||
if not request.service_token:
|
||||
self._confirm_token_bind(user_auth_ref, request)
|
||||
except ksm_exceptions.InvalidToken:
|
||||
self.log.info(_LI('Invalid user token'))
|
||||
request.user_token_valid = False
|
||||
|
|
|
@ -2049,6 +2049,35 @@ class CommonCompositeAuthTests(object):
|
|||
expected_status=403)
|
||||
self.assertEqual(FakeApp.FORBIDDEN, resp.body)
|
||||
|
||||
def assert_kerberos_composite_bind(self, user_token, service_token,
|
||||
bind_level):
|
||||
conf = {
|
||||
'enforce_token_bind': bind_level,
|
||||
'auth_version': self.auth_version,
|
||||
}
|
||||
self.set_middleware(conf=conf)
|
||||
|
||||
req = webob.Request.blank('/')
|
||||
req.headers['X-Auth-Token'] = user_token
|
||||
req.headers['X-Service-Token'] = service_token
|
||||
|
||||
req.environ['REMOTE_USER'] = self.examples.SERVICE_KERBEROS_BIND
|
||||
req.environ['AUTH_TYPE'] = 'Negotiate'
|
||||
|
||||
resp = req.get_response(self.middleware)
|
||||
|
||||
self.assertEqual(200, resp.status_int)
|
||||
self.assertEqual(FakeApp.SUCCESS, resp.body)
|
||||
self.assertIn('keystone.token_info', req.environ)
|
||||
|
||||
def test_composite_auth_with_bind(self):
|
||||
token = self.token_dict['uuid_token_bind']
|
||||
service_token = self.token_dict['uuid_service_token_bind']
|
||||
|
||||
self.assert_kerberos_composite_bind(token,
|
||||
service_token,
|
||||
bind_level='required')
|
||||
|
||||
|
||||
class v2CompositeAuthTests(BaseAuthTokenMiddlewareTest,
|
||||
CommonCompositeAuthTests,
|
||||
|
@ -2069,9 +2098,13 @@ class v2CompositeAuthTests(BaseAuthTokenMiddlewareTest,
|
|||
|
||||
uuid_token_default = self.examples.UUID_TOKEN_DEFAULT
|
||||
uuid_service_token_default = self.examples.UUID_SERVICE_TOKEN_DEFAULT
|
||||
uuid_token_bind = self.examples.UUID_TOKEN_BIND
|
||||
uuid_service_token_bind = self.examples.UUID_SERVICE_TOKEN_BIND
|
||||
self.token_dict = {
|
||||
'uuid_token_default': uuid_token_default,
|
||||
'uuid_service_token_default': uuid_service_token_default,
|
||||
'uuid_token_bind': uuid_token_bind,
|
||||
'uuid_service_token_bind': uuid_service_token_bind,
|
||||
}
|
||||
|
||||
self.requests_mock.get(BASE_URI,
|
||||
|
@ -2086,7 +2119,9 @@ class v2CompositeAuthTests(BaseAuthTokenMiddlewareTest,
|
|||
status_code=200)
|
||||
|
||||
for token in (self.examples.UUID_TOKEN_DEFAULT,
|
||||
self.examples.UUID_SERVICE_TOKEN_DEFAULT,):
|
||||
self.examples.UUID_SERVICE_TOKEN_DEFAULT,
|
||||
self.examples.UUID_TOKEN_BIND,
|
||||
self.examples.UUID_SERVICE_TOKEN_BIND):
|
||||
text = self.examples.JSON_TOKEN_RESPONSES[token]
|
||||
self.requests_mock.get('%s/v2.0/tokens/%s' % (BASE_URI, token),
|
||||
text=text)
|
||||
|
@ -2120,9 +2155,13 @@ class v3CompositeAuthTests(BaseAuthTokenMiddlewareTest,
|
|||
|
||||
uuid_token_default = self.examples.v3_UUID_TOKEN_DEFAULT
|
||||
uuid_serv_token_default = self.examples.v3_UUID_SERVICE_TOKEN_DEFAULT
|
||||
uuid_token_bind = self.examples.v3_UUID_TOKEN_BIND
|
||||
uuid_service_token_bind = self.examples.v3_UUID_SERVICE_TOKEN_BIND
|
||||
self.token_dict = {
|
||||
'uuid_token_default': uuid_token_default,
|
||||
'uuid_service_token_default': uuid_serv_token_default,
|
||||
'uuid_token_bind': uuid_token_bind,
|
||||
'uuid_service_token_bind': uuid_service_token_bind,
|
||||
}
|
||||
|
||||
self.requests_mock.get(BASE_URI, json=VERSION_LIST_v3, status_code=300)
|
||||
|
|
|
@ -105,6 +105,7 @@ class Examples(fixtures.Fixture):
|
|||
self.SIGNING_CERT = f.read()
|
||||
|
||||
self.KERBEROS_BIND = 'USER@REALM'
|
||||
self.SERVICE_KERBEROS_BIND = 'SERVICE_USER@SERVICE_REALM'
|
||||
|
||||
self.SIGNING_KEY_FILE = os.path.join(KEYDIR, 'signing_key.pem')
|
||||
with open(self.SIGNING_KEY_FILE) as f:
|
||||
|
@ -127,7 +128,9 @@ class Examples(fixtures.Fixture):
|
|||
self.v3_UUID_TOKEN_UNKNOWN_BIND = '7ed9781b62cd4880b8d8c6788ab1d1e2'
|
||||
|
||||
self.UUID_SERVICE_TOKEN_DEFAULT = 'fe4c0710ec2f492748596c1b53ab124'
|
||||
self.UUID_SERVICE_TOKEN_BIND = '5e43439613d34a13a7e03b2762bd08ab'
|
||||
self.v3_UUID_SERVICE_TOKEN_DEFAULT = 'g431071bbc2f492748596c1b53cb229'
|
||||
self.v3_UUID_SERVICE_TOKEN_BIND = 'be705e4426d0449a89e35ae21c380a05'
|
||||
|
||||
revoked_token = self.REVOKED_TOKEN
|
||||
if isinstance(revoked_token, six.text_type):
|
||||
|
@ -321,6 +324,17 @@ class Examples(fixtures.Fixture):
|
|||
token['access']['token']['bind'] = {'kerberos': self.KERBEROS_BIND}
|
||||
self.TOKEN_RESPONSES[self.UUID_TOKEN_BIND] = token
|
||||
|
||||
token = fixture.V2Token(token_id=self.UUID_SERVICE_TOKEN_BIND,
|
||||
tenant_id=SERVICE_PROJECT_ID,
|
||||
tenant_name=SERVICE_PROJECT_NAME,
|
||||
user_id=SERVICE_USER_ID,
|
||||
user_name=SERVICE_USER_NAME)
|
||||
token.add_role(SERVICE_ROLE_NAME1)
|
||||
token.add_role(SERVICE_ROLE_NAME2)
|
||||
token['access']['token']['bind'] = {
|
||||
'kerberos': self.SERVICE_KERBEROS_BIND}
|
||||
self.TOKEN_RESPONSES[self.UUID_SERVICE_TOKEN_BIND] = token
|
||||
|
||||
token = fixture.V2Token(token_id=self.UUID_TOKEN_UNKNOWN_BIND,
|
||||
tenant_id=PROJECT_ID,
|
||||
tenant_name=PROJECT_NAME,
|
||||
|
@ -405,6 +419,21 @@ class Examples(fixtures.Fixture):
|
|||
token['token']['bind'] = {'kerberos': self.KERBEROS_BIND}
|
||||
self.TOKEN_RESPONSES[self.v3_UUID_TOKEN_BIND] = token
|
||||
|
||||
token = fixture.V3Token(user_id=SERVICE_USER_ID,
|
||||
user_name=SERVICE_USER_NAME,
|
||||
user_domain_id=SERVICE_DOMAIN_ID,
|
||||
user_domain_name=SERVICE_DOMAIN_NAME,
|
||||
project_id=SERVICE_PROJECT_ID,
|
||||
project_name=SERVICE_PROJECT_NAME,
|
||||
project_domain_id=SERVICE_DOMAIN_ID,
|
||||
project_domain_name=SERVICE_DOMAIN_NAME)
|
||||
token.add_role(name=SERVICE_ROLE_NAME1)
|
||||
token.add_role(name=SERVICE_ROLE_NAME2)
|
||||
svc = token.add_service(self.SERVICE_TYPE)
|
||||
svc.add_endpoint('public', self.SERVICE_URL)
|
||||
token['token']['bind'] = {'kerberos': self.SERVICE_KERBEROS_BIND}
|
||||
self.TOKEN_RESPONSES[self.v3_UUID_SERVICE_TOKEN_BIND] = token
|
||||
|
||||
token = fixture.V3Token(user_id=USER_ID,
|
||||
user_name=USER_NAME,
|
||||
user_domain_id=DOMAIN_ID,
|
||||
|
|
Loading…
Reference in New Issue