def post(self): """Create project. POST /v3/projects """ project = self.request_body_json.get('project', {}) target = {'project': project} ENFORCER.enforce_call( action='identity:create_project', target_attr=target ) validation.lazy_validate(schema.project_create, project) project = self._assign_unique_id(project) if not project.get('is_domain'): project = self._normalize_domain_id(project) # Our API requires that you specify the location in the hierarchy # unambiguously. This could be by parent_id or, if it is a top # level project, just by providing a domain_id. if not project.get('parent_id'): project['parent_id'] = project.get('domain_id') project = self._normalize_dict(project) try: ref = PROVIDERS.resource_api.create_project( project['id'], project, initiator=self.audit_initiator) except (exception.DomainNotFound, exception.ProjectNotFound) as e: raise exception.ValidationError(e) return self.wrap_member(ref), http_client.CREATED
def patch(self, role_id): """Update role. PATCH /v3/roles/{role_id} """ err = None role = {} try: role = PROVIDERS.role_api.get_role(role_id) except Exception as e: # nosec # We don't raise out here, we raise out after enforcement, this # ensures we do not leak role existence. Do nothing yet, process # enforcement before raising out an error. err = e finally: if err is not None or not self._is_domain_role(role): ENFORCER.enforce_call(action='identity:update_role') if err: raise err else: ENFORCER.enforce_call(action='identity:update_domain_role', member_target_type='role', member_target=role) request_body_role = self.request_body_json.get('role', {}) validation.lazy_validate(schema.role_update, request_body_role) self._require_matching_id(request_body_role) ref = PROVIDERS.role_api.update_role( role_id, request_body_role, initiator=self.audit_initiator) return self.wrap_member(ref)
def create_user(self, request, user): validation.lazy_validate(schema.user_create_v2, user) user = self._normalize_OSKSADM_password_on_request(user) user = self.normalize_username_in_request(user) user = self._normalize_dict(user) self.assert_admin(request) default_project_id = user.pop('tenantId', None) if default_project_id is not None: # Check to see if the project is valid before moving on. self.resource_api.get_project(default_project_id) user['default_project_id'] = default_project_id self.resource_api.ensure_default_domain_exists() # The manager layer will generate the unique ID for users user_ref = self._normalize_domain_id(request, user.copy()) new_user_ref = self.v3_to_v2_user( self.identity_api.create_user( user_ref, initiator=request.audit_initiator ) ) if default_project_id is not None: self.assignment_api.add_user_to_project(default_project_id, new_user_ref['id']) return {'user': new_user_ref}
def create_project_patched(self, request, project): validation.lazy_validate(schema.project_create, project) ref = self._assign_unique_id(self._normalize_dict(project)) if not ref.get('is_domain'): ref = self._normalize_domain_id(request, ref) LOG.warn( "Monkypatch in action! " "Hacking the new project id to equal the new project name.") ref['id'] = project['name'] # Our API requires that you specify the location in the hierarchy # unambiguously. This could be by parent_id or, if it is a top level # project, just by providing a domain_id. if not ref.get('parent_id'): ref['parent_id'] = ref.get('domain_id') initiator = notifications._get_request_audit_info(request.context_dict) try: ref = self.resource_api.create_project(ref['id'], ref, initiator=initiator) except (exception.DomainNotFound, exception.ProjectNotFound) as e: raise exception.ValidationError(e) return resource_controllers.ProjectV3.wrap_member(request.context_dict, ref)
def update_limits(self, request, limits): validation.lazy_validate(schema.limit_update, limits) refs = PROVIDERS.unified_limit_api.update_limits( [self._normalize_dict(limit) for limit in limits]) refs = LimitV3.wrap_collection(request.context_dict, refs) refs.pop("links") return refs
def create_service(self, request, service): validation.lazy_validate(schema.service_create, service) ref = self._assign_unique_id(self._normalize_dict(service)) ref = self.catalog_api.create_service( ref['id'], ref, initiator=request.audit_initiator ) return ServiceV3.wrap_member(request.context_dict, ref)
def create_endpoint(self, request, endpoint): validation.lazy_validate(schema.endpoint_create, endpoint) utils.check_endpoint_url(endpoint["url"]) ref = self._assign_unique_id(self._normalize_dict(endpoint)) ref = self._validate_endpoint_region(ref, request) ref = self.catalog_api.create_endpoint(ref["id"], ref, initiator=request.audit_initiator) return EndpointV3.wrap_member(request.context_dict, ref)
def create_credential(self, request, credential): validation.lazy_validate(schema.credential_create, credential) trust_id = self._get_trust_id_for_request(request.context_dict) ref = self._assign_unique_id(self._normalize_dict(credential), trust_id) ref = self.credential_api.create_credential(ref['id'], ref) return CredentialV3.wrap_member(request.context_dict, ref)
def update_service(self, request, service_id, service): validation.lazy_validate(schema.service_update, service) self._require_matching_id(service_id, service) ref = self.catalog_api.update_service( service_id, service, initiator=request.audit_initiator ) return ServiceV3.wrap_member(request.context_dict, ref)
def create_application_credential(self, request, user_id, application_credential): validation.lazy_validate(schema.application_credential_create, application_credential) token = request.auth_context['token'] self._check_unrestricted(token) if request.context.user_id != user_id: action = _("Cannot create an application credential for another " "user") raise exception.ForbiddenAction(action=action) project_id = request.context.project_id app_cred = self._assign_unique_id(application_credential) if not app_cred.get('secret'): app_cred['secret'] = self._generate_secret() app_cred['user_id'] = user_id app_cred['project_id'] = project_id app_cred['roles'] = self._normalize_role_list( app_cred.get('roles', token['roles'])) if app_cred.get('expires_at'): app_cred['expires_at'] = utils.parse_expiration_date( app_cred['expires_at']) app_cred = self._normalize_dict(app_cred) app_cred_api = PROVIDERS.application_credential_api try: ref = app_cred_api.create_application_credential( app_cred, initiator=request.audit_initiator ) except exception.RoleAssignmentNotFound as e: # Raise a Bad Request, not a Not Found, in accordance with the # API-SIG recommendations: # https://specs.openstack.org/openstack/api-wg/guidelines/http.html#failure-code-clarifications raise exception.ApplicationCredentialValidationError( detail=str(e)) return ApplicationCredentialV3.wrap_member(request.context_dict, ref)
def update_endpoint_group(self, request, endpoint_group_id, endpoint_group): """Update fixed values and/or extend the filters.""" validation.lazy_validate(schema.endpoint_group_update, endpoint_group) if "filters" in endpoint_group: self._require_valid_filter(endpoint_group) ref = self.catalog_api.update_endpoint_group(endpoint_group_id, endpoint_group) return EndpointGroupV3Controller.wrap_member(request.context_dict, ref)
def update_project(self, request, project_id, project): validation.lazy_validate(schema.project_update, project) self._require_matching_id(project_id, project) self._require_matching_domain_id(project_id, project, self.resource_api.get_project) initiator = notifications._get_request_audit_info(request.context_dict) ref = self.resource_api.update_project(project_id, project, initiator=initiator) return ProjectV3.wrap_member(request.context_dict, ref)
def update_consumer(self, request, consumer_id, consumer): validation.lazy_validate(schema.consumer_update, consumer) self._require_matching_id(consumer_id, consumer) ref = self._normalize_dict(consumer) initiator = notifications._get_request_audit_info(request.context_dict) ref = self.oauth_api.update_consumer(consumer_id, ref, initiator) return ConsumerCrudV3.wrap_member(request.context_dict, ref)
def create_consumer(self, request, consumer): validation.lazy_validate(schema.consumer_create, consumer) ref = self._assign_unique_id(self._normalize_dict(consumer)) consumer_ref = self.oauth_api.create_consumer( ref, initiator=request.audit_initiator ) return ConsumerCrudV3.wrap_member(request.context_dict, consumer_ref)
def patch(self, region_id): ENFORCER.enforce_call(action='identity:update_region') region = self.request_body_json.get('region') validation.lazy_validate(schema.region_update, region) self._require_matching_id(region) return self.wrap_member(PROVIDERS.catalog_api.update_region( region_id, region, initiator=self.audit_initiator))
def create_domain(self, request, domain): validation.lazy_validate(schema.domain_create, domain) ref = self._assign_unique_id(self._normalize_dict(domain)) ref = self.resource_api.create_domain( ref['id'], ref, initiator=request.audit_initiator ) return DomainV3.wrap_member(request.context_dict, ref)
def update_group(self, request, group_id, group): validation.lazy_validate(schema.group_update, group) self._require_matching_id(group_id, group) ref = PROVIDERS.identity_api.update_group( group_id, group, initiator=request.audit_initiator ) return GroupV3.wrap_member(request.context_dict, ref)
def update_region(self, request, region_id, region): validation.lazy_validate(schema.region_update, region) self._require_matching_id(region_id, region) ref = self.catalog_api.update_region(region_id, region, initiator=request.audit_initiator) return RegionV3.wrap_member(request.context_dict, ref)
def update_domain(self, request, domain_id, domain): validation.lazy_validate(schema.domain_update, domain) self._require_matching_id(domain_id, domain) ref = self.resource_api.update_domain( domain_id, domain, initiator=request.audit_initiator ) return DomainV3.wrap_member(request.context_dict, ref)
def create_service(self, request, OS_KSADM_service): validation.lazy_validate(schema.service_create_v2, OS_KSADM_service) self.assert_admin(request) service_id = uuid.uuid4().hex service_ref = OS_KSADM_service.copy() service_ref["id"] = service_id new_service_ref = self.catalog_api.create_service(service_id, service_ref, initiator=request.audit_initiator) return {"OS-KSADM:service": new_service_ref}
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)
def create_protocol(self, request, idp_id, protocol_id, protocol): validation.lazy_validate(schema.protocol_create, protocol) ref = self._normalize_dict(protocol) ref = self.federation_api.create_protocol(idp_id, protocol_id, ref) response = FederationProtocol.wrap_member(request.context_dict, ref) return wsgi.render_response( body=response, status=(http_client.CREATED, http_client.responses[http_client.CREATED]))
def update_endpoint(self, request, endpoint_id, endpoint): validation.lazy_validate(schema.endpoint_update, endpoint) self._require_matching_id(endpoint_id, endpoint) endpoint = self._validate_endpoint_region(endpoint.copy(), request) ref = self.catalog_api.update_endpoint(endpoint_id, endpoint, initiator=request.audit_initiator) return EndpointV3.wrap_member(request.context_dict, ref)
def create_limits(self, request, limits): validation.lazy_validate(schema.limit_create, limits) limits = [self._assign_unique_id(self._normalize_dict(limit)) for limit in limits] refs = PROVIDERS.unified_limit_api.create_limits(limits) refs = LimitV3.wrap_collection(request.context_dict, refs) refs.pop("links") return refs
def create_endpoint_group(self, request, endpoint_group): """Create an Endpoint Group with the associated filters.""" validation.lazy_validate(schema.endpoint_group_create, endpoint_group) ref = self._assign_unique_id(self._normalize_dict(endpoint_group)) self._require_attribute(ref, 'filters') self._require_valid_filter(ref) ref = self.catalog_api.create_endpoint_group(ref['id'], ref) return EndpointGroupV3Controller.wrap_member(request.context_dict, ref)
def update_project(self, request, tenant_id, tenant): validation.lazy_validate(schema.tenant_update, tenant) self.assert_admin(request) self._assert_not_is_domain_project(tenant_id) tenant_ref = self.resource_api.update_project( tenant_id, tenant, initiator=request.audit_initiator) return {'tenant': self.v3_to_v2_project(tenant_ref)}
def patch(self, service_id): ENFORCER.enforce_call(action='identity:update_service') service = self.request_body_json.get('service') validation.lazy_validate(schema.service_update, service) self._require_matching_id(service) ref = PROVIDERS.catalog_api.update_service( service_id, service, initiator=self.audit_initiator) return self.wrap_member(ref)
def create_endpoint(self, request, endpoint): validation.lazy_validate(schema.endpoint_create, endpoint) utils.check_endpoint_url(endpoint['url']) ref = self._assign_unique_id(self._normalize_dict(endpoint)) ref = self._validate_endpoint_region(ref, request.context_dict) initiator = notifications._get_request_audit_info(request.context_dict) ref = self.catalog_api.create_endpoint(ref['id'], ref, initiator) return EndpointV3.wrap_member(request.context_dict, ref)
def update_credential(self, request, credential_id, credential): validation.lazy_validate(schema.credential_update, credential) self._require_matching_id(credential_id, credential) ref = PROVIDERS.credential_api.update_credential( credential_id, credential ) return CredentialV3.wrap_member(request.context_dict, ref)
def post(self): ENFORCER.enforce_call(action='identity:create_service') service = self.request_body_json.get('service') validation.lazy_validate(schema.service_create, service) service = self._assign_unique_id(self._normalize_dict(service)) ref = PROVIDERS.catalog_api.create_service( service['id'], service, initiator=self.audit_initiator) return self.wrap_member(ref), http_client.CREATED
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 = self.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]))
def post(self): ENFORCER.enforce_call(action='identity:create_region') region = self.request_body_json.get('region') validation.lazy_validate(schema.region_create, region) region = self._normalize_dict(region) if not region.get('id'): # NOTE(morgan): even though we officially only support 'id' setting # via the PUT mechanism, this is historical and we need to support # both ways. region = self._assign_unique_id(region) ref = PROVIDERS.catalog_api.create_region( region, initiator=self.audit_initiator) return self.wrap_member(ref), http_client.CREATED
def create_region(self, request, region): validation.lazy_validate(schema.region_create, region) ref = self._normalize_dict(region) if not ref.get('id'): ref = self._assign_unique_id(ref) ref = self.catalog_api.create_region(ref, initiator=request.audit_initiator) return wsgi.render_response( RegionV3.wrap_member(request.context_dict, ref), status=(http_client.CREATED, http_client.responses[http_client.CREATED]))
def post(self): """Create group. POST /groups """ ENFORCER.enforce_call(action='identity:create_group') group = self.request_body_json.get('group', {}) validation.lazy_validate(schema.group_create, group) group = self._normalize_dict(group) group = self._normalize_domain_id(group) ref = PROVIDERS.identity_api.create_group( group, initiator=self.audit_initiator) return self.wrap_member(ref), http_client.CREATED
def patch(self, project_id): """Update project. PATCH /v3/projects/{project_id} """ ENFORCER.enforce_call(action='identity:update_project', build_target=_build_project_target_enforcement) project = self.request_body_json.get('project', {}) validation.lazy_validate(schema.project_update, project) self._require_matching_id(project) ref = PROVIDERS.resource_api.update_project( project_id, project, initiator=self.audit_initiator) return self.wrap_member(ref)
def put(self, request_token_id): ENFORCER.enforce_call(action='identity:authorize_request_token') roles = (flask.request.get_json(force=True, silent=True) or {}).get('roles', []) validation.lazy_validate(schema.request_token_authorize, roles) ctx = flask.request.environ[context.REQUEST_CONTEXT_ENV] if ctx.is_delegated_auth: raise exception.Forbidden( _('Cannot authorize a request token with a token issued via ' 'delegation.')) req_token = PROVIDERS.oauth_api.get_request_token(request_token_id) expires_at = req_token['expires_at'] if expires_at: now = timeutils.utcnow() expires = timeutils.normalize_time( timeutils.parse_isotime(expires_at)) if now > expires: raise exception.Unauthorized(_('Request token is expired')) authed_roles = _normalize_role_list(roles) # verify the authorizing user has the roles try: auth_context = flask.request.environ[ authorization.AUTH_CONTEXT_ENV] user_token_ref = auth_context['token'] except KeyError: LOG.warning("Couldn't find the auth context.") raise exception.Unauthorized() user_id = user_token_ref.user_id project_id = req_token['requested_project_id'] user_roles = PROVIDERS.assignment_api.get_roles_for_user_and_project( user_id, project_id) cred_set = set(user_roles) if not cred_set.issuperset(authed_roles): msg = _('authorizing user does not have role required') raise exception.Unauthorized(message=msg) # create least of just the id's for the backend role_ids = list(authed_roles) # finally authorize the token authed_token = PROVIDERS.oauth_api.authorize_request_token( request_token_id, user_id, role_ids) to_return = {'token': {'oauth_verifier': authed_token['verifier']}} return to_return
def create_project(self, request, tenant): tenant_ref = self._normalize_dict(tenant) validation.lazy_validate(schema.tenant_create, tenant) self.assert_admin(request) self.resource_api.ensure_default_domain_exists() tenant_ref['id'] = tenant_ref.get('id', uuid.uuid4().hex) tenant = self.resource_api.create_project( tenant_ref['id'], self._normalize_domain_id(request, tenant_ref), initiator=request.audit_initiator) return {'tenant': self.v3_to_v2_project(tenant)}
def put(self, project_id): """Update all tags associated with a given project. PUT /v3/projects/{project_id}/tags """ ENFORCER.enforce_call( action='identity:update_project_tags', build_target=_build_project_target_enforcement ) tags = self.request_body_json.get('tags', {}) validation.lazy_validate(schema.project_tags_update, tags) ref = PROVIDERS.resource_api.update_project_tags( project_id, tags, initiator=self.audit_initiator) return self.wrap_member(ref)
def post(self): ENFORCER.enforce_call(action='identity:create_endpoint_group') ep_group = self.request_body_json.get('endpoint_group', {}) validation.lazy_validate(schema.endpoint_group_create, ep_group) if not ep_group.get('filters'): # TODO(morgan): Make this not require substitution. Substitution is # done here due to String Freeze in the Rocky release. msg = _('%s field is required and cannot be empty') % 'filters' raise exception.ValidationError(message=msg) self._require_valid_filter(ep_group) ep_group = self._assign_unique_id(ep_group) return self.wrap_member( PROVIDERS.catalog_api.create_endpoint_group( ep_group['id'], ep_group)), http.client.CREATED
def patch(self, credential_id): # Update Credential ENFORCER.enforce_call( action='identity:update_credential', build_target=_build_target_enforcement ) PROVIDERS.credential_api.get_credential(credential_id) credential = self.request_body_json.get('credential', {}) validation.lazy_validate(schema.credential_update, credential) self._require_matching_id(credential) ref = PROVIDERS.credential_api.update_credential( credential_id, credential) return self.wrap_member(ref)
def post(self): """Create a user. POST /v3/users """ ENFORCER.enforce_call(action='identity:create_user') user_data = self.request_body_json.get('user', {}) validation.lazy_validate(schema.user_create, user_data) user_data = self._normalize_dict(user_data) user_data = self._normalize_domain_id(user_data) ref = PROVIDERS.identity_api.create_user( user_data, initiator=self.audit_initiator) return self.wrap_member(ref), http_client.CREATED
def post(self): # Create a new credential credential = self.request_body_json.get('credential', {}) target = {} target['credential'] = credential ENFORCER.enforce_call(action='identity:create_credential', target_attr=target) validation.lazy_validate(schema.credential_create, credential) trust_id = getattr(self.oslo_context, 'trust_id', None) ref = self._assign_unique_id(self._normalize_dict(credential), trust_id=trust_id) ref = PROVIDERS.credential_api.create_credential( ref['id'], ref, initiator=self.audit_initiator) return self.wrap_member(ref), http.client.CREATED
def post(self, user_id): user_data = self.request_body_json.get('user', {}) validation.lazy_validate(schema.password_change, user_data) try: PROVIDERS.identity_api.change_password( user_id=user_id, original_password=user_data['original_password'], new_password=user_data['password'], initiator=self.audit_initiator) except AssertionError as e: raise ks_exception.Unauthorized( _('Error when changing user password: %s') % e) return None, http.client.NO_CONTENT
def post(self, user_id): """Create application credential. POST /v3/users/{user_id}/application_credentials """ ENFORCER.enforce_call(action='identity:create_application_credential') app_cred_data = self.request_body_json.get('application_credential', {}) validation.lazy_validate(app_cred_schema.application_credential_create, app_cred_data) token = self.auth_context['token'] _check_unrestricted_application_credential(token) if self.oslo_context.user_id != user_id: action = _('Cannot create an application credential for another ' 'user.') raise ks_exception.ForbiddenAction(action=action) project_id = self.oslo_context.project_id app_cred_data = self._assign_unique_id(app_cred_data) if not app_cred_data.get('secret'): app_cred_data['secret'] = self._generate_secret() app_cred_data['user_id'] = user_id app_cred_data['project_id'] = project_id app_cred_data['roles'] = self._normalize_role_list( app_cred_data.get('roles', token.roles)) if app_cred_data.get('expires_at'): app_cred_data['expires_at'] = utils.parse_expiration_date( 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_api = PROVIDERS.application_credential_api try: ref = app_cred_api.create_application_credential( app_cred_data, initiator=self.audit_initiator) except ks_exception.RoleAssignmentNotFound as e: # Raise a Bad Request, not a Not Found, in accordance with the # API-SIG recommendations: # https://specs.openstack.org/openstack/api-wg/guidelines/http.html#failure-code-clarifications raise ks_exception.ApplicationCredentialValidationError( detail=str(e)) return self.wrap_member(ref), http.client.CREATED
def patch(self, user_id): """Update a user. PATCH /v3/users/{user_id} """ ENFORCER.enforce_call(action='identity:update_user', build_target=_build_user_target_enforcement) PROVIDERS.identity_api.get_user(user_id) user_data = self.request_body_json.get('user', {}) validation.lazy_validate(schema.user_update, user_data) self._require_matching_id(user_data) ref = PROVIDERS.identity_api.update_user( user_id, user_data, initiator=self.audit_initiator) return self.wrap_member(ref)
def create_saml_assertion(self, request, auth): """Exchange a scoped token for a SAML assertion. :param auth: Dictionary that contains a token and service provider ID :returns: SAML Assertion based on properties from the token """ validation.lazy_validate(schema.saml_create, auth) t = self._create_base_saml_assertion(request.context_dict, auth) (response, service_provider) = t headers = self._build_response_headers(service_provider) return wsgi.render_response( body=response.to_string(), status=(http_client.OK, http_client.responses[http_client.OK]), headers=headers)
def post(self): """Create role. POST /v3/roles """ role = self.request_body_json.get('role', {}) if self._is_domain_role(role): ENFORCER.enforce_call(action='identity:create_domain_role') else: ENFORCER.enforce_call(action='identity:create_role') validation.lazy_validate(schema.role_create, role) role = self._assign_unique_id(role) role = self._normalize_dict(role) ref = PROVIDERS.role_api.create_role( role['id'], role, initiator=self.audit_initiator) return self.wrap_member(ref), http_client.CREATED
def authorize_request_token(self, request, request_token_id, roles): """An authenticated user is going to authorize a request token. As a security precaution, the requested roles must match those in the request token. Because this is in a CLI-only world at the moment, there is not another easy way to make sure the user knows which roles are being requested before authorizing. """ validation.lazy_validate(schema.request_token_authorize, roles) if request.context.is_delegated_auth: raise exception.Forbidden( _('Cannot authorize a request token' ' with a token issued via delegation.')) req_token = PROVIDERS.oauth_api.get_request_token(request_token_id) expires_at = req_token['expires_at'] if expires_at: now = timeutils.utcnow() expires = timeutils.normalize_time( timeutils.parse_isotime(expires_at)) if now > expires: raise exception.Unauthorized(_('Request token is expired')) authed_roles = self._normalize_role_list(roles) # verify the authorizing user has the roles user_token = authorization.get_token_ref(request.context_dict) user_id = user_token.user_id project_id = req_token['requested_project_id'] user_roles = PROVIDERS.assignment_api.get_roles_for_user_and_project( user_id, project_id) cred_set = set(user_roles) if not cred_set.issuperset(authed_roles): msg = _('authorizing user does not have role required') raise exception.Unauthorized(message=msg) # create list of just the id's for the backend role_ids = list(authed_roles) # finally authorize the token authed_token = PROVIDERS.oauth_api.authorize_request_token( request_token_id, user_id, role_ids) to_return = {'token': {'oauth_verifier': authed_token['verifier']}} return to_return
def patch(self, credential_id): # Update Credential ENFORCER.enforce_call(action='identity:update_credential', build_target=_build_target_enforcement) current = PROVIDERS.credential_api.get_credential(credential_id) credential = self.request_body_json.get('credential', {}) validation.lazy_validate(schema.credential_update, credential) self._validate_blob_update_keys(current.copy(), credential.copy()) self._require_matching_id(credential) # Check that the user hasn't illegally modified the owner or scope target = {'credential': dict(current, **credential)} ENFORCER.enforce_call(action='identity:update_credential', target_attr=target) ref = PROVIDERS.credential_api.update_credential( credential_id, credential) return self.wrap_member(ref)
def create_role(self, request, role): validation.lazy_validate(schema.role_create_v2, role) role = self._normalize_dict(role) self.assert_admin(request) if role['name'] == CONF.member_role_name: # Use the configured member role ID when creating the configured # member role name. This avoids the potential of creating a # "member" role with an unexpected ID. role_id = CONF.member_role_id else: role_id = uuid.uuid4().hex role['id'] = role_id initiator = notifications._get_request_audit_info(request.context_dict) role_ref = self.role_api.create_role(role_id, role, initiator) return {'role': role_ref}
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
def create_trust(self, request, trust): """Create a new trust. The user creating the trust must be the trustor. """ validation.lazy_validate(schema.trust_create, trust) # Check if delegated via trust if request.context.is_delegated_auth: # Redelegation case src_trust_id = request.context.trust_id if not src_trust_id: raise exception.Forbidden( _('Redelegation allowed for delegated by trust only')) redelegated_trust = self.trust_api.get_trust(src_trust_id) else: redelegated_trust = None if trust.get('project_id') and not trust.get('roles'): msg = _('At least one role should be specified.') raise exception.Forbidden(msg) # the creating user must be the trustor if request.context.user_id != trust.get('trustor_user_id'): msg = _("The authenticated user should match the trustor.") raise exception.Forbidden(msg) # ensure trustee exists self.identity_api.get_user(trust['trustee_user_id']) all_roles = self.role_api.list_roles() # Normalize roles normalized_roles = self._normalize_role_list(trust, all_roles) trust['roles'] = normalized_roles self._require_trustor_has_role_in_project(trust) trust['expires_at'] = self._parse_expiration_date( trust.get('expires_at')) trust_id = uuid.uuid4().hex initiator = notifications._get_request_audit_info(request.context_dict) new_trust = self.trust_api.create_trust(trust_id, trust, normalized_roles, redelegated_trust, initiator) self._fill_in_roles(request.context_dict, new_trust, all_roles) return TrustV3.wrap_member(request.context_dict, new_trust)
def create_project(self, request, project): validation.lazy_validate(schema.project_create, project) ref = self._assign_unique_id(self._normalize_dict(project)) if not ref.get('is_domain'): ref = self._normalize_domain_id(request, ref) # Our API requires that you specify the location in the hierarchy # unambiguously. This could be by parent_id or, if it is a top level # project, just by providing a domain_id. if not ref.get('parent_id'): ref['parent_id'] = ref.get('domain_id') try: ref = PROVIDERS.resource_api.create_project( ref['id'], ref, initiator=request.audit_initiator) except (exception.DomainNotFound, exception.ProjectNotFound) as e: raise exception.ValidationError(e) return ProjectV3.wrap_member(request.context_dict, ref)
def put(self, region_id): ENFORCER.enforce_call(action='identity:create_region') region = self.request_body_json.get('region') validation.lazy_validate(schema.region_create, region) region = self._normalize_dict(region) if 'id' not in region: region['id'] = region_id elif region_id != region.get('id'): raise exception.ValidationError( _('Conflicting region IDs specified: ' '"%(url_id)s" != "%(ref_id)s"') % { 'url_id': region_id, 'ref_id': region['id'] }) ref = PROVIDERS.catalog_api.create_region( region, initiator=self.audit_initiator) return self.wrap_member(ref), http.client.CREATED
def validate_issue_token_auth(auth=None): if auth is None: return validation.lazy_validate(schema.token_issue, auth) user = auth['identity'].get('password', {}).get('user') if user is not None: if 'id' not in user and 'name' not in user: msg = _('Invalid input for field identity/password/user: '******'id or name must be present.') raise exception.SchemaValidationError(detail=msg) domain = user.get('domain') if domain is not None: if 'id' not in domain and 'name' not in domain: msg = _( 'Invalid input for field identity/password/user/domain: ' 'id or name must be present.') raise exception.SchemaValidationError(detail=msg) scope = auth.get('scope') if scope is not None and isinstance(scope, dict): project = scope.get('project') if project is not None: if 'id' not in project and 'name' not in project: msg = _( 'Invalid input for field scope/project: ' 'id or name must be present.') raise exception.SchemaValidationError(detail=msg) domain = project.get('domain') if domain is not None: if 'id' not in domain and 'name' not in domain: msg = _( 'Invalid input for field scope/project/domain: ' 'id or name must be present.') raise exception.SchemaValidationError(detail=msg) domain = scope.get('domain') if domain is not None: if 'id' not in domain and 'name' not in domain: msg = _( 'Invalid input for field scope/domain: ' 'id or name must be present.') raise exception.SchemaValidationError(detail=msg)
def post(self): """Exchange a scoped token for an ECP assertion. POST /v3/auth/OS-FEDERATION/saml2/ecp """ auth = self.request_body_json.get('auth') validation.lazy_validate(federation_schema.saml_create, auth) saml_assertion, service_provider = saml.create_base_saml_assertion( auth) relay_state_prefix = service_provider['relay_state_prefix'] generator = keystone_idp.ECPGenerator() ecp_assertion = generator.generate_ecp(saml_assertion, relay_state_prefix) headers = _build_response_headers(service_provider) response = flask.make_response(ecp_assertion.to_string(), http_client.OK) for header, value in headers: response.headers[header] = value return response
def create_ecp_assertion(self, request, auth): """Exchange a scoped token for an ECP assertion. :param auth: Dictionary that contains a token and service provider ID :returns: ECP Assertion based on properties from the token """ validation.lazy_validate(schema.saml_create, auth) t = self._create_base_saml_assertion(request.context_dict, auth) (saml_assertion, service_provider) = t relay_state_prefix = service_provider['relay_state_prefix'] generator = keystone_idp.ECPGenerator() ecp_assertion = generator.generate_ecp(saml_assertion, relay_state_prefix) headers = self._build_response_headers(service_provider) return wsgi.render_response( body=ecp_assertion.to_string(), status=(http_client.OK, http_client.responses[http_client.OK]), headers=headers)
def post(self, user_id): """Create application credential. POST /v3/users/{user_id}/application_credentials """ ENFORCER.enforce_call(action='identity:create_application_credential') app_cred_data = self.request_body_json.get('application_credential', {}) validation.lazy_validate(app_cred_schema.application_credential_create, app_cred_data) token = self.auth_context['token'] _check_unrestricted_application_credential(token) if self.oslo_context.user_id != user_id: action = _('Cannot create an application credential for another ' 'user.') raise ks_exception.ForbiddenAction(action=action) project_id = self.oslo_context.project_id app_cred_data = self._assign_unique_id(app_cred_data) if not app_cred_data.get('secret'): app_cred_data['secret'] = self._generate_secret() app_cred_data['user_id'] = user_id app_cred_data['project_id'] = project_id app_cred_data['roles'] = self._normalize_role_list( app_cred_data.get('roles', token.roles)) if app_cred_data.get('expires_at'): app_cred_data['expires_at'] = utils.parse_expiration_date( app_cred_data['expires_at']) app_cred_data = self._normalize_dict(app_cred_data) app_cred_api = PROVIDERS.application_credential_api try: ref = app_cred_api.create_application_credential( app_cred_data, initiator=self.audit_initiator) except ks_exception.RoleAssignmentNotFound as e: # Raise a Bad Request, not a Not Found, in accordance with the # API-SIG recommendations: # https://specs.openstack.org/openstack/api-wg/guidelines/http.html#failure-code-clarifications raise ks_exception.ApplicationCredentialValidationError( detail=str(e)) return self.wrap_member(ref), http_client.CREATED
def create_trust(self, request, trust): """Create a new trust. The user creating the trust must be the trustor. """ validation.lazy_validate(schema.trust_create, trust) token = request.auth_context['token'] self._check_unrestricted(token) redelegated_trust = self._find_redelegated_trust(request) if trust.get('project_id') and not trust.get('roles'): action = _('At least one role should be specified') raise exception.ForbiddenAction(action=action) # the creating user must be the trustor if request.context.user_id != trust.get('trustor_user_id'): action = _("The authenticated user should match the trustor") raise exception.ForbiddenAction(action=action) # ensure trustee exists PROVIDERS.identity_api.get_user(trust['trustee_user_id']) # Normalize roles normalized_roles = self._normalize_role_list(trust.get('roles', [])) trust['roles'] = normalized_roles self._require_trustor_has_role_in_project(trust) trust['expires_at'] = self._parse_expiration_date( trust.get('expires_at')) trust_id = uuid.uuid4().hex new_trust = PROVIDERS.trust_api.create_trust( trust_id, trust, normalized_roles, redelegated_trust, initiator=request.audit_initiator) self._fill_in_roles(request.context_dict, new_trust) return TrustV3.wrap_member(request.context_dict, new_trust)
def post(self): """Create domain. POST /v3/domains """ ENFORCER.enforce_call(action='identity:create_domain') domain = self.request_body_json.get('domain', {}) validation.lazy_validate(schema.domain_create, domain) domain_id = domain.get('explicit_domain_id') if domain_id is None: domain = self._assign_unique_id(domain) else: # Domain ID validation provided by PyCADF try: self._validate_id_format(domain_id) except ValueError: raise exception.DomainIdInvalid domain['id'] = domain_id domain = self._normalize_dict(domain) ref = PROVIDERS.resource_api.create_domain( domain['id'], domain, initiator=self.audit_initiator) return self.wrap_member(ref), http_client.CREATED