summaryrefslogtreecommitdiff
path: root/keystone/federation
diff options
context:
space:
mode:
authorMorgan Fainberg <morgan.fainberg@gmail.com>2018-08-10 13:41:52 -0700
committermorgan fainberg <morgan.fainberg@gmail.com>2018-09-10 11:22:58 -0700
commit94f8f103abc6911144423c277fbd1a71d691aa99 (patch)
tree395775ed35d7777125fc11a0432e636ac193ab22 /keystone/federation
parent294ca38554bb229f66a772e7dba35a5b08a36b20 (diff)
downloadkeystone-94f8f103abc6911144423c277fbd1a71d691aa99.tar.gz
Convert OS-FEDERATION to flask native dispatching
Convert OS-FEDERATION to flask native dispatching. NOTE: Two changes occured that impact testing in this patch. * The JSON Home test now uses assertDictEquals to make it easier to debug json_home document errors * It was by general good luck that the overloaded relation 'identity_providers' worked as expected. The relation was used for both '/OS-FEDERATION/identity_providers' and the Identity-Provider-Specific WebSSO path. The change to the JSON Home document and the tests make the Identity-Provider-Specific WebSSO path now a relation of 'identity_providers_websso' to more closely align with 'websso' relation for '/auth/OS-FEDERATION/websso/{protocol_id}'. While this constitutes a minor break in our contract (the output of the json home document) it was required to ensure consistency and functionality. The alternative is to not represent '/OS-FEDERATION/identity_providers' (list endpoint) in the JSON Home document at all, instead represent only the WebSSO endpoint. Change-Id: If746c14491322d4a5f88fa0cbb31105f6d38c240 Partial-Bug: #1776504
Diffstat (limited to 'keystone/federation')
-rw-r--r--keystone/federation/controllers.py326
-rw-r--r--keystone/federation/routers.py178
2 files changed, 3 insertions, 501 deletions
diff --git a/keystone/federation/controllers.py b/keystone/federation/controllers.py
index 86bb25928..96dce6d10 100644
--- a/keystone/federation/controllers.py
+++ b/keystone/federation/controllers.py
@@ -15,7 +15,6 @@
import string
from oslo_log import log
-from oslo_log import versionutils
from six.moves import http_client
from six.moves import urllib
import webob
@@ -49,217 +48,6 @@ class _ControllerBase(controller.V3Controller):
return super(_ControllerBase, cls).base_url(context, path=path)
-class IdentityProvider(_ControllerBase):
- """Identity Provider representation."""
-
- collection_name = 'identity_providers'
- member_name = 'identity_provider'
-
- _public_parameters = frozenset(['id', 'enabled', 'description',
- 'remote_ids', 'links', 'domain_id'
- ])
-
- @classmethod
- def _add_related_links(cls, context, ref):
- """Add URLs for entities related with Identity Provider.
-
- Add URLs pointing to:
- - protocols tied to the Identity Provider
-
- """
- ref.setdefault('links', {})
- base_path = ref['links'].get('self')
- if base_path is None:
- base_path = '/'.join([IdentityProvider.base_url(context),
- ref['id']])
- for name in ['protocols']:
- ref['links'][name] = '/'.join([base_path, name])
-
- @classmethod
- def _add_self_referential_link(cls, context, ref):
- id = ref['id']
- self_path = '/'.join([cls.base_url(context), id])
- ref.setdefault('links', {})
- ref['links']['self'] = self_path
-
- @classmethod
- def wrap_member(cls, context, ref):
- cls._add_self_referential_link(context, ref)
- cls._add_related_links(context, ref)
- ref = cls.filter_params(ref)
- return {cls.member_name: ref}
-
- @controller.protected()
- def create_identity_provider(self, request, idp_id, identity_provider):
- validation.lazy_validate(schema.identity_provider_create,
- identity_provider)
- identity_provider = self._normalize_dict(identity_provider)
- identity_provider.setdefault('enabled', False)
- idp_ref = PROVIDERS.federation_api.create_idp(
- idp_id, identity_provider
- )
- response = IdentityProvider.wrap_member(request.context_dict, idp_ref)
- return wsgi.render_response(
- body=response, status=(http_client.CREATED,
- http_client.responses[http_client.CREATED]))
-
- @controller.filterprotected('id', 'enabled')
- def list_identity_providers(self, request, filters):
- hints = self.build_driver_hints(request, filters)
- ref = PROVIDERS.federation_api.list_idps(hints=hints)
- ref = [self.filter_params(x) for x in ref]
- return IdentityProvider.wrap_collection(request.context_dict,
- ref, hints=hints)
-
- @controller.protected()
- def get_identity_provider(self, request, idp_id):
- ref = PROVIDERS.federation_api.get_idp(idp_id)
- return IdentityProvider.wrap_member(request.context_dict, ref)
-
- @controller.protected()
- def delete_identity_provider(self, request, idp_id):
- PROVIDERS.federation_api.delete_idp(idp_id)
-
- @controller.protected()
- def update_identity_provider(self, request, idp_id, identity_provider):
- validation.lazy_validate(schema.identity_provider_update,
- identity_provider)
- identity_provider = self._normalize_dict(identity_provider)
- idp_ref = PROVIDERS.federation_api.update_idp(
- idp_id, identity_provider
- )
- return IdentityProvider.wrap_member(request.context_dict, idp_ref)
-
-
-class FederationProtocol(_ControllerBase):
- """A federation protocol representation.
-
- See keystone.common.controller.V3Controller docstring for explanation
- on _public_parameters class attributes.
-
- """
-
- collection_name = 'protocols'
- member_name = 'protocol'
-
- _public_parameters = frozenset(['id', 'mapping_id', 'links'])
-
- @classmethod
- def _add_self_referential_link(cls, context, ref):
- """Add 'links' entry to the response dictionary.
-
- Calls IdentityProvider.base_url() class method, as it constructs
- proper URL along with the 'identity providers' part included.
-
- :param ref: response dictionary
-
- """
- ref.setdefault('links', {})
- base_path = ref['links'].get('identity_provider')
- if base_path is None:
- base_path = [IdentityProvider.base_url(context), ref['idp_id']]
- base_path = '/'.join(base_path)
- self_path = [base_path, 'protocols', ref['id']]
- self_path = '/'.join(self_path)
- ref['links']['self'] = self_path
-
- @classmethod
- def _add_related_links(cls, context, ref):
- """Add new entries to the 'links' subdictionary in the response.
-
- Adds 'identity_provider' key with URL pointing to related identity
- provider as a value.
-
- :param ref: response dictionary
-
- """
- ref.setdefault('links', {})
- base_path = '/'.join([IdentityProvider.base_url(context),
- ref['idp_id']])
- ref['links']['identity_provider'] = base_path
-
- @classmethod
- def wrap_member(cls, context, ref):
- cls._add_related_links(context, ref)
- cls._add_self_referential_link(context, ref)
- ref = cls.filter_params(ref)
- return {cls.member_name: ref}
-
- @controller.protected()
- def create_protocol(self, request, idp_id, protocol_id, protocol):
- validation.lazy_validate(schema.protocol_create, protocol)
- protocol = self._normalize_dict(protocol)
- ref = PROVIDERS.federation_api.create_protocol(
- idp_id, protocol_id, protocol)
- response = FederationProtocol.wrap_member(request.context_dict, ref)
- return wsgi.render_response(
- body=response, status=(http_client.CREATED,
- http_client.responses[http_client.CREATED]))
-
- @controller.protected()
- def update_protocol(self, request, idp_id, protocol_id, protocol):
- validation.lazy_validate(schema.protocol_update, protocol)
- protocol = self._normalize_dict(protocol)
- ref = PROVIDERS.federation_api.update_protocol(idp_id, protocol_id,
- protocol)
- return FederationProtocol.wrap_member(request.context_dict, ref)
-
- @controller.protected()
- def get_protocol(self, request, idp_id, protocol_id):
- ref = PROVIDERS.federation_api.get_protocol(idp_id, protocol_id)
- return FederationProtocol.wrap_member(request.context_dict, ref)
-
- @controller.protected()
- def list_protocols(self, request, idp_id):
- protocols_ref = PROVIDERS.federation_api.list_protocols(idp_id)
- protocols = list(protocols_ref)
- return FederationProtocol.wrap_collection(request.context_dict,
- protocols)
-
- @controller.protected()
- def delete_protocol(self, request, idp_id, protocol_id):
- PROVIDERS.federation_api.delete_protocol(idp_id, protocol_id)
-
-
-class MappingController(_ControllerBase):
- collection_name = 'mappings'
- member_name = 'mapping'
-
- @controller.protected()
- def create_mapping(self, request, mapping_id, mapping):
- ref = self._normalize_dict(mapping)
- utils.validate_mapping_structure(ref)
- mapping_ref = PROVIDERS.federation_api.create_mapping(mapping_id, ref)
- response = MappingController.wrap_member(request.context_dict,
- mapping_ref)
- return wsgi.render_response(
- body=response, status=(http_client.CREATED,
- http_client.responses[http_client.CREATED]))
-
- @controller.protected()
- def list_mappings(self, request):
- ref = PROVIDERS.federation_api.list_mappings()
- return MappingController.wrap_collection(request.context_dict, ref)
-
- @controller.protected()
- def get_mapping(self, request, mapping_id):
- ref = PROVIDERS.federation_api.get_mapping(mapping_id)
- return MappingController.wrap_member(request.context_dict, ref)
-
- @controller.protected()
- def delete_mapping(self, request, mapping_id):
- PROVIDERS.federation_api.delete_mapping(mapping_id)
-
- @controller.protected()
- def update_mapping(self, request, mapping_id, mapping):
- mapping = self._normalize_dict(mapping)
- utils.validate_mapping_structure(mapping)
- mapping_ref = PROVIDERS.federation_api.update_mapping(
- mapping_id, mapping
- )
- return MappingController.wrap_member(request.context_dict, mapping_ref)
-
-
class Auth(auth_controllers.Auth):
def _get_sso_origin_host(self, request):
@@ -436,117 +224,3 @@ class Auth(auth_controllers.Auth):
body=ecp_assertion.to_string(),
status=(http_client.OK, http_client.responses[http_client.OK]),
headers=headers)
-
-
-class DomainV3(controller.V3Controller):
- collection_name = 'domains'
- member_name = 'domain'
-
- def __init__(self):
- super(DomainV3, self).__init__()
- self.get_member_from_driver = PROVIDERS.resource_api.get_domain
-
- @versionutils.deprecated(
- as_of=versionutils.deprecated.JUNO,
- in_favor_of='GET /v3/auth/domains/',
- )
- @controller.protected()
- def list_domains_for_user(self, request):
- """List all domains available to an authenticated user.
-
- :param context: request context
- :returns: list of accessible domains
-
- """
- controller = auth_controllers.Auth()
- return controller.get_auth_domains(request)
-
-
-class ProjectAssignmentV3(controller.V3Controller):
- collection_name = 'projects'
- member_name = 'project'
-
- def __init__(self):
- super(ProjectAssignmentV3, self).__init__()
- self.get_member_from_driver = PROVIDERS.resource_api.get_project
-
- @versionutils.deprecated(
- as_of=versionutils.deprecated.JUNO,
- in_favor_of='GET /v3/auth/projects/',
- )
- @controller.protected()
- def list_projects_for_user(self, request):
- """List all projects available to an authenticated user.
-
- :param context: request context
- :returns: list of accessible projects
-
- """
- controller = auth_controllers.Auth()
- return controller.get_auth_projects(request)
-
-
-class ServiceProvider(_ControllerBase):
- """Service Provider representation."""
-
- collection_name = 'service_providers'
- member_name = 'service_provider'
-
- _public_parameters = frozenset(['auth_url', 'id', 'enabled', 'description',
- 'links', 'relay_state_prefix', 'sp_url'])
-
- @controller.protected()
- def create_service_provider(self, request, sp_id, service_provider):
- validation.lazy_validate(schema.service_provider_create,
- service_provider)
- service_provider = self._normalize_dict(service_provider)
- service_provider.setdefault('enabled', False)
- service_provider.setdefault('relay_state_prefix',
- CONF.saml.relay_state_prefix)
- sp_ref = PROVIDERS.federation_api.create_sp(sp_id, service_provider)
- response = ServiceProvider.wrap_member(request.context_dict, sp_ref)
- return wsgi.render_response(
- body=response, status=(http_client.CREATED,
- http_client.responses[http_client.CREATED]))
-
- @controller.filterprotected('id', 'enabled')
- def list_service_providers(self, request, filters):
- hints = self.build_driver_hints(request, filters)
- ref = PROVIDERS.federation_api.list_sps(hints=hints)
- ref = [self.filter_params(x) for x in ref]
- return ServiceProvider.wrap_collection(request.context_dict,
- ref, hints=hints)
-
- @controller.protected()
- def get_service_provider(self, request, sp_id):
- ref = PROVIDERS.federation_api.get_sp(sp_id)
- return ServiceProvider.wrap_member(request.context_dict, ref)
-
- @controller.protected()
- def delete_service_provider(self, request, sp_id):
- PROVIDERS.federation_api.delete_sp(sp_id)
-
- @controller.protected()
- def update_service_provider(self, request, sp_id, service_provider):
- validation.lazy_validate(schema.service_provider_update,
- service_provider)
- service_provider = self._normalize_dict(service_provider)
- sp_ref = PROVIDERS.federation_api.update_sp(sp_id, service_provider)
- return ServiceProvider.wrap_member(request.context_dict, sp_ref)
-
-
-class SAMLMetadataV3(_ControllerBase):
- member_name = 'metadata'
-
- def get_metadata(self, context):
- metadata_path = CONF.saml.idp_metadata_path
- try:
- with open(metadata_path, 'r') as metadata_handler:
- metadata = metadata_handler.read()
- except IOError as e:
- # Raise HTTP 500 in case Metadata file cannot be read.
- raise exception.MetadataFileError(reason=e)
- return wsgi.render_response(
- body=metadata, status=(http_client.OK,
- http_client.responses[http_client.OK]),
- headers=[('Content-Type', 'text/xml')])
diff --git a/keystone/federation/routers.py b/keystone/federation/routers.py
index 8b07f5376..9bfd11740 100644
--- a/keystone/federation/routers.py
+++ b/keystone/federation/routers.py
@@ -36,54 +36,6 @@ class Routers(wsgi.RoutersBase):
The API looks like::
- 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}
-
- PUT /OS-FEDERATION/identity_providers/
- {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/
- {idp_id}/protocols/{protocol_id}
-
- 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}
-
- GET /OS-FEDERATION/identity_providers/{idp_id}/
- protocols/{protocol_id}/auth
- POST /OS-FEDERATION/identity_providers/{idp_id}/
- protocols/{protocol_id}/auth
GET /auth/OS-FEDERATION/identity_providers/
{idp_id}/protocols/{protocol_id}/websso
?origin=https%3A//horizon.example.com
@@ -94,8 +46,6 @@ 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
@@ -105,133 +55,17 @@ class Routers(wsgi.RoutersBase):
"""
- _path_prefixes = ('auth', 'OS-FEDERATION')
+ _path_prefixes = ('auth',)
def _construct_url(self, suffix):
return "/OS-FEDERATION/%s" % suffix
def append_v3_routers(self, mapper, routers):
auth_controller = controllers.Auth()
- idp_controller = controllers.IdentityProvider()
- protocol_controller = controllers.FederationProtocol()
- mapping_controller = controllers.MappingController()
- project_controller = controllers.ProjectAssignmentV3()
- domain_controller = controllers.DomainV3()
- saml_metadata_controller = controllers.SAMLMetadataV3()
- sp_controller = controllers.ServiceProvider()
-
- # Identity Provider CRUD operations
-
- self._add_resource(
- mapper, idp_controller,
- path=self._construct_url('identity_providers/{idp_id}'),
- get_head_action='get_identity_provider',
- put_action='create_identity_provider',
- patch_action='update_identity_provider',
- delete_action='delete_identity_provider',
- rel=build_resource_relation(resource_name='identity_provider'),
- path_vars={
- 'idp_id': IDP_ID_PARAMETER_RELATION,
- })
- self._add_resource(
- mapper, idp_controller,
- path=self._construct_url('identity_providers'),
- get_head_action='list_identity_providers',
- rel=build_resource_relation(resource_name='identity_providers'))
-
- # Protocol CRUD operations
-
- self._add_resource(
- mapper, protocol_controller,
- path=self._construct_url('identity_providers/{idp_id}/protocols/'
- '{protocol_id}'),
- get_head_action='get_protocol',
- put_action='create_protocol',
- patch_action='update_protocol',
- delete_action='delete_protocol',
- rel=build_resource_relation(
- resource_name='identity_provider_protocol'),
- path_vars={
- 'idp_id': IDP_ID_PARAMETER_RELATION,
- 'protocol_id': PROTOCOL_ID_PARAMETER_RELATION,
- })
- self._add_resource(
- mapper, protocol_controller,
- path=self._construct_url('identity_providers/{idp_id}/protocols'),
- get_head_action='list_protocols',
- rel=build_resource_relation(
- resource_name='identity_provider_protocols'),
- path_vars={
- 'idp_id': IDP_ID_PARAMETER_RELATION,
- })
-
- # Mapping CRUD operations
-
- self._add_resource(
- mapper, mapping_controller,
- path=self._construct_url('mappings/{mapping_id}'),
- get_head_action='get_mapping',
- put_action='create_mapping',
- patch_action='update_mapping',
- delete_action='delete_mapping',
- rel=build_resource_relation(resource_name='mapping'),
- path_vars={
- 'mapping_id': build_parameter_relation(
- parameter_name='mapping_id'),
- })
- self._add_resource(
- mapper, mapping_controller,
- path=self._construct_url('mappings'),
- get_head_action='list_mappings',
- rel=build_resource_relation(resource_name='mappings'))
-
- # Service Providers CRUD operations
-
- self._add_resource(
- mapper, sp_controller,
- path=self._construct_url('service_providers/{sp_id}'),
- get_head_action='get_service_provider',
- put_action='create_service_provider',
- patch_action='update_service_provider',
- delete_action='delete_service_provider',
- rel=build_resource_relation(resource_name='service_provider'),
- path_vars={
- 'sp_id': SP_ID_PARAMETER_RELATION,
- })
-
- self._add_resource(
- mapper, sp_controller,
- path=self._construct_url('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_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_head_action='list_projects_for_user',
- rel=build_resource_relation(resource_name='projects'))
# Auth operations
self._add_resource(
mapper, auth_controller,
- path=self._construct_url('identity_providers/{idp_id}/'
- 'protocols/{protocol_id}/auth'),
- get_post_action='federated_authentication',
- rel=build_resource_relation(
- resource_name='identity_provider_protocol_auth'),
- path_vars={
- 'idp_id': IDP_ID_PARAMETER_RELATION,
- 'protocol_id': PROTOCOL_ID_PARAMETER_RELATION,
- })
- self._add_resource(
- mapper, auth_controller,
path='/auth' + self._construct_url('saml2'),
post_action='create_saml_assertion',
rel=build_resource_relation(resource_name='saml2'))
@@ -253,15 +87,9 @@ class Routers(wsgi.RoutersBase):
path='/auth' + self._construct_url(
'identity_providers/{idp_id}/protocols/{protocol_id}/websso'),
get_post_action='federated_idp_specific_sso_auth',
- rel=build_resource_relation(resource_name='identity_providers'),
+ rel=build_resource_relation(
+ resource_name='identity_providers_websso'),
path_vars={
'idp_id': IDP_ID_PARAMETER_RELATION,
'protocol_id': PROTOCOL_ID_PARAMETER_RELATION,
})
-
- # Keystone-Identity-Provider metadata endpoint
- self._add_resource(
- mapper, saml_metadata_controller,
- path=self._construct_url('saml2/metadata'),
- get_head_action='get_metadata',
- rel=build_resource_relation(resource_name='metadata'))