Verify token binding in auth_token middleware

The server side has had token bind checking implemented for a while. Now
that it is possible to generate bound tokens auth_token middleware
should be capable of verifying them.

Change-Id: I4f9c5855ab3102333b0738864c506e2501bf9c7e
This commit is contained in:
Jamie Lennox
2013-10-03 17:24:19 +10:00
parent 4ffaf7c0a5
commit 3beec3e2ea
2 changed files with 276 additions and 0 deletions

View File

@@ -77,6 +77,8 @@ class Examples(fixtures.Fixture):
with open(self.SIGNING_CERT_FILE) as f:
self.SIGNING_CERT = f.read()
self.KERBEROS_BIND = 'USER@REALM'
self.SIGNING_KEY_FILE = os.path.join(KEYDIR, 'signing_key.pem')
with open(self.SIGNING_KEY_FILE) as f:
self.SIGNING_KEY = f.read()
@@ -88,10 +90,14 @@ class Examples(fixtures.Fixture):
self.UUID_TOKEN_DEFAULT = "ec6c0710ec2f471498484c1b53ab4f9d"
self.UUID_TOKEN_NO_SERVICE_CATALOG = '8286720fbe4941e69fa8241723bb02df'
self.UUID_TOKEN_UNSCOPED = '731f903721c14827be7b2dc912af7776'
self.UUID_TOKEN_BIND = '3fc54048ad64405c98225ce0897af7c5'
self.UUID_TOKEN_UNKNOWN_BIND = '8885fdf4d42e4fb9879e6379fa1eaf48'
self.VALID_DIABLO_TOKEN = 'b0cf19b55dbb4f20a6ee18e6c6cf1726'
self.v3_UUID_TOKEN_DEFAULT = '5603457654b346fdbb93437bfe76f2f1'
self.v3_UUID_TOKEN_UNSCOPED = 'd34835fdaec447e695a0a024d84f8d79'
self.v3_UUID_TOKEN_DOMAIN_SCOPED = 'e8a7b63aaa4449f38f0c5c05c3581792'
self.v3_UUID_TOKEN_BIND = '2f61f73e1c854cbb9534c487f9bd63c2'
self.v3_UUID_TOKEN_UNKNOWN_BIND = '7ed9781b62cd4880b8d8c6788ab1d1e2'
self.REVOKED_TOKEN_HASH = utils.hash_signed_token(self.REVOKED_TOKEN)
self.REVOKED_TOKEN_LIST = (
@@ -209,6 +215,50 @@ class Examples(fixtures.Fixture):
}
},
},
self.UUID_TOKEN_BIND: {
'access': {
'token': {
'bind': {'kerberos': self.KERBEROS_BIND},
'id': self.UUID_TOKEN_BIND,
'expires': '2020-01-01T00:00:10.000123Z',
'tenant': {
'id': 'tenant_id1',
'name': 'tenant_name1',
},
},
'user': {
'id': 'user_id1',
'name': 'user_name1',
'roles': [
{'name': 'role1'},
{'name': 'role2'},
],
},
'serviceCatalog': {}
},
},
self.UUID_TOKEN_UNKNOWN_BIND: {
'access': {
'token': {
'bind': {'FOO': 'BAR'},
'id': self.UUID_TOKEN_UNKNOWN_BIND,
'expires': '2020-01-01T00:00:10.000123Z',
'tenant': {
'id': 'tenant_id1',
'name': 'tenant_name1',
},
},
'user': {
'id': 'user_id1',
'name': 'user_name1',
'roles': [
{'name': 'role1'},
{'name': 'role2'},
],
},
'serviceCatalog': {}
},
},
self.v3_UUID_TOKEN_DEFAULT: {
'token': {
'expires_at': '2020-01-01T00:00:10.000123Z',
@@ -328,6 +378,60 @@ class Examples(fixtures.Fixture):
'catalog': {}
}
},
self.v3_UUID_TOKEN_BIND: {
'token': {
'bind': {'kerberos': self.KERBEROS_BIND},
'expires_at': '2020-01-01T00:00:10.000123Z',
'user': {
'id': 'user_id1',
'name': 'user_name1',
'domain': {
'id': 'domain_id1',
'name': 'domain_name1'
}
},
'project': {
'id': 'tenant_id1',
'name': 'tenant_name1',
'domain': {
'id': 'domain_id1',
'name': 'domain_name1'
}
},
'roles': [
{'name': 'role1', 'id': 'Role1'},
{'name': 'role2', 'id': 'Role2'},
],
'catalog': {}
}
},
self.v3_UUID_TOKEN_UNKNOWN_BIND: {
'token': {
'bind': {'FOO': 'BAR'},
'expires_at': '2020-01-01T00:00:10.000123Z',
'user': {
'id': 'user_id1',
'name': 'user_name1',
'domain': {
'id': 'domain_id1',
'name': 'domain_name1'
}
},
'project': {
'id': 'tenant_id1',
'name': 'tenant_name1',
'domain': {
'id': 'domain_id1',
'name': 'domain_name1'
}
},
'roles': [
{'name': 'role1', 'id': 'Role1'},
{'name': 'role2', 'id': 'Role2'},
],
'catalog': {}
}
},
}
self.JSON_TOKEN_RESPONSES = dict([(k, jsonutils.dumps(v)) for k, v in

View File

@@ -247,6 +247,7 @@ class BaseAuthTokenMiddlewareTest(testtools.TestCase):
'auth_uri': 'https://keystone.example.com:1234',
}
self.auth_version = auth_version
self.response_status = None
self.response_headers = None
@@ -902,6 +903,170 @@ class CommonAuthTokenMiddlewareTest(object):
self.assert_valid_request_200(self.token_dict['uuid_token_default'],
with_catalog=False)
def assert_kerberos_bind(self, token, bind_level,
use_kerberos=True, success=True):
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'] = token
if use_kerberos:
if use_kerberos is True:
req.environ['REMOTE_USER'] = self.examples.KERBEROS_BIND
else:
req.environ['REMOTE_USER'] = use_kerberos
req.environ['AUTH_TYPE'] = 'Negotiate'
body = self.middleware(req.environ, self.start_fake_response)
if success:
self.assertEqual(self.response_status, 200)
self.assertEqual(body, ['SUCCESS'])
self.assertIn('keystone.token_info', req.environ)
self.assert_valid_last_url(token)
else:
self.assertEqual(self.response_status, 401)
self.assertEqual(self.response_headers['WWW-Authenticate'],
"Keystone uri='https://keystone.example.com:1234'"
)
def test_uuid_bind_token_disabled_with_kerb_user(self):
for use_kerberos in [True, False]:
self.assert_kerberos_bind(self.token_dict['uuid_token_bind'],
bind_level='disabled',
use_kerberos=use_kerberos,
success=True)
def test_uuid_bind_token_disabled_with_incorrect_ticket(self):
self.assert_kerberos_bind(self.token_dict['uuid_token_bind'],
bind_level='kerberos',
use_kerberos='ronald@MCDONALDS.COM',
success=False)
def test_uuid_bind_token_permissive_with_kerb_user(self):
self.assert_kerberos_bind(self.token_dict['uuid_token_bind'],
bind_level='permissive',
use_kerberos=True,
success=True)
def test_uuid_bind_token_permissive_without_kerb_user(self):
self.assert_kerberos_bind(self.token_dict['uuid_token_bind'],
bind_level='permissive',
use_kerberos=False,
success=False)
def test_uuid_bind_token_permissive_with_unknown_bind(self):
token = self.token_dict['uuid_token_unknown_bind']
for use_kerberos in [True, False]:
self.assert_kerberos_bind(token,
bind_level='permissive',
use_kerberos=use_kerberos,
success=True)
def test_uuid_bind_token_permissive_with_incorrect_ticket(self):
self.assert_kerberos_bind(self.token_dict['uuid_token_bind'],
bind_level='kerberos',
use_kerberos='ronald@MCDONALDS.COM',
success=False)
def test_uuid_bind_token_strict_with_kerb_user(self):
self.assert_kerberos_bind(self.token_dict['uuid_token_bind'],
bind_level='strict',
use_kerberos=True,
success=True)
def test_uuid_bind_token_strict_with_kerbout_user(self):
self.assert_kerberos_bind(self.token_dict['uuid_token_bind'],
bind_level='strict',
use_kerberos=False,
success=False)
def test_uuid_bind_token_strict_with_unknown_bind(self):
token = self.token_dict['uuid_token_unknown_bind']
for use_kerberos in [True, False]:
self.assert_kerberos_bind(token,
bind_level='strict',
use_kerberos=use_kerberos,
success=False)
def test_uuid_bind_token_required_with_kerb_user(self):
self.assert_kerberos_bind(self.token_dict['uuid_token_bind'],
bind_level='required',
use_kerberos=True,
success=True)
def test_uuid_bind_token_required_without_kerb_user(self):
self.assert_kerberos_bind(self.token_dict['uuid_token_bind'],
bind_level='required',
use_kerberos=False,
success=False)
def test_uuid_bind_token_required_with_unknown_bind(self):
token = self.token_dict['uuid_token_unknown_bind']
for use_kerberos in [True, False]:
self.assert_kerberos_bind(token,
bind_level='required',
use_kerberos=use_kerberos,
success=False)
def test_uuid_bind_token_required_without_bind(self):
for use_kerberos in [True, False]:
self.assert_kerberos_bind(self.token_dict['uuid_token_default'],
bind_level='required',
use_kerberos=use_kerberos,
success=False)
def test_uuid_bind_token_named_kerberos_with_kerb_user(self):
self.assert_kerberos_bind(self.token_dict['uuid_token_bind'],
bind_level='kerberos',
use_kerberos=True,
success=True)
def test_uuid_bind_token_named_kerberos_without_kerb_user(self):
self.assert_kerberos_bind(self.token_dict['uuid_token_bind'],
bind_level='kerberos',
use_kerberos=False,
success=False)
def test_uuid_bind_token_named_kerberos_with_unknown_bind(self):
token = self.token_dict['uuid_token_unknown_bind']
for use_kerberos in [True, False]:
self.assert_kerberos_bind(token,
bind_level='kerberos',
use_kerberos=use_kerberos,
success=False)
def test_uuid_bind_token_named_kerberos_without_bind(self):
for use_kerberos in [True, False]:
self.assert_kerberos_bind(self.token_dict['uuid_token_default'],
bind_level='kerberos',
use_kerberos=use_kerberos,
success=False)
def test_uuid_bind_token_named_kerberos_with_incorrect_ticket(self):
self.assert_kerberos_bind(self.token_dict['uuid_token_bind'],
bind_level='kerberos',
use_kerberos='ronald@MCDONALDS.COM',
success=False)
def test_uuid_bind_token_with_unknown_named_FOO(self):
token = self.token_dict['uuid_token_bind']
for use_kerberos in [True, False]:
self.assert_kerberos_bind(token,
bind_level='FOO',
use_kerberos=use_kerberos,
success=False)
class CertDownloadMiddlewareTest(BaseAuthTokenMiddlewareTest,
testresources.ResourcedTestCase):
@@ -1043,6 +1208,8 @@ class v2AuthTokenMiddlewareTest(BaseAuthTokenMiddlewareTest,
self.token_dict = {
'uuid_token_default': self.examples.UUID_TOKEN_DEFAULT,
'uuid_token_unscoped': self.examples.UUID_TOKEN_UNSCOPED,
'uuid_token_bind': self.examples.UUID_TOKEN_BIND,
'uuid_token_unknown_bind': self.examples.UUID_TOKEN_UNKNOWN_BIND,
'signed_token_scoped': self.examples.SIGNED_TOKEN_SCOPED,
'signed_token_scoped_expired':
self.examples.SIGNED_TOKEN_SCOPED_EXPIRED,
@@ -1069,6 +1236,8 @@ class v2AuthTokenMiddlewareTest(BaseAuthTokenMiddlewareTest,
for token in (self.examples.UUID_TOKEN_DEFAULT,
self.examples.UUID_TOKEN_UNSCOPED,
self.examples.UUID_TOKEN_BIND,
self.examples.UUID_TOKEN_UNKNOWN_BIND,
self.examples.UUID_TOKEN_NO_SERVICE_CATALOG):
httpretty.register_uri(httpretty.GET,
"%s/v2.0/tokens/%s" % (BASE_URI, token),
@@ -1223,6 +1392,9 @@ class v3AuthTokenMiddlewareTest(BaseAuthTokenMiddlewareTest,
self.token_dict = {
'uuid_token_default': self.examples.v3_UUID_TOKEN_DEFAULT,
'uuid_token_unscoped': self.examples.v3_UUID_TOKEN_UNSCOPED,
'uuid_token_bind': self.examples.v3_UUID_TOKEN_BIND,
'uuid_token_unknown_bind':
self.examples.v3_UUID_TOKEN_UNKNOWN_BIND,
'signed_token_scoped': self.examples.SIGNED_v3_TOKEN_SCOPED,
'signed_token_scoped_expired':
self.examples.SIGNED_TOKEN_SCOPED_EXPIRED,