Add API changes for app cred access rules
bp whitelist-extension-for-app-creds Change-Id: Ie022e379d03d0309ec320b6947b987758d87fe5d
This commit is contained in:
parent
ee7315971c
commit
14c4b177ef
|
@ -545,7 +545,8 @@ class UserAppCredListCreateResource(ks_flask.ResourceBase):
|
||||||
# secret is only exposed after create, it is not stored
|
# secret is only exposed after create, it is not stored
|
||||||
'secret',
|
'secret',
|
||||||
'links',
|
'links',
|
||||||
'unrestricted'
|
'unrestricted',
|
||||||
|
'access_rules'
|
||||||
])
|
])
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
@ -608,6 +609,16 @@ class UserAppCredListCreateResource(ks_flask.ResourceBase):
|
||||||
if app_cred_data.get('expires_at'):
|
if app_cred_data.get('expires_at'):
|
||||||
app_cred_data['expires_at'] = utils.parse_expiration_date(
|
app_cred_data['expires_at'] = utils.parse_expiration_date(
|
||||||
app_cred_data['expires_at'])
|
app_cred_data['expires_at'])
|
||||||
|
if app_cred_data.get('access_rules'):
|
||||||
|
for access_rule in app_cred_data['access_rules']:
|
||||||
|
# If user provides an access rule by ID, it will be looked up
|
||||||
|
# by ID. If user provides an access rule that is identical to
|
||||||
|
# an existing one, the ID generated here will be ignored and
|
||||||
|
# the pre-existing access rule will be used.
|
||||||
|
if 'id' not in access_rule:
|
||||||
|
# Generate directly, rather than using _assign_unique_id,
|
||||||
|
# so that there is no deep copy made
|
||||||
|
access_rule['id'] = uuid.uuid4().hex
|
||||||
app_cred_data = self._normalize_dict(app_cred_data)
|
app_cred_data = self._normalize_dict(app_cred_data)
|
||||||
app_cred_api = PROVIDERS.application_credential_api
|
app_cred_api = PROVIDERS.application_credential_api
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,28 @@ _role_properties = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_access_rules_properties = {
|
||||||
|
'type': 'array',
|
||||||
|
'items': {
|
||||||
|
'type': 'object',
|
||||||
|
'properties': {
|
||||||
|
'path': {
|
||||||
|
'type': 'string',
|
||||||
|
'minLength': 0,
|
||||||
|
'maxLength': 225,
|
||||||
|
'pattern': '^\/.*'
|
||||||
|
},
|
||||||
|
'method': {
|
||||||
|
'type': 'string',
|
||||||
|
'pattern': '^(POST|GET|HEAD|PATCH|PUT|DELETE)$'
|
||||||
|
},
|
||||||
|
'service': parameter_types.id_string,
|
||||||
|
'id': parameter_types.id_string,
|
||||||
|
},
|
||||||
|
'additionalProperties': False
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_application_credential_properties = {
|
_application_credential_properties = {
|
||||||
'name': parameter_types.name,
|
'name': parameter_types.name,
|
||||||
'description': validation.nullable(parameter_types.description),
|
'description': validation.nullable(parameter_types.description),
|
||||||
|
@ -39,7 +61,8 @@ _application_credential_properties = {
|
||||||
'type': ['null', 'string']
|
'type': ['null', 'string']
|
||||||
},
|
},
|
||||||
'roles': _role_properties,
|
'roles': _role_properties,
|
||||||
'unrestricted': parameter_types.boolean
|
'unrestricted': parameter_types.boolean,
|
||||||
|
'access_rules': _access_rules_properties
|
||||||
}
|
}
|
||||||
|
|
||||||
application_credential_create = {
|
application_credential_create = {
|
||||||
|
|
|
@ -35,7 +35,8 @@ class ApplicationCredentialTestCase(test_v3.RestfulTestCase):
|
||||||
self.config_fixture.config(group='auth',
|
self.config_fixture.config(group='auth',
|
||||||
methods='password,application_credential')
|
methods='password,application_credential')
|
||||||
|
|
||||||
def _app_cred_body(self, roles=None, name=None, expires=None, secret=None):
|
def _app_cred_body(self, roles=None, name=None, expires=None, secret=None,
|
||||||
|
access_rules=None):
|
||||||
name = name or uuid.uuid4().hex
|
name = name or uuid.uuid4().hex
|
||||||
description = 'Credential for backups'
|
description = 'Credential for backups'
|
||||||
app_cred_data = {
|
app_cred_data = {
|
||||||
|
@ -48,6 +49,8 @@ class ApplicationCredentialTestCase(test_v3.RestfulTestCase):
|
||||||
app_cred_data['expires_at'] = expires
|
app_cred_data['expires_at'] = expires
|
||||||
if secret:
|
if secret:
|
||||||
app_cred_data['secret'] = secret
|
app_cred_data['secret'] = secret
|
||||||
|
if access_rules is not None:
|
||||||
|
app_cred_data['access_rules'] = access_rules
|
||||||
return {'application_credential': app_cred_data}
|
return {'application_credential': app_cred_data}
|
||||||
|
|
||||||
def test_create_application_credential(self):
|
def test_create_application_credential(self):
|
||||||
|
@ -187,6 +190,96 @@ class ApplicationCredentialTestCase(test_v3.RestfulTestCase):
|
||||||
expected_status_code=http_client.CREATED,
|
expected_status_code=http_client.CREATED,
|
||||||
headers={'x-Auth-Token': token_data.headers['x-subject-token']})
|
headers={'x-Auth-Token': token_data.headers['x-subject-token']})
|
||||||
|
|
||||||
|
def test_create_application_credential_with_access_rules(self):
|
||||||
|
roles = [{'id': self.role_id}]
|
||||||
|
access_rules = [
|
||||||
|
{
|
||||||
|
'path': '/v3/projects',
|
||||||
|
'method': 'POST',
|
||||||
|
'service': 'identity',
|
||||||
|
}
|
||||||
|
]
|
||||||
|
app_cred_body = self._app_cred_body(roles=roles,
|
||||||
|
access_rules=access_rules)
|
||||||
|
with self.test_client() as c:
|
||||||
|
token = self.get_scoped_token()
|
||||||
|
resp = c.post('/v3/users/%s/application_credentials' % self.user_id,
|
||||||
|
headers={'X-Auth-Token': token},
|
||||||
|
json=app_cred_body,
|
||||||
|
expected_status_code=http_client.CREATED)
|
||||||
|
resp_access_rules = resp.json['application_credential']['access_rules']
|
||||||
|
self.assertIn('id', resp_access_rules[0])
|
||||||
|
resp_access_rules[0].pop('id')
|
||||||
|
self.assertEqual(access_rules[0], resp_access_rules[0])
|
||||||
|
|
||||||
|
def test_create_application_credential_with_duplicate_access_rule(self):
|
||||||
|
roles = [{'id': self.role_id}]
|
||||||
|
access_rules = [
|
||||||
|
{
|
||||||
|
'path': '/v3/projects',
|
||||||
|
'method': 'POST',
|
||||||
|
'service': 'identity',
|
||||||
|
}
|
||||||
|
]
|
||||||
|
app_cred_body_1 = self._app_cred_body(roles=roles,
|
||||||
|
access_rules=access_rules)
|
||||||
|
with self.test_client() as c:
|
||||||
|
token = self.get_scoped_token()
|
||||||
|
resp = c.post('/v3/users/%s/application_credentials' % self.user_id,
|
||||||
|
headers={'X-Auth-Token': token},
|
||||||
|
json=app_cred_body_1,
|
||||||
|
expected_status_code=http_client.CREATED)
|
||||||
|
resp_access_rules = resp.json['application_credential']['access_rules']
|
||||||
|
self.assertIn('id', resp_access_rules[0])
|
||||||
|
access_rule_id = resp_access_rules[0].pop('id')
|
||||||
|
self.assertEqual(access_rules[0], resp_access_rules[0])
|
||||||
|
|
||||||
|
app_cred_body_2 = self._app_cred_body(roles=roles,
|
||||||
|
access_rules=access_rules)
|
||||||
|
with self.test_client() as c:
|
||||||
|
token = self.get_scoped_token()
|
||||||
|
resp = c.post('/v3/users/%s/application_credentials' % self.user_id,
|
||||||
|
headers={'X-Auth-Token': token},
|
||||||
|
json=app_cred_body_2,
|
||||||
|
expected_status_code=http_client.CREATED)
|
||||||
|
resp_access_rules = resp.json['application_credential']['access_rules']
|
||||||
|
self.assertEqual(access_rule_id, resp_access_rules[0]['id'])
|
||||||
|
|
||||||
|
def test_create_application_credential_with_access_rule_by_id(self):
|
||||||
|
roles = [{'id': self.role_id}]
|
||||||
|
access_rules = [
|
||||||
|
{
|
||||||
|
'path': '/v3/projects',
|
||||||
|
'method': 'POST',
|
||||||
|
'service': 'identity',
|
||||||
|
}
|
||||||
|
]
|
||||||
|
app_cred_body_1 = self._app_cred_body(roles=roles,
|
||||||
|
access_rules=access_rules)
|
||||||
|
with self.test_client() as c:
|
||||||
|
token = self.get_scoped_token()
|
||||||
|
resp = c.post('/v3/users/%s/application_credentials' % self.user_id,
|
||||||
|
headers={'X-Auth-Token': token},
|
||||||
|
json=app_cred_body_1,
|
||||||
|
expected_status_code=http_client.CREATED)
|
||||||
|
resp_access_rules = resp.json['application_credential']['access_rules']
|
||||||
|
access_rule_id = resp_access_rules
|
||||||
|
self.assertIn('id', resp_access_rules[0])
|
||||||
|
access_rule_id = resp_access_rules[0].pop('id')
|
||||||
|
self.assertEqual(access_rules[0], resp_access_rules[0])
|
||||||
|
|
||||||
|
access_rules = [{'id': access_rule_id}]
|
||||||
|
app_cred_body_2 = self._app_cred_body(roles=roles,
|
||||||
|
access_rules=access_rules)
|
||||||
|
with self.test_client() as c:
|
||||||
|
token = self.get_scoped_token()
|
||||||
|
resp = c.post('/v3/users/%s/application_credentials' % self.user_id,
|
||||||
|
headers={'X-Auth-Token': token},
|
||||||
|
json=app_cred_body_2,
|
||||||
|
expected_status_code=http_client.CREATED)
|
||||||
|
resp_access_rules = resp.json['application_credential']['access_rules']
|
||||||
|
self.assertEqual(access_rule_id, resp_access_rules[0]['id'])
|
||||||
|
|
||||||
def test_list_application_credentials(self):
|
def test_list_application_credentials(self):
|
||||||
with self.test_client() as c:
|
with self.test_client() as c:
|
||||||
token = self.get_scoped_token()
|
token = self.get_scoped_token()
|
||||||
|
|
Loading…
Reference in New Issue