Add HEAD APIs to federated API
This commit ensures that all Federated GET APIs have a corresponding HEAD API if not already specified. This is to be consistent with other APIs in keystone. Change-Id: Ifc7c9d73eca9f715a0f3f25701bcee389ddc354d Partial-Bug: 1696574
This commit is contained in:
parent
c528539879
commit
d7b13fd368
|
@ -25,14 +25,32 @@ identity_provider_policies = [
|
|||
name=base.IDENTITY % 'list_identity_providers',
|
||||
check_str=base.RULE_ADMIN_REQUIRED,
|
||||
description='List identity providers.',
|
||||
operations=[{'path': '/v3/OS-FEDERATION/identity_providers',
|
||||
'method': 'GET'}]),
|
||||
operations=[
|
||||
{
|
||||
'path': '/v3/OS-FEDERATION/identity_providers',
|
||||
'method': 'GET'
|
||||
},
|
||||
{
|
||||
'path': '/v3/OS-FEDERATION/identity_providers',
|
||||
'method': 'HEAD'
|
||||
}
|
||||
]
|
||||
),
|
||||
policy.DocumentedRuleDefault(
|
||||
name=base.IDENTITY % 'get_identity_providers',
|
||||
check_str=base.RULE_ADMIN_REQUIRED,
|
||||
description='Get identity provider.',
|
||||
operations=[{'path': '/v3/OS-FEDERATION/identity_providers/{idp_id}',
|
||||
'method': 'GET'}]),
|
||||
operations=[
|
||||
{
|
||||
'path': '/v3/OS-FEDERATION/identity_providers/{idp_id}',
|
||||
'method': 'GET'
|
||||
},
|
||||
{
|
||||
'path': '/v3/OS-FEDERATION/identity_providers/{idp_id}',
|
||||
'method': 'HEAD'
|
||||
}
|
||||
]
|
||||
),
|
||||
policy.DocumentedRuleDefault(
|
||||
name=base.IDENTITY % 'update_identity_provider',
|
||||
check_str=base.RULE_ADMIN_REQUIRED,
|
||||
|
|
|
@ -26,14 +26,32 @@ mapping_policies = [
|
|||
name=base.IDENTITY % 'get_mapping',
|
||||
check_str=base.RULE_ADMIN_REQUIRED,
|
||||
description='Get a federated mapping.',
|
||||
operations=[{'path': '/v3/OS-FEDERATION/mappings/{mapping_id}',
|
||||
'method': 'GET'}]),
|
||||
operations=[
|
||||
{
|
||||
'path': '/v3/OS-FEDERATION/mappings/{mapping_id}',
|
||||
'method': 'GET'
|
||||
},
|
||||
{
|
||||
'path': '/v3/OS-FEDERATION/mappings/{mapping_id}',
|
||||
'method': 'HEAD'
|
||||
}
|
||||
]
|
||||
),
|
||||
policy.DocumentedRuleDefault(
|
||||
name=base.IDENTITY % 'list_mappings',
|
||||
check_str=base.RULE_ADMIN_REQUIRED,
|
||||
description='List federated mappings.',
|
||||
operations=[{'path': '/v3/OS-FEDERATION/mappings',
|
||||
'method': 'GET'}]),
|
||||
operations=[
|
||||
{
|
||||
'path': '/v3/OS-FEDERATION/mappings',
|
||||
'method': 'GET'
|
||||
},
|
||||
{
|
||||
'path': '/v3/OS-FEDERATION/mappings',
|
||||
'method': 'HEAD'
|
||||
}
|
||||
]
|
||||
),
|
||||
policy.DocumentedRuleDefault(
|
||||
name=base.IDENTITY % 'delete_mapping',
|
||||
check_str=base.RULE_ADMIN_REQUIRED,
|
||||
|
|
|
@ -26,15 +26,34 @@ service_provider_policies = [
|
|||
name=base.IDENTITY % 'list_service_providers',
|
||||
check_str=base.RULE_ADMIN_REQUIRED,
|
||||
description='List federated service providers.',
|
||||
operations=[{'path': '/v3/OS-FEDERATION/service_providers',
|
||||
'method': 'GET'}]),
|
||||
operations=[
|
||||
{
|
||||
'path': '/v3/OS-FEDERATION/service_providers',
|
||||
'method': 'GET'
|
||||
},
|
||||
{
|
||||
'path': '/v3/OS-FEDERATION/service_providers',
|
||||
'method': 'HEAD'
|
||||
}
|
||||
]
|
||||
),
|
||||
policy.DocumentedRuleDefault(
|
||||
name=base.IDENTITY % 'get_service_provider',
|
||||
check_str=base.RULE_ADMIN_REQUIRED,
|
||||
description='Get federated service provider.',
|
||||
operations=[{'path': ('/v3/OS-FEDERATION/service_providers/'
|
||||
'{service_provider_id}'),
|
||||
'method': 'GET'}]),
|
||||
operations=[
|
||||
{
|
||||
'path': ('/v3/OS-FEDERATION/service_providers/'
|
||||
'{service_provider_id}'),
|
||||
'method': 'GET'
|
||||
},
|
||||
{
|
||||
'path': ('/v3/OS-FEDERATION/service_providers/'
|
||||
'{service_provider_id}'),
|
||||
'method': 'HEAD'
|
||||
}
|
||||
]
|
||||
),
|
||||
policy.DocumentedRuleDefault(
|
||||
name=base.IDENTITY % 'update_service_provider',
|
||||
check_str=base.RULE_ADMIN_REQUIRED,
|
||||
|
|
|
@ -38,7 +38,9 @@ class Routers(wsgi.RoutersBase):
|
|||
|
||||
PUT /OS-FEDERATION/identity_providers/{idp_id}
|
||||
GET /OS-FEDERATION/identity_providers
|
||||
HEAD /OS-FEDERATION/identity_providers
|
||||
GET /OS-FEDERATION/identity_providers/{idp_id}
|
||||
HEAD /OS-FEDERATION/identity_providers/{idp_id}
|
||||
DELETE /OS-FEDERATION/identity_providers/{idp_id}
|
||||
PATCH /OS-FEDERATION/identity_providers/{idp_id}
|
||||
|
||||
|
@ -46,8 +48,12 @@ class Routers(wsgi.RoutersBase):
|
|||
{idp_id}/protocols/{protocol_id}
|
||||
GET /OS-FEDERATION/identity_providers/
|
||||
{idp_id}/protocols
|
||||
HEAD /OS-FEDERATION/identity_providers/
|
||||
{idp_id}/protocols
|
||||
GET /OS-FEDERATION/identity_providers/
|
||||
{idp_id}/protocols/{protocol_id}
|
||||
HEAD /OS-FEDERATION/identity_providers/
|
||||
{idp_id}/protocols/{protocol_id}
|
||||
PATCH /OS-FEDERATION/identity_providers/
|
||||
{idp_id}/protocols/{protocol_id}
|
||||
DELETE /OS-FEDERATION/identity_providers/
|
||||
|
@ -55,16 +61,22 @@ class Routers(wsgi.RoutersBase):
|
|||
|
||||
PUT /OS-FEDERATION/mappings
|
||||
GET /OS-FEDERATION/mappings
|
||||
HEAD /OS-FEDERATION/mappings
|
||||
PATCH /OS-FEDERATION/mappings/{mapping_id}
|
||||
GET /OS-FEDERATION/mappings/{mapping_id}
|
||||
HEAD /OS-FEDERATION/mappings/{mapping_id}
|
||||
DELETE /OS-FEDERATION/mappings/{mapping_id}
|
||||
|
||||
GET /OS-FEDERATION/projects
|
||||
HEAD /OS-FEDERATION/projects
|
||||
GET /OS-FEDERATION/domains
|
||||
HEAD /OS-FEDERATION/domains
|
||||
|
||||
PUT /OS-FEDERATION/service_providers/{sp_id}
|
||||
GET /OS-FEDERATION/service_providers
|
||||
HEAD /OS-FEDERATION/service_providers
|
||||
GET /OS-FEDERATION/service_providers/{sp_id}
|
||||
HEAD /OS-FEDERATION/service_providers/{sp_id}
|
||||
DELETE /OS-FEDERATION/service_providers/{sp_id}
|
||||
PATCH /OS-FEDERATION/service_providers/{sp_id}
|
||||
|
||||
|
@ -83,6 +95,7 @@ class Routers(wsgi.RoutersBase):
|
|||
POST /auth/OS-FEDERATION/saml2
|
||||
POST /auth/OS-FEDERATION/saml2/ecp
|
||||
GET /OS-FEDERATION/saml2/metadata
|
||||
HEAD /OS-FEDERATION/saml2/metadata
|
||||
|
||||
GET /auth/OS-FEDERATION/websso/{protocol_id}
|
||||
?origin=https%3A//horizon.example.com
|
||||
|
@ -110,7 +123,7 @@ class Routers(wsgi.RoutersBase):
|
|||
self._add_resource(
|
||||
mapper, idp_controller,
|
||||
path=self._construct_url('identity_providers/{idp_id}'),
|
||||
get_action='get_identity_provider',
|
||||
get_head_action='get_identity_provider',
|
||||
put_action='create_identity_provider',
|
||||
patch_action='update_identity_provider',
|
||||
delete_action='delete_identity_provider',
|
||||
|
@ -121,7 +134,7 @@ class Routers(wsgi.RoutersBase):
|
|||
self._add_resource(
|
||||
mapper, idp_controller,
|
||||
path=self._construct_url('identity_providers'),
|
||||
get_action='list_identity_providers',
|
||||
get_head_action='list_identity_providers',
|
||||
rel=build_resource_relation(resource_name='identity_providers'))
|
||||
|
||||
# Protocol CRUD operations
|
||||
|
@ -130,7 +143,7 @@ class Routers(wsgi.RoutersBase):
|
|||
mapper, protocol_controller,
|
||||
path=self._construct_url('identity_providers/{idp_id}/protocols/'
|
||||
'{protocol_id}'),
|
||||
get_action='get_protocol',
|
||||
get_head_action='get_protocol',
|
||||
put_action='create_protocol',
|
||||
patch_action='update_protocol',
|
||||
delete_action='delete_protocol',
|
||||
|
@ -143,7 +156,7 @@ class Routers(wsgi.RoutersBase):
|
|||
self._add_resource(
|
||||
mapper, protocol_controller,
|
||||
path=self._construct_url('identity_providers/{idp_id}/protocols'),
|
||||
get_action='list_protocols',
|
||||
get_head_action='list_protocols',
|
||||
rel=build_resource_relation(
|
||||
resource_name='identity_provider_protocols'),
|
||||
path_vars={
|
||||
|
@ -155,7 +168,7 @@ class Routers(wsgi.RoutersBase):
|
|||
self._add_resource(
|
||||
mapper, mapping_controller,
|
||||
path=self._construct_url('mappings/{mapping_id}'),
|
||||
get_action='get_mapping',
|
||||
get_head_action='get_mapping',
|
||||
put_action='create_mapping',
|
||||
patch_action='update_mapping',
|
||||
delete_action='delete_mapping',
|
||||
|
@ -167,7 +180,7 @@ class Routers(wsgi.RoutersBase):
|
|||
self._add_resource(
|
||||
mapper, mapping_controller,
|
||||
path=self._construct_url('mappings'),
|
||||
get_action='list_mappings',
|
||||
get_head_action='list_mappings',
|
||||
rel=build_resource_relation(resource_name='mappings'))
|
||||
|
||||
# Service Providers CRUD operations
|
||||
|
@ -175,7 +188,7 @@ class Routers(wsgi.RoutersBase):
|
|||
self._add_resource(
|
||||
mapper, sp_controller,
|
||||
path=self._construct_url('service_providers/{sp_id}'),
|
||||
get_action='get_service_provider',
|
||||
get_head_action='get_service_provider',
|
||||
put_action='create_service_provider',
|
||||
patch_action='update_service_provider',
|
||||
delete_action='delete_service_provider',
|
||||
|
@ -187,20 +200,20 @@ class Routers(wsgi.RoutersBase):
|
|||
self._add_resource(
|
||||
mapper, sp_controller,
|
||||
path=self._construct_url('service_providers'),
|
||||
get_action='list_service_providers',
|
||||
get_head_action='list_service_providers',
|
||||
rel=build_resource_relation(resource_name='service_providers'))
|
||||
|
||||
self._add_resource(
|
||||
mapper, domain_controller,
|
||||
path=self._construct_url('domains'),
|
||||
new_path='/auth/domains',
|
||||
get_action='list_domains_for_user',
|
||||
get_head_action='list_domains_for_user',
|
||||
rel=build_resource_relation(resource_name='domains'))
|
||||
self._add_resource(
|
||||
mapper, project_controller,
|
||||
path=self._construct_url('projects'),
|
||||
new_path='/auth/projects',
|
||||
get_action='list_projects_for_user',
|
||||
get_head_action='list_projects_for_user',
|
||||
rel=build_resource_relation(resource_name='projects'))
|
||||
|
||||
# Auth operations
|
||||
|
@ -248,5 +261,5 @@ class Routers(wsgi.RoutersBase):
|
|||
self._add_resource(
|
||||
mapper, saml_metadata_controller,
|
||||
path=self._construct_url('saml2/metadata'),
|
||||
get_action='get_metadata',
|
||||
get_head_action='get_metadata',
|
||||
rel=build_resource_relation(resource_name='metadata'))
|
||||
|
|
|
@ -1137,7 +1137,7 @@ class FederatedIdentityProviderTests(test_v3.RestfulTestCase):
|
|||
self.assertIn('Duplicate remote ID',
|
||||
resp_data['error']['message'])
|
||||
|
||||
def test_list_idps(self, iterations=5):
|
||||
def test_list_head_idps(self, iterations=5):
|
||||
"""List all available IdentityProviders.
|
||||
|
||||
This test collects ids of created IdPs and
|
||||
|
@ -1170,7 +1170,9 @@ class FederatedIdentityProviderTests(test_v3.RestfulTestCase):
|
|||
ids_intersection = entities_ids.intersection(ids)
|
||||
self.assertEqual(ids_intersection, ids)
|
||||
|
||||
def test_filter_list_idp_by_id(self):
|
||||
self.head(url, expected_status=http_client.OK)
|
||||
|
||||
def test_filter_list_head_idp_by_id(self):
|
||||
def get_id(resp):
|
||||
r = self._fetch_attribute_from_response(resp,
|
||||
'identity_provider')
|
||||
|
@ -1194,7 +1196,9 @@ class FederatedIdentityProviderTests(test_v3.RestfulTestCase):
|
|||
self.assertThat(filtered_service_list, matchers.HasLength(1))
|
||||
self.assertEqual(idp1_id, filtered_service_list[0].get('id'))
|
||||
|
||||
def test_filter_list_idp_by_enabled(self):
|
||||
self.head(url, expected_status=http_client.OK)
|
||||
|
||||
def test_filter_list_head_idp_by_enabled(self):
|
||||
def get_id(resp):
|
||||
r = self._fetch_attribute_from_response(resp,
|
||||
'identity_provider')
|
||||
|
@ -1221,6 +1225,8 @@ class FederatedIdentityProviderTests(test_v3.RestfulTestCase):
|
|||
self.assertThat(filtered_service_list, matchers.HasLength(1))
|
||||
self.assertEqual(idp1_id, filtered_service_list[0].get('id'))
|
||||
|
||||
self.head(url, expected_status=http_client.OK)
|
||||
|
||||
def test_check_idp_uniqueness(self):
|
||||
"""Add same IdP twice.
|
||||
|
||||
|
@ -1241,7 +1247,7 @@ class FederatedIdentityProviderTests(test_v3.RestfulTestCase):
|
|||
self.assertIn('Duplicate entry',
|
||||
resp_data.get('error', {}).get('message'))
|
||||
|
||||
def test_get_idp(self):
|
||||
def test_get_head_idp(self):
|
||||
"""Create and later fetch IdP."""
|
||||
body = self._http_idp_input()
|
||||
domain = unit.new_domain_ref()
|
||||
|
@ -1260,6 +1266,8 @@ class FederatedIdentityProviderTests(test_v3.RestfulTestCase):
|
|||
dummy_validator, keys_to_check=body_keys,
|
||||
ref=body)
|
||||
|
||||
self.head(url, expected_status=http_client.OK)
|
||||
|
||||
def test_get_nonexisting_idp(self):
|
||||
"""Fetch nonexisting IdP entity.
|
||||
|
||||
|
@ -1446,7 +1454,7 @@ class FederatedIdentityProviderTests(test_v3.RestfulTestCase):
|
|||
validate=False,
|
||||
**kwargs)
|
||||
|
||||
def test_get_protocol(self):
|
||||
def test_get_head_protocol(self):
|
||||
"""Create and later fetch protocol tied to IdP."""
|
||||
resp, idp_id, proto = self._assign_protocol_to_idp(
|
||||
expected_status=http_client.CREATED)
|
||||
|
@ -1465,7 +1473,9 @@ class FederatedIdentityProviderTests(test_v3.RestfulTestCase):
|
|||
keys_to_check=reference_keys,
|
||||
ref=reference)
|
||||
|
||||
def test_list_protocols(self):
|
||||
self.head(url, expected_status=http_client.OK)
|
||||
|
||||
def test_list_head_protocols(self):
|
||||
"""Create set of protocols and later list them.
|
||||
|
||||
Compare input and output id sets.
|
||||
|
@ -1494,6 +1504,8 @@ class FederatedIdentityProviderTests(test_v3.RestfulTestCase):
|
|||
protocols_intersection = entities.intersection(protocol_ids)
|
||||
self.assertEqual(protocols_intersection, set(protocol_ids))
|
||||
|
||||
self.head(url, expected_status=http_client.OK)
|
||||
|
||||
def test_update_protocols_attribute(self):
|
||||
"""Update protocol's attribute."""
|
||||
resp, idp_id, proto = self._assign_protocol_to_idp(
|
||||
|
@ -1573,7 +1585,7 @@ class MappingCRUDTests(test_v3.RestfulTestCase):
|
|||
resp = self._create_default_mapping_entry()
|
||||
self.assertValidMappingResponse(resp, mapping_fixtures.MAPPING_LARGE)
|
||||
|
||||
def test_mapping_list(self):
|
||||
def test_mapping_list_head(self):
|
||||
url = self.MAPPING_URL
|
||||
self._create_default_mapping_entry()
|
||||
resp = self.get(url)
|
||||
|
@ -1582,6 +1594,7 @@ class MappingCRUDTests(test_v3.RestfulTestCase):
|
|||
self.assertResponseStatus(resp, http_client.OK)
|
||||
self.assertValidListLinks(resp.result.get('links'))
|
||||
self.assertEqual(1, len(entities))
|
||||
self.head(url, expected_status=http_client.OK)
|
||||
|
||||
def test_mapping_delete(self):
|
||||
url = self.MAPPING_URL + '%(mapping_id)s'
|
||||
|
@ -1592,13 +1605,14 @@ class MappingCRUDTests(test_v3.RestfulTestCase):
|
|||
self.assertResponseStatus(resp, http_client.NO_CONTENT)
|
||||
self.get(url, expected_status=http_client.NOT_FOUND)
|
||||
|
||||
def test_mapping_get(self):
|
||||
def test_mapping_get_head(self):
|
||||
url = self.MAPPING_URL + '%(mapping_id)s'
|
||||
resp = self._create_default_mapping_entry()
|
||||
mapping_id = self._get_id_from_response(resp)
|
||||
url = url % {'mapping_id': mapping_id}
|
||||
resp = self.get(url)
|
||||
self.assertValidMappingResponse(resp, mapping_fixtures.MAPPING_LARGE)
|
||||
self.head(url, expected_status=http_client.OK)
|
||||
|
||||
def test_mapping_update(self):
|
||||
url = self.MAPPING_URL + '%(mapping_id)s'
|
||||
|
@ -3052,7 +3066,7 @@ class FederatedUserTests(test_v3.RestfulTestCase, FederatedSetupMixin):
|
|||
# compare
|
||||
self.assertItemsEqual(auth_domains, fed_domains)
|
||||
|
||||
def test_list_domains_for_user_duplicates(self):
|
||||
def test_list_head_domains_for_user_duplicates(self):
|
||||
# create role
|
||||
role_ref = unit.new_role_ref()
|
||||
self.role_api.create_role(role_ref['id'], role_ref)
|
||||
|
@ -3065,6 +3079,12 @@ class FederatedUserTests(test_v3.RestfulTestCase, FederatedSetupMixin):
|
|||
group_domains = r.result['domains']
|
||||
domain_from_group = group_domains[0]
|
||||
|
||||
self.head(
|
||||
'/OS-FEDERATION/domains',
|
||||
token=unscoped_token,
|
||||
expected_status=http_client.OK
|
||||
)
|
||||
|
||||
# assign group domain and role to user, this should create a
|
||||
# duplicate domain
|
||||
self.assignment_api.create_grant(role_ref['id'],
|
||||
|
@ -3079,7 +3099,7 @@ class FederatedUserTests(test_v3.RestfulTestCase, FederatedSetupMixin):
|
|||
self.assertNotIn(domain['id'], user_domain_ids)
|
||||
user_domain_ids.append(domain['id'])
|
||||
|
||||
def test_list_projects_for_user_duplicates(self):
|
||||
def test_list_head_projects_for_user_duplicates(self):
|
||||
# create role
|
||||
role_ref = unit.new_role_ref()
|
||||
self.role_api.create_role(role_ref['id'], role_ref)
|
||||
|
@ -3092,6 +3112,12 @@ class FederatedUserTests(test_v3.RestfulTestCase, FederatedSetupMixin):
|
|||
group_projects = r.result['projects']
|
||||
project_from_group = group_projects[0]
|
||||
|
||||
self.head(
|
||||
'/OS-FEDERATION/projects',
|
||||
token=unscoped_token,
|
||||
expected_status=http_client.OK
|
||||
)
|
||||
|
||||
# assign group project and role to user, this should create a
|
||||
# duplicate project
|
||||
self.assignment_api.add_role_to_user_and_project(
|
||||
|
@ -4040,9 +4066,10 @@ class IdPMetadataGenerationTests(test_v3.RestfulTestCase):
|
|||
self.get(self.METADATA_URL,
|
||||
expected_status=http_client.INTERNAL_SERVER_ERROR)
|
||||
|
||||
def test_get_metadata(self):
|
||||
def test_get_head_metadata(self):
|
||||
self.config_fixture.config(
|
||||
group='saml', idp_metadata_path=XMLDIR + '/idp_saml2_metadata.xml')
|
||||
self.head(self.METADATA_URL, expected_status=http_client.OK)
|
||||
r = self.get(self.METADATA_URL, response_content_type='text/xml')
|
||||
self.assertEqual('text/xml', r.headers.get('Content-Type'))
|
||||
|
||||
|
@ -4096,11 +4123,12 @@ class ServiceProviderTests(test_v3.RestfulTestCase):
|
|||
expected_status=http_client.CREATED)
|
||||
return resp
|
||||
|
||||
def test_get_service_provider(self):
|
||||
def test_get_head_service_provider(self):
|
||||
url = self.base_url(suffix=self.SERVICE_PROVIDER_ID)
|
||||
resp = self.get(url)
|
||||
self.assertValidEntity(resp.result['service_provider'],
|
||||
keys_to_check=self.SP_KEYS)
|
||||
resp = self.head(url, expected_status=http_client.OK)
|
||||
|
||||
def test_get_service_provider_fail(self):
|
||||
url = self.base_url(suffix=uuid.uuid4().hex)
|
||||
|
@ -4244,7 +4272,7 @@ class ServiceProviderTests(test_v3.RestfulTestCase):
|
|||
self.put(url, body={'service_provider': sp},
|
||||
expected_status=http_client.BAD_REQUEST)
|
||||
|
||||
def test_list_service_providers(self):
|
||||
def test_list_head_service_providers(self):
|
||||
"""Test listing of service provider objects.
|
||||
|
||||
Add two new service providers. List all available service providers.
|
||||
|
@ -4277,6 +4305,8 @@ class ServiceProviderTests(test_v3.RestfulTestCase):
|
|||
service_provider, ref=ref_service_providers[id],
|
||||
keys_to_check=self.SP_KEYS)
|
||||
|
||||
self.head(url, expected_status=http_client.OK)
|
||||
|
||||
def test_update_service_provider(self):
|
||||
"""Update existing service provider.
|
||||
|
||||
|
|
Loading…
Reference in New Issue