Exemplo n.º 1
0
def build_prior_role_response_data(prior_role_id, prior_role_name):
    return {
        'id': prior_role_id,
        'links': {
            'self': ks_flask.base_url(path='/roles/%s' % prior_role_id)
        },
        'name': prior_role_name}
Exemplo n.º 2
0
 def get(self):
     ENFORCER.enforce_call(action='identity:list_revoke_events')
     since = flask.request.args.get('since')
     last_fetch = None
     if since:
         try:
             last_fetch = timeutils.normalize_time(
                 timeutils.parse_isotime(since))
         except ValueError:
             raise exception.ValidationError(
                 message=_('invalidate date format %s') % since)
     # FIXME(notmorgan): The revocation events cannot have resource options
     # added to them or lazy-loaded relationships as long as to_dict
     # is called outside of an active session context. This API is unused
     # and should be deprecated in the near future. Fix this before adding
     # resource_options or any lazy-loaded relationships to the revocation
     # events themselves.
     events = PROVIDERS.revoke_api.list_events(last_fetch=last_fetch)
     # Build the links by hand as the standard controller calls require ids
     response = {'events': [event.to_dict() for event in events],
                 'links': {
                     'next': None,
                     'self': ks_flask.base_url(path='/OS-REVOKE/events'),
                     'previous': None}
                 }
     return response
Exemplo n.º 3
0
def get_versions():
    if v3_mime_type_best_match() == MimeTypes.JSON_HOME:
        # RENDER JSON-Home form, we have a clever client who will
        # understand the JSON-Home document.
        v3_json_home = json_home.JsonHomeResources.resources()
        json_home.translate_urls(v3_json_home, '/v3')
        return flask.Response(response=jsonutils.dumps(v3_json_home),
                              mimetype=MimeTypes.JSON_HOME)
    else:
        identity_url = '%s/' % ks_flask.base_url()
        versions = _get_versions_list(identity_url)
        # Set the preferred version to the latest "stable" version.
        # TODO(morgan): If we ever have more API versions find the latest
        # stable version instead of just using the "base_url", for now we
        # simply have a single version so use it as the preferred location.
        preferred_location = identity_url

        response = flask.Response(
            response=jsonutils.dumps(
                {'versions': {
                    'values': list(versions.values())}}),
            mimetype=MimeTypes.JSON,
            status=http.client.MULTIPLE_CHOICES)
        response.headers['Location'] = preferred_location
        return response
Exemplo n.º 4
0
 def get(self):
     ENFORCER.enforce_call(action='identity:list_revoke_events')
     since = flask.request.args.get('since')
     last_fetch = None
     if since:
         try:
             last_fetch = timeutils.normalize_time(
                 timeutils.parse_isotime(since))
         except ValueError:
             raise exception.ValidationError(
                 message=_('invalidate date format %s') % since)
     # FIXME(notmorgan): The revocation events cannot have resource options
     # added to them or lazy-loaded relationships as long as to_dict
     # is called outside of an active session context. This API is unused
     # and should be deprecated in the near future. Fix this before adding
     # resource_options or any lazy-loaded relationships to the revocation
     # events themselves.
     events = PROVIDERS.revoke_api.list_events(last_fetch=last_fetch)
     # Build the links by hand as the standard controller calls require ids
     response = {'events': [event.to_dict() for event in events],
                 'links': {
                     'next': None,
                     'self': ks_flask.base_url(path='/OS-REVOKE/events'),
                     'previous': None}
                 }
     return response
Exemplo n.º 5
0
    def get(self):
        """Get possible system scopes for token.

        GET/HEAD /v3/auth/system
        """
        ENFORCER.enforce_call(action='identity:get_auth_system')
        user_id = self.auth_context.get('user_id')
        group_ids = self.auth_context.get('group_ids')

        user_assignments = []
        group_assignments = []

        if user_id:
            try:
                user_assignments = (
                    PROVIDERS.assignment_api.list_system_grants_for_user(
                        user_id)
                )
            except exception.UserNotFound:  # nosec
                # federated users have an id but they don't link to anything
                pass

        if group_ids:
            group_assignments = (
                PROVIDERS.assignment_api.list_system_grants_for_groups(
                    group_ids)
            )

        assignments = _combine_lists_uniquely(
            user_assignments, group_assignments)

        if assignments:
            response = {
                'system': [{'all': True}],
                'links': {
                    'self': ks_flask.base_url(path='auth/system')
                }
            }
        else:
            response = {
                'system': [],
                'links': {
                    'self': ks_flask.base_url(path='auth/system')
                }
            }
        return response
Exemplo n.º 6
0
    def get(self):
        """Get possible system scopes for token.

        GET/HEAD /v3/auth/system
        """
        ENFORCER.enforce_call(action='identity:get_auth_system')
        user_id = self.auth_context.get('user_id')
        group_ids = self.auth_context.get('group_ids')

        user_assignments = []
        group_assignments = []

        if user_id:
            try:
                user_assignments = (
                    PROVIDERS.assignment_api.list_system_grants_for_user(
                        user_id)
                )
            except exception.UserNotFound:  # nosec
                # federated users have an id but they don't link to anything
                pass

        if group_ids:
            group_assignments = (
                PROVIDERS.assignment_api.list_system_grants_for_groups(
                    group_ids)
            )

        assignments = _combine_lists_uniquely(
            user_assignments, group_assignments)

        if assignments:
            response = {
                'system': [{'all': True}],
                'links': {
                    'self': ks_flask.base_url(path='auth/system')
                }
            }
        else:
            response = {
                'system': [],
                'links': {
                    'self': ks_flask.base_url(path='auth/system')
                }
            }
        return response
Exemplo n.º 7
0
def _update_url_scheme():
    """Update request url scheme with base url scheme."""
    url = ks_flask.base_url()
    url_scheme = list(urlparse.urlparse(url))[0]
    req_url_list = list(urlparse.urlparse(flask.request.url))
    req_url_list[0] = url_scheme
    req_url = urlparse.urlunparse(req_url_list)
    return req_url
Exemplo n.º 8
0
def _update_url_scheme():
    """Update request url scheme with base url scheme."""
    url = ks_flask.base_url()
    url_scheme = list(urlparse.urlparse(url))[0]
    req_url_list = list(urlparse.urlparse(flask.request.url))
    req_url_list[0] = url_scheme
    req_url = urlparse.urlunparse(req_url_list)
    return req_url
Exemplo n.º 9
0
def build_implied_role_response_data(implied_role):
    return {
        'id': implied_role['id'],
        'links': {
            'self': ks_flask.base_url(
                path='/roles/%s' % implied_role['id'])
        },
        'name': implied_role['name']}
Exemplo n.º 10
0
 def _add_self_referential_link(cls, ref, collection_name=None):
     # NOTE(morgan): This should be refactored to have an OAuth1 API with
     # a sane prefix instead of overloading the "_add_self_referential_link"
     # method. This was chosen as it more closely mirrors the pre-flask
     # code (for transition).
     ref.setdefault('links', {})
     path = '/users/%(user_id)s/OS-OAUTH1/access_tokens' % {
         'user_id': ref.get('authorizing_user_id', '')
     }
     ref['links']['self'] = ks_flask.base_url(path) + '/' + ref['id']
Exemplo n.º 11
0
 def _add_self_referential_link(cls, ref, collection_name=None):
     # NOTE(morgan): This should be refactored to have an OAuth1 API with
     # a sane prefix instead of overloading the "_add_self_referential_link"
     # method. This was chosen as it more closely mirrors the pre-flask
     # code (for transition).
     ref.setdefault('links', {})
     path = '/users/%(user_id)s/OS-OAUTH1/access_tokens' % {
         'user_id': ref.get('authorizing_user_id', '')
     }
     ref['links']['self'] = ks_flask.base_url(path) + '/' + ref['id']
Exemplo n.º 12
0
    def _add_related_links(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', {})
        ref['links']['identity_provider'] = ks_flask.base_url(
            path=ref['idp_id'])
Exemplo n.º 13
0
    def _add_related_links(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', {})
        ref['links']['identity_provider'] = ks_flask.base_url(
            path=ref['idp_id'])
Exemplo n.º 14
0
    def _add_self_referential_link(cls, ref, collection_name=None):
        # NOTE(morgan): This should be refactored to have an EC2 Cred API with
        # a sane prefix instead of overloading the "_add_self_referential_link"
        # method. This was chosen as it more closely mirrors the pre-flask
        # code (for transition).
        path = '/users/%(user_id)s/credentials/OS-EC2/%(credential_id)s'

        url = ks_flask.base_url(path) % {
            'user_id': ref['user_id'],
            'credential_id': ref['access']}
        ref.setdefault('links', {})
        ref['links']['self'] = url
Exemplo n.º 15
0
    def _add_self_referential_link(cls, ref, collection_name=None):
        # NOTE(morgan): This should be refactored to have an EC2 Cred API with
        # a sane prefix instead of overloading the "_add_self_referential_link"
        # method. This was chosen as it more closely mirrors the pre-flask
        # code (for transition).
        path = '/users/%(user_id)s/credentials/OS-EC2/%(credential_id)s'

        url = ks_flask.base_url(path) % {
            'user_id': ref['user_id'],
            'credential_id': ref['access']}
        ref.setdefault('links', {})
        ref['links']['self'] = url
Exemplo n.º 16
0
def get_version_v3():
    if v3_mime_type_best_match() == MimeTypes.JSON_HOME:
        # RENDER JSON-Home form, we have a clever client who will
        # understand the JSON-Home document.
        content = json_home.JsonHomeResources.resources()
        return flask.Response(response=jsonutils.dumps(content),
                              mimetype=MimeTypes.JSON_HOME)
    else:
        identity_url = '%s/' % ks_flask.base_url()
        versions = _get_versions_list(identity_url)
        return flask.Response(
            response=jsonutils.dumps({'version': versions['v3']}),
            mimetype=MimeTypes.JSON)
Exemplo n.º 17
0
    def _add_related_links(ref):
        """Add URLs for entities related with Identity Provider.

        Add URLs pointing to:
        - protocols tied to the Identity Provider

        """
        base_path = ref['links'].get('self')
        if base_path is None:
            base_path = '/'.join(ks_flask.base_url(path='/%s' % ref['id']))

        for name in ['protocols']:
            ref['links'][name] = '/'.join([base_path, name])
Exemplo n.º 18
0
    def _add_related_links(ref):
        """Add URLs for entities related with Identity Provider.

        Add URLs pointing to:
        - protocols tied to the Identity Provider

        """
        base_path = ref['links'].get('self')
        if base_path is None:
            base_path = '/'.join(ks_flask.base_url(path='/%s' % ref['id']))

        for name in ['protocols']:
            ref['links'][name] = '/'.join([base_path, name])
Exemplo n.º 19
0
 def _get_implied_role(self, prior_role_id, implied_role_id):
     # Isolate this logic so it can be re-used without added enforcement
     PROVIDERS.role_api.get_implied_role(
         prior_role_id, implied_role_id)
     implied_role_ref = PROVIDERS.role_api.get_role(implied_role_id)
     response_json = shared.role_inference_response(prior_role_id)
     response_json['role_inference'][
         'implies'] = shared.build_implied_role_response_data(
         implied_role_ref)
     response_json['links'] = {
         'self': ks_flask.base_url(
             path='/roles/%(prior)s/implies/%(implies)s' % {
                 'prior': prior_role_id, 'implies': implied_role_id})}
     return response_json
Exemplo n.º 20
0
 def _get_implied_role(self, prior_role_id, implied_role_id):
     # Isolate this logic so it can be re-used without added enforcement
     PROVIDERS.role_api.get_implied_role(
         prior_role_id, implied_role_id)
     implied_role_ref = PROVIDERS.role_api.get_role(implied_role_id)
     response_json = shared.role_inference_response(prior_role_id)
     response_json['role_inference'][
         'implies'] = shared.build_implied_role_response_data(
         implied_role_ref)
     response_json['links'] = {
         'self': ks_flask.base_url(
             path='/roles/%(prior)s/implies/%(implies)s' % {
                 'prior': prior_role_id, 'implies': implied_role_id})}
     return response_json
Exemplo n.º 21
0
def get_version_v3():
    if 'v3' not in _VERSIONS:
        raise exception.VersionNotFound(version='v3')

    if v3_mime_type_best_match() == MimeTypes.JSON_HOME:
        # RENDER JSON-Home form, we have a clever client who will
        # understand the JSON-Home document.
        content = _v3_json_home_content()
        return flask.Response(response=jsonutils.dumps(content),
                              mimetype=MimeTypes.JSON_HOME)
    else:
        identity_url = '%s/' % ks_flask.base_url()
        versions = _get_versions_list(identity_url)
        return flask.Response(response=jsonutils.dumps(
            {'version': versions['v3']}),
                              mimetype=MimeTypes.JSON)
Exemplo n.º 22
0
    def put(self, project_id, value):
        """Add a single tag to a project.

        PUT /v3/projects/{project_id}/tags/{value}
        """
        ENFORCER.enforce_call(action='identity:create_project_tag')
        validation.lazy_validate(schema.project_tag_create, value)
        # Check if we will exceed the max number of tags on this project
        tags = PROVIDERS.resource_api.list_project_tags(project_id)
        tags.append(value)
        validation.lazy_validate(schema.project_tags_update, tags)
        PROVIDERS.resource_api.create_project_tag(
            project_id, value, initiator=self.audit_initiator)
        url = '/'.join((ks_flask.base_url(), project_id, 'tags', value))
        response = flask.make_response('', http_client.CREATED)
        response.headers['Location'] = url
        return response
Exemplo n.º 23
0
def get_versions():
    if v3_mime_type_best_match() == MimeTypes.JSON_HOME:
        # RENDER JSON-Home form, we have a clever client who will
        # understand the JSON-Home document.
        v3_json_home = _v3_json_home_content()
        json_home.translate_urls(v3_json_home, '/v3')
        return flask.Response(response=jsonutils.dumps(v3_json_home),
                              mimetype=MimeTypes.JSON_HOME)
    else:
        identity_url = '%s/' % ks_flask.base_url()
        versions = _get_versions_list(identity_url)
        return flask.Response(response=jsonutils.dumps(
            {'versions': {
                'values': list(versions.values())
            }}),
                              mimetype=MimeTypes.JSON,
                              status=http_client.MULTIPLE_CHOICES)
Exemplo n.º 24
0
def _format_token_entity(entity):

    formatted_entity = entity.copy()
    access_token_id = formatted_entity['id']
    user_id = formatted_entity.get('authorizing_user_id', '')
    if 'role_ids' in entity:
        formatted_entity.pop('role_ids')
    if 'access_secret' in entity:
        formatted_entity.pop('access_secret')

    url = ('/users/%(user_id)s/OS-OAUTH1/access_tokens/%(access_token_id)s'
           '/roles' % {'user_id': user_id,
                       'access_token_id': access_token_id})

    formatted_entity.setdefault('links', {})
    formatted_entity['links']['roles'] = (ks_flask.base_url(url))

    return formatted_entity
Exemplo n.º 25
0
def _normalize_trust_roles(trust):
    # fill in role data
    trust_full_roles = []
    for trust_role in trust.get('roles', []):
        trust_role = trust_role['id']
        try:
            matching_role = PROVIDERS.role_api.get_role(trust_role)
            full_role = ks_flask.ResourceBase.wrap_member(
                matching_role, collection_name='roles', member_name='role')
            trust_full_roles.append(full_role['role'])
        except exception.RoleNotFound:
            pass

    trust['roles'] = trust_full_roles
    trust['roles_links'] = {
        'self': ks_flask.base_url(path='/%s/roles' % trust['id']),
        'next': None,
        'previous': None}
Exemplo n.º 26
0
def _format_token_entity(entity):

    formatted_entity = entity.copy()
    access_token_id = formatted_entity['id']
    user_id = formatted_entity.get('authorizing_user_id', '')
    if 'role_ids' in entity:
        formatted_entity.pop('role_ids')
    if 'access_secret' in entity:
        formatted_entity.pop('access_secret')

    url = ('/users/%(user_id)s/OS-OAUTH1/access_tokens/%(access_token_id)s'
           '/roles' % {'user_id': user_id,
                       'access_token_id': access_token_id})

    formatted_entity.setdefault('links', {})
    formatted_entity['links']['roles'] = (ks_flask.base_url(url))

    return formatted_entity
Exemplo n.º 27
0
    def get(self, prior_role_id):
        """List Implied Roles.

        GET/HEAD /v3/roles/{prior_role_id}/implies
        """
        ENFORCER.enforce_call(action='identity:list_implied_roles',
                              build_target=_build_enforcement_target_ref)
        ref = PROVIDERS.role_api.list_implied_roles(prior_role_id)
        implied_ids = [r['implied_role_id'] for r in ref]
        response_json = shared.role_inference_response(prior_role_id)
        response_json['role_inference']['implies'] = []
        for implied_id in implied_ids:
            implied_role = PROVIDERS.role_api.get_role(implied_id)
            response_json['role_inference']['implies'].append(
                shared.build_implied_role_response_data(implied_role))
        response_json['links'] = {
            'self': ks_flask.base_url(
                path='/roles/%s/implies' % prior_role_id)}
        return response_json
Exemplo n.º 28
0
    def get(self, prior_role_id):
        """List Implied Roles.

        GET/HEAD /v3/roles/{prior_role_id}/implies
        """
        ENFORCER.enforce_call(action='identity:list_implied_roles',
                              build_target=_build_enforcement_target_ref)
        ref = PROVIDERS.role_api.list_implied_roles(prior_role_id)
        implied_ids = [r['implied_role_id'] for r in ref]
        response_json = shared.role_inference_response(prior_role_id)
        response_json['role_inference']['implies'] = []
        for implied_id in implied_ids:
            implied_role = PROVIDERS.role_api.get_role(implied_id)
            response_json['role_inference']['implies'].append(
                shared.build_implied_role_response_data(implied_role))
        response_json['links'] = {
            'self': ks_flask.base_url(path='/roles/%s/implies' % prior_role_id)
        }
        return response_json
Exemplo n.º 29
0
    def put(self, project_id, value):
        """Add a single tag to a project.

        PUT /v3/projects/{project_id}/tags/{value}
        """
        ENFORCER.enforce_call(action='identity:create_project_tag')
        validation.lazy_validate(schema.project_tag_create, value)
        # Check if we will exceed the max number of tags on this project
        tags = PROVIDERS.resource_api.list_project_tags(project_id)
        tags.append(value)
        validation.lazy_validate(schema.project_tags_update, tags)
        PROVIDERS.resource_api.create_project_tag(
            project_id,
            value,
            initiator=self.audit_initiator
        )
        url = '/'.join((ks_flask.base_url(), project_id, 'tags', value))
        response = flask.make_response('', http_client.CREATED)
        response.headers['Location'] = url
        return response
Exemplo n.º 30
0
    def get(self):
        """Get service catalog for token.

        GET/HEAD /v3/auth/catalog
        """
        ENFORCER.enforce_call(action='identity:get_auth_catalog')
        user_id = self.auth_context.get('user_id')
        project_id = self.auth_context.get('project_id')

        if not project_id:
            raise exception.Forbidden(
                _('A project-scoped token is required to produce a '
                  'service catalog.'))

        return {
            'catalog':
            PROVIDERS.catalog_api.get_v3_catalog(user_id, project_id),
            'links': {
                'self': ks_flask.base_url(path='auth/catalog')
            }
        }
Exemplo n.º 31
0
def _normalize_trust_roles(trust):
    # fill in role data
    trust_full_roles = []
    for trust_role in trust.get('roles', []):
        trust_role = trust_role['id']
        try:
            matching_role = PROVIDERS.role_api.get_role(trust_role)
            # TODO(morgan): Correct the cross-subsystem call here to allow
            # for local handling of the role wrapping
            full_role = assignment.controllers.RoleV3.wrap_member(
                {'environment': flask.request.environ},
                matching_role)['role']
            trust_full_roles.append(full_role)
        except exception.RoleNotFound:
            pass

    trust['roles'] = trust_full_roles
    trust['roles_links'] = {
        'self': ks_flask.base_url() + '/%s/roles' % trust['id'],
        'next': None,
        'previous': None}
Exemplo n.º 32
0
    def authenticate(self, auth_payload):
        """Turn a signed request with an access key into a keystone token."""
        response_data = {}
        oauth_headers = oauth.get_oauth_headers(flask.request.headers)
        access_token_id = oauth_headers.get('oauth_token')

        if not access_token_id:
            raise exception.ValidationError(
                attribute='oauth_token', target='request')

        acc_token = PROVIDERS.oauth_api.get_access_token(access_token_id)

        expires_at = acc_token['expires_at']
        if expires_at:
            now = timeutils.utcnow()
            expires = timeutils.normalize_time(
                timeutils.parse_isotime(expires_at))
            if now > expires:
                raise exception.Unauthorized(_('Access token is expired'))

        url = ks_flask.base_url(path=flask.request.path)
        access_verifier = oauth.ResourceEndpoint(
            request_validator=validator.OAuthValidator(),
            token_generator=oauth.token_generator)
        result, request = access_verifier.validate_protected_resource_request(
            url,
            http_method='POST',
            body=flask.request.args,
            headers=flask.request.headers,
            realms=None
        )
        if not result:
            msg = _('Could not validate the access token')
            raise exception.Unauthorized(msg)
        response_data['user_id'] = acc_token['authorizing_user_id']
        response_data['access_token_id'] = access_token_id
        response_data['project_id'] = acc_token['project_id']

        return base.AuthHandlerResponse(status=True, response_body=None,
                                        response_data=response_data)
Exemplo n.º 33
0
    def authenticate(self, auth_payload):
        """Turn a signed request with an access key into a keystone token."""
        response_data = {}
        oauth_headers = oauth.get_oauth_headers(flask.request.headers)
        access_token_id = oauth_headers.get('oauth_token')

        if not access_token_id:
            raise exception.ValidationError(attribute='oauth_token',
                                            target='request')

        acc_token = PROVIDERS.oauth_api.get_access_token(access_token_id)

        expires_at = acc_token['expires_at']
        if expires_at:
            now = timeutils.utcnow()
            expires = timeutils.normalize_time(
                timeutils.parse_isotime(expires_at))
            if now > expires:
                raise exception.Unauthorized(_('Access token is expired'))

        url = ks_flask.base_url(path=flask.request.path)
        access_verifier = oauth.ResourceEndpoint(
            request_validator=validator.OAuthValidator(),
            token_generator=oauth.token_generator)
        result, request = access_verifier.validate_protected_resource_request(
            url,
            http_method='POST',
            body=flask.request.args,
            headers=flask.request.headers,
            realms=None)
        if not result:
            msg = _('Could not validate the access token')
            raise exception.Unauthorized(msg)
        response_data['user_id'] = acc_token['authorizing_user_id']
        response_data['access_token_id'] = access_token_id
        response_data['project_id'] = acc_token['project_id']

        return base.AuthHandlerResponse(status=True,
                                        response_body=None,
                                        response_data=response_data)
Exemplo n.º 34
0
    def get(self):
        """Get service catalog for token.

        GET/HEAD /v3/auth/catalog
        """
        ENFORCER.enforce_call(action='identity:get_auth_catalog')
        user_id = self.auth_context.get('user_id')
        project_id = self.auth_context.get('project_id')

        if not project_id:
            raise exception.Forbidden(
                _('A project-scoped token is required to produce a '
                  'service catalog.'))

        return {
            'catalog': PROVIDERS.catalog_api.get_v3_catalog(
                user_id, project_id
            ),
            'links': {
                'self': ks_flask.base_url(path='auth/catalog')
            }
        }
Exemplo n.º 35
0
    def _format_entity(self, entity):
        """Format an assignment entity for API response.

        The driver layer returns entities as dicts containing the ids of the
        actor (e.g. user or group), target (e.g. domain or project) and role.
        If it is an inherited role, then this is also indicated. Examples:

        For a non-inherited expanded assignment from group membership:
        {'user_id': user_id,
         'project_id': project_id,
         'role_id': role_id,
         'indirect': {'group_id': group_id}}

        or, for a project inherited role:

        {'user_id': user_id,
         'project_id': project_id,
         'role_id': role_id,
         'indirect': {'project_id': parent_id}}

        or, for a role that was implied by a prior role:

        {'user_id': user_id,
         'project_id': project_id,
         'role_id': role_id,
         'indirect': {'role_id': prior role_id}}

        It is possible to deduce if a role assignment came from group
        membership if it has both 'user_id' in the main body of the dict and
        'group_id' in the 'indirect' subdict, as well as it is possible to
        deduce if it has come from inheritance if it contains both a
        'project_id' in the main body of the dict and 'parent_id' in the
        'indirect' subdict.

        This function maps this into the format to be returned via the API,
        e.g. for the second example above:

        {
            'user': {
                {'id': user_id}
            },
            'scope': {
                'project': {
                    {'id': project_id}
                },
                'OS-INHERIT:inherited_to': 'projects'
            },
            'role': {
                {'id': role_id}
            },
            'links': {
                'assignment': '/OS-INHERIT/projects/parent_id/users/user_id/'
                              'roles/role_id/inherited_to_projects'
            }
        }

        """
        formatted_link = ''
        formatted_entity = {'links': {}}
        inherited_assignment = entity.get('inherited_to_projects')

        if 'project_id' in entity:
            if 'project_name' in entity:
                formatted_entity['scope'] = {
                    'project': {
                        'id': entity['project_id'],
                        'name': entity['project_name'],
                        'domain': {
                            'id': entity['project_domain_id'],
                            'name': entity['project_domain_name']
                        }
                    }
                }
            else:
                formatted_entity['scope'] = {
                    'project': {
                        'id': entity['project_id']
                    }
                }

            if 'domain_id' in entity.get('indirect', {}):
                inherited_assignment = True
                formatted_link = ('/domains/%s' %
                                  entity['indirect']['domain_id'])
            elif 'project_id' in entity.get('indirect', {}):
                inherited_assignment = True
                formatted_link = ('/projects/%s' %
                                  entity['indirect']['project_id'])
            else:
                formatted_link = '/projects/%s' % entity['project_id']
        elif 'domain_id' in entity:
            if 'domain_name' in entity:
                formatted_entity['scope'] = {
                    'domain': {
                        'id': entity['domain_id'],
                        'name': entity['domain_name']
                    }
                }
            else:
                formatted_entity['scope'] = {
                    'domain': {
                        'id': entity['domain_id']
                    }
                }
            formatted_link = '/domains/%s' % entity['domain_id']
        elif 'system' in entity:
            formatted_link = '/system'
            formatted_entity['scope'] = {'system': entity['system']}

        if 'user_id' in entity:
            if 'user_name' in entity:
                formatted_entity['user'] = {
                    'id': entity['user_id'],
                    'name': entity['user_name'],
                    'domain': {
                        'id': entity['user_domain_id'],
                        'name': entity['user_domain_name']
                    }
                }
            else:
                formatted_entity['user'] = {'id': entity['user_id']}
            if 'group_id' in entity.get('indirect', {}):
                membership_url = (ks_flask.base_url(
                    path='/groups/%s/users/%s' %
                    (entity['indirect']['group_id'], entity['user_id'])))
                formatted_entity['links']['membership'] = membership_url
                formatted_link += '/groups/%s' % entity['indirect']['group_id']
            else:
                formatted_link += '/users/%s' % entity['user_id']
        elif 'group_id' in entity:
            if 'group_name' in entity:
                formatted_entity['group'] = {
                    'id': entity['group_id'],
                    'name': entity['group_name'],
                    'domain': {
                        'id': entity['group_domain_id'],
                        'name': entity['group_domain_name']
                    }
                }
            else:
                formatted_entity['group'] = {'id': entity['group_id']}
            formatted_link += '/groups/%s' % entity['group_id']

        if 'role_name' in entity:
            formatted_entity['role'] = {
                'id': entity['role_id'],
                'name': entity['role_name']
            }
            if 'role_domain_id' in entity and 'role_domain_name' in entity:
                formatted_entity['role'].update({
                    'domain': {
                        'id': entity['role_domain_id'],
                        'name': entity['role_domain_name']
                    }
                })
        else:
            formatted_entity['role'] = {'id': entity['role_id']}
        prior_role_link = ''
        if 'role_id' in entity.get('indirect', {}):
            formatted_link += '/roles/%s' % entity['indirect']['role_id']
            prior_role_link = ('/prior_role/%(prior)s/implies/%(implied)s' % {
                'prior': entity['role_id'],
                'implied': entity['indirect']['role_id']
            })
        else:
            formatted_link += '/roles/%s' % entity['role_id']

        if inherited_assignment:
            formatted_entity['scope']['OS-INHERIT:inherited_to'] = ('projects')
            formatted_link = ('/OS-INHERIT%s/inherited_to_projects' %
                              formatted_link)

        formatted_entity['links']['assignment'] = ks_flask.base_url(
            path=formatted_link)
        if prior_role_link:
            formatted_entity['links']['prior_role'] = (ks_flask.base_url(
                path=prior_role_link))

        return formatted_entity
Exemplo n.º 36
0
    def _format_entity(self, entity):
        """Format an assignment entity for API response.

        The driver layer returns entities as dicts containing the ids of the
        actor (e.g. user or group), target (e.g. domain or project) and role.
        If it is an inherited role, then this is also indicated. Examples:

        For a non-inherited expanded assignment from group membership:
        {'user_id': user_id,
         'project_id': project_id,
         'role_id': role_id,
         'indirect': {'group_id': group_id}}

        or, for a project inherited role:

        {'user_id': user_id,
         'project_id': project_id,
         'role_id': role_id,
         'indirect': {'project_id': parent_id}}

        or, for a role that was implied by a prior role:

        {'user_id': user_id,
         'project_id': project_id,
         'role_id': role_id,
         'indirect': {'role_id': prior role_id}}

        It is possible to deduce if a role assignment came from group
        membership if it has both 'user_id' in the main body of the dict and
        'group_id' in the 'indirect' subdict, as well as it is possible to
        deduce if it has come from inheritance if it contains both a
        'project_id' in the main body of the dict and 'parent_id' in the
        'indirect' subdict.

        This function maps this into the format to be returned via the API,
        e.g. for the second example above:

        {
            'user': {
                {'id': user_id}
            },
            'scope': {
                'project': {
                    {'id': project_id}
                },
                'OS-INHERIT:inherited_to': 'projects'
            },
            'role': {
                {'id': role_id}
            },
            'links': {
                'assignment': '/OS-INHERIT/projects/parent_id/users/user_id/'
                              'roles/role_id/inherited_to_projects'
            }
        }

        """
        formatted_link = ''
        formatted_entity = {'links': {}}
        inherited_assignment = entity.get('inherited_to_projects')

        if 'project_id' in entity:
            if 'project_name' in entity:
                formatted_entity['scope'] = {'project': {
                    'id': entity['project_id'],
                    'name': entity['project_name'],
                    'domain': {'id': entity['project_domain_id'],
                               'name': entity['project_domain_name']}}}
            else:
                formatted_entity['scope'] = {
                    'project': {'id': entity['project_id']}}

            if 'domain_id' in entity.get('indirect', {}):
                inherited_assignment = True
                formatted_link = ('/domains/%s' %
                                  entity['indirect']['domain_id'])
            elif 'project_id' in entity.get('indirect', {}):
                inherited_assignment = True
                formatted_link = ('/projects/%s' %
                                  entity['indirect']['project_id'])
            else:
                formatted_link = '/projects/%s' % entity['project_id']
        elif 'domain_id' in entity:
            if 'domain_name' in entity:
                formatted_entity['scope'] = {
                    'domain': {'id': entity['domain_id'],
                               'name': entity['domain_name']}}
            else:
                formatted_entity['scope'] = {
                    'domain': {'id': entity['domain_id']}}
            formatted_link = '/domains/%s' % entity['domain_id']
        elif 'system' in entity:
            formatted_link = '/system'
            formatted_entity['scope'] = {'system': entity['system']}

        if 'user_id' in entity:
            if 'user_name' in entity:
                formatted_entity['user'] = {
                    'id': entity['user_id'],
                    'name': entity['user_name'],
                    'domain': {'id': entity['user_domain_id'],
                               'name': entity['user_domain_name']}}
            else:
                formatted_entity['user'] = {'id': entity['user_id']}
            if 'group_id' in entity.get('indirect', {}):
                membership_url = (
                    ks_flask.base_url(path='/groups/%s/users/%s' % (
                        entity['indirect']['group_id'], entity['user_id'])))
                formatted_entity['links']['membership'] = membership_url
                formatted_link += '/groups/%s' % entity['indirect']['group_id']
            else:
                formatted_link += '/users/%s' % entity['user_id']
        elif 'group_id' in entity:
            if 'group_name' in entity:
                formatted_entity['group'] = {
                    'id': entity['group_id'],
                    'name': entity['group_name'],
                    'domain': {'id': entity['group_domain_id'],
                               'name': entity['group_domain_name']}}
            else:
                formatted_entity['group'] = {'id': entity['group_id']}
            formatted_link += '/groups/%s' % entity['group_id']

        if 'role_name' in entity:
            formatted_entity['role'] = {'id': entity['role_id'],
                                        'name': entity['role_name']}
            if 'role_domain_id' in entity and 'role_domain_name' in entity:
                formatted_entity['role'].update(
                    {'domain': {'id': entity['role_domain_id'],
                                'name': entity['role_domain_name']}})
        else:
            formatted_entity['role'] = {'id': entity['role_id']}
        prior_role_link = ''
        if 'role_id' in entity.get('indirect', {}):
            formatted_link += '/roles/%s' % entity['indirect']['role_id']
            prior_role_link = (
                '/prior_role/%(prior)s/implies/%(implied)s' % {
                    'prior': entity['role_id'],
                    'implied': entity['indirect']['role_id']
                })
        else:
            formatted_link += '/roles/%s' % entity['role_id']

        if inherited_assignment:
            formatted_entity['scope']['OS-INHERIT:inherited_to'] = (
                'projects')
            formatted_link = ('/OS-INHERIT%s/inherited_to_projects' %
                              formatted_link)

        formatted_entity['links']['assignment'] = ks_flask.base_url(
            path=formatted_link)
        if prior_role_link:
            formatted_entity['links']['prior_role'] = (
                ks_flask.base_url(path=prior_role_link))

        return formatted_entity