Merge "Allow full v3 authentication"

This commit is contained in:
Jenkins 2015-03-12 11:05:44 +00:00 committed by Gerrit Code Review
commit 1727a993b1
7 changed files with 98 additions and 47 deletions

View File

@ -76,7 +76,7 @@ class TestDefaultProjectId (base.BaseIdentityV3AdminTest):
# create a new client with user's credentials (NOTE: unscoped token!)
creds = auth.KeystoneV3Credentials(username=user_name,
password=user_name,
domain_name=dom_name)
user_domain_name=dom_name)
auth_provider = manager.get_auth_provider(creds)
creds = auth_provider.fill_credentials()
admin_client = clients.Manager(credentials=creds)

View File

@ -144,11 +144,11 @@ class RolesV3TestJSON(base.BaseIdentityV3AdminTest):
self.client.add_group_user(self.group_body['id'], self.user_body['id'])
self.addCleanup(self.client.delete_group_user,
self.group_body['id'], self.user_body['id'])
body = self.token.auth(user=self.user_body['id'],
body = self.token.auth(user_id=self.user_body['id'],
password=self.u_password,
user_domain=self.domain['name'],
project=self.project['name'],
project_domain=self.domain['name'])
user_domain_name=self.domain['name'],
project_name=self.project['name'],
project_domain_name=self.domain['name'])
roles = body['token']['roles']
self.assertEqual(len(roles), 1)
self.assertEqual(roles[0]['id'], self.role['id'])

View File

@ -36,7 +36,8 @@ class TokensV3TestJSON(base.BaseIdentityV3AdminTest):
email=u_email)
self.addCleanup(self.client.delete_user, user['id'])
# Perform Authentication
resp = self.token.auth(user['id'], u_password).response
resp = self.token.auth(user_id=user['id'],
password=u_password).response
subject_token = resp['x-subject-token']
# Perform GET Token
token_details = self.client.get_token(subject_token)
@ -87,7 +88,7 @@ class TokensV3TestJSON(base.BaseIdentityV3AdminTest):
role['id'])
# Get an unscoped token.
token_auth = self.token.auth(user=user['id'],
token_auth = self.token.auth(user_id=user['id'],
password=user_password)
token_id = token_auth.response['x-subject-token']
@ -110,8 +111,8 @@ class TokensV3TestJSON(base.BaseIdentityV3AdminTest):
# Use the unscoped token to get a scoped token.
token_auth = self.token.auth(token=token_id,
project=project1_name,
project_domain='Default')
project_name=project1_name,
project_domain_name='Default')
token1_id = token_auth.response['x-subject-token']
self.assertEqual(orig_expires_at, token_auth['token']['expires_at'],
@ -140,8 +141,8 @@ class TokensV3TestJSON(base.BaseIdentityV3AdminTest):
# Now get another scoped token using the unscoped token.
token_auth = self.token.auth(token=token_id,
project=project2_name,
project_domain='Default')
project_name=project2_name,
project_domain_name='Default')
self.assertEqual(project2['id'],
token_auth['token']['project']['id'])

View File

@ -79,7 +79,8 @@ class UsersV3TestJSON(base.BaseIdentityV3AdminTest):
new_password = data_utils.rand_name('pass1')
self.client.update_user_password(user['id'], new_password,
original_password)
resp = self.token.auth(user['id'], new_password).response
resp = self.token.auth(user_id=user['id'],
password=new_password).response
subject_token = resp['x-subject-token']
# Perform GET Token to verify and confirm password is updated
token_details = self.client.get_token(subject_token)

View File

@ -328,11 +328,17 @@ class KeystoneV3AuthProvider(KeystoneAuthProvider):
def _auth_params(self):
return dict(
user=self.credentials.username,
user_id=self.credentials.user_id,
username=self.credentials.username,
password=self.credentials.password,
project=self.credentials.tenant_name,
user_domain=self.credentials.user_domain_name,
project_domain=self.credentials.project_domain_name,
project_id=self.credentials.project_id,
project_name=self.credentials.project_name,
user_domain_id=self.credentials.user_domain_id,
user_domain_name=self.credentials.user_domain_name,
project_domain_id=self.credentials.project_domain_id,
project_domain_name=self.credentials.project_domain_name,
domain_id=self.credentials.domain_id,
domain_name=self.credentials.domain_name,
auth_data=True)
def _fill_credentials(self, auth_data_body):
@ -579,7 +585,7 @@ class KeystoneV3Credentials(Credentials):
Credentials suitable for the Keystone Identity V3 API
"""
ATTRIBUTES = ['domain_name', 'password', 'tenant_name', 'username',
ATTRIBUTES = ['domain_id', 'domain_name', 'password', 'username',
'project_domain_id', 'project_domain_name', 'project_id',
'project_name', 'tenant_id', 'tenant_name', 'user_domain_id',
'user_domain_name', 'user_id']
@ -625,6 +631,8 @@ class KeystoneV3Credentials(Credentials):
- None
- Project id (optional domain)
- Project name and its domain id/name
- Domain id
- Domain name
"""
valid_user_domain = any(
[self.user_domain_id is not None,
@ -635,11 +643,16 @@ class KeystoneV3Credentials(Credentials):
valid_user = any(
[self.user_id is not None,
self.username is not None and valid_user_domain])
valid_project = any(
valid_project_scope = any(
[self.project_name is None and self.project_id is None,
self.project_id is not None,
self.project_name is not None and valid_project_domain])
return all([self.password is not None, valid_user, valid_project])
valid_domain_scope = any(
[self.domain_id is None and self.domain_name is None,
self.domain_id or self.domain_name])
return all([self.password is not None,
valid_user,
valid_project_scope and valid_domain_scope])
IDENTITY_VERSION = {'v2': (KeystoneV2Credentials, KeystoneV2AuthProvider),

View File

@ -37,22 +37,30 @@ class V3TokenClientJSON(rest_client.RestClient):
self.auth_url = auth_url
def auth(self, user=None, password=None, project=None, user_type='id',
user_domain=None, project_domain=None, token=None):
def auth(self, user_id=None, username=None, password=None, project_id=None,
project_name=None, user_domain_id=None, user_domain_name=None,
project_domain_id=None, project_domain_name=None, domain_id=None,
domain_name=None, token=None):
"""
:param user: user id or name, as specified in user_type
:param user_domain: the user domain
:param project_domain: the project domain
:param user_id: user id
:param username: user name
:param user_domain_id: the user domain id
:param user_domain_name: the user domain name
:param project_domain_id: the project domain id
:param project_domain_name: the project domain name
:param domain_id: a domain id to scope to
:param domain_name: a domain name to scope to
:param project_id: a project id to scope to
:param project_name: a project name to scope to
:param token: a token to re-scope.
Accepts different combinations of credentials. Restrictions:
- project and domain are only name (no id)
Accepts different combinations of credentials.
Sample sample valid combinations:
- token
- token, project, project_domain
- token, project_name, project_domain_id
- user_id, password
- username, password, user_domain
- username, password, project, user_domain, project_domain
- username, password, user_domain_id
- username, password, project_name, user_domain_id, project_domain_id
Validation is left to the server side.
"""
creds = {
@ -68,25 +76,45 @@ class V3TokenClientJSON(rest_client.RestClient):
id_obj['token'] = {
'id': token
}
if user and password:
if (user_id or username) and password:
id_obj['methods'].append('password')
id_obj['password'] = {
'user': {
'password': password,
}
}
if user_type == 'id':
id_obj['password']['user']['id'] = user
if user_id:
id_obj['password']['user']['id'] = user_id
else:
id_obj['password']['user']['name'] = user
if user_domain is not None:
_domain = dict(name=user_domain)
id_obj['password']['user']['name'] = username
_domain = None
if user_domain_id is not None:
_domain = dict(id=user_domain_id)
elif user_domain_name is not None:
_domain = dict(name=user_domain_name)
if _domain:
id_obj['password']['user']['domain'] = _domain
if project is not None:
_domain = dict(name=project_domain)
_project = dict(name=project, domain=_domain)
scope = dict(project=_project)
creds['auth']['scope'] = scope
if (project_id or project_name):
_project = dict()
if project_id:
_project['id'] = project_id
elif project_name:
_project['name'] = project_name
if project_domain_id is not None:
_project['domain'] = {'id': project_domain_id}
elif project_domain_name is not None:
_project['domain'] = {'name': project_domain_name}
creds['auth']['scope'] = dict(project=_project)
elif domain_id:
creds['auth']['scope'] = dict(domain={'id': domain_id})
elif domain_name:
creds['auth']['scope'] = dict(domain={'name': domain_name})
body = json.dumps(creds)
resp, body = self.post(self.auth_url, body=body)
@ -120,15 +148,22 @@ class V3TokenClientJSON(rest_client.RestClient):
return resp, json.loads(resp_body)
def get_token(self, user, password, project=None, project_domain='Default',
user_domain='Default', auth_data=False):
def get_token(self, **kwargs):
"""
:param user: username
Returns (token id, token data) for supplied credentials
"""
body = self.auth(user, password, project, user_type='name',
user_domain=user_domain,
project_domain=project_domain)
auth_data = kwargs.pop('auth_data', False)
if not (kwargs.get('user_domain_id') or
kwargs.get('user_domain_name')):
kwargs['user_domain_name'] = 'Default'
if not (kwargs.get('project_domain_id') or
kwargs.get('project_domain_name')):
kwargs['project_domain_name'] = 'Default'
body = self.auth(**kwargs)
token = body.response.get('x-subject-token')
if auth_data:

View File

@ -43,7 +43,8 @@ class FakeKeystoneV3Credentials(auth.KeystoneV3Credentials):
username='fake_username',
password='fake_password',
user_domain_name='fake_domain_name',
project_name='fake_tenant_name'
project_name='fake_tenant_name',
project_domain_name='fake_domain_name'
)
super(FakeKeystoneV3Credentials, self).__init__(**creds)