def create_domain_config(self, context, domain_id, config): original_config = self.domain_config_api.get_config_with_sensitive_info(domain_id) ref = self.domain_config_api.create_config(domain_id, config) if original_config: # Return status code 200, since config already existed return wsgi.render_response(body={self.member_name: ref}) else: return wsgi.render_response(body={self.member_name: ref}, status=("201", "Created"))
def get_versions(self, context): req_mime_type = v3_mime_type_best_match(context) if req_mime_type == MimeTypes.JSON_HOME: v3_json_home = request_v3_json_home("/v3") return wsgi.render_response(body=v3_json_home, headers=(("Content-Type", MimeTypes.JSON_HOME),)) versions = self._get_versions_list(context) return wsgi.render_response( status=(300, "Multiple Choices"), body={"versions": {"values": list(versions.values())}} )
def create_domain_config(self, request, domain_id, config): self.resource_api.get_domain(domain_id) original_config = ( self.domain_config_api.get_config_with_sensitive_info(domain_id)) ref = self.domain_config_api.create_config(domain_id, config) if original_config: # Return status code 200, since config already existed return wsgi.render_response(body={self.member_name: ref}) else: return wsgi.render_response(body={self.member_name: ref}, status=('201', 'Created'))
def get_version_v3(self, context): versions = self._get_versions_list(context) if "v3" in _VERSIONS: req_mime_type = v3_mime_type_best_match(context) if req_mime_type == MimeTypes.JSON_HOME: return wsgi.render_response( body=self._get_json_home_v3(), headers=(("Content-Type", MimeTypes.JSON_HOME),) ) return wsgi.render_response(body={"version": versions["v3"]}) else: raise exception.VersionNotFound(version="v3")
def get_version_v3(self, request): versions = self._get_versions_list(request.context_dict) if 'v3' in _VERSIONS: req_mime_type = v3_mime_type_best_match(request) if req_mime_type == MimeTypes.JSON_HOME: return wsgi.render_response( body=self._get_json_home_v3(), headers=(('Content-Type', MimeTypes.JSON_HOME),)) return wsgi.render_response(body={ 'version': versions['v3'] }) else: raise exception.VersionNotFound(version='v3')
def get_versions(self, context): req_mime_type = v3_mime_type_best_match(context) if req_mime_type == MimeTypes.JSON_HOME: v3_json_home = request_v3_json_home('/v3') return wsgi.render_response( body=v3_json_home, headers=(('Content-Type', MimeTypes.JSON_HOME),)) versions = self._get_versions_list(context) return wsgi.render_response(status=(300, 'Multiple Choices'), body={ 'versions': { 'values': versions.values() } })
def create_domain_config(self, request, domain_id, config): PROVIDERS.resource_api.get_domain(domain_id) original_config = ( PROVIDERS.domain_config_api.get_config_with_sensitive_info( domain_id ) ) ref = PROVIDERS.domain_config_api.create_config(domain_id, config) if original_config: # Return status code 200, since config already existed return wsgi.render_response(body={self.member_name: ref}) else: return wsgi.render_response( body={self.member_name: ref}, status=(http_client.CREATED, http_client.responses[http_client.CREATED]))
def create_identity_provider(self, context, idp_id, identity_provider): identity_provider = self._normalize_dict(identity_provider) identity_provider.setdefault('enabled', False) IdentityProvider.check_immutable_params(identity_provider) idp_ref = self.federation_api.create_idp(idp_id, identity_provider) response = IdentityProvider.wrap_member(context, idp_ref) return wsgi.render_response(body=response, status=('201', 'Created'))
def get_versions(self, context): versions = self._get_versions_list(context) return wsgi.render_response(status=(300, 'Multiple Choices'), body={ 'versions': { 'values': versions.values() } })
def create_saml_assertion(self, context, auth): """Exchange a scoped token for a SAML assertion. :param auth: Dictionary that contains a token id and region id :returns: SAML Assertion based on properties from the token """ issuer = CONF.saml.idp_entity_id region_id = auth['scope']['region']['id'] region = self.catalog_api.get_region(region_id) recipient = region['url'] token_id = auth['identity']['token']['id'] token_data = self.token_provider_api.validate_token(token_id) token_ref = token_model.KeystoneToken(token_id, token_data) subject = token_ref.user_name roles = token_ref.role_names if token_ref.project_scoped: project = token_ref.project_name else: raise ValueError(_('Use a project scoped token when attempting to' 'create a SAML assertion')) generator = keystone_idp.SAMLGenerator() response = generator.samlize_token(issuer, recipient, subject, roles, project) return wsgi.render_response(body=response.to_string(), status=('200', 'OK'), headers=[('Content-Type', 'text/xml')])
def create_saml_assertion(self, context, auth): """Exchange a scoped token for a SAML assertion. :param auth: Dictionary that contains a token id and region id :returns: SAML Assertion based on properties from the token """ issuer = CONF.saml.idp_entity_id region_id = auth["scope"]["region"]["id"] region = self.catalog_api.get_region(region_id) recipient = region["url"] token_id = auth["identity"]["token"]["id"] token_data = self.token_provider_api.validate_token(token_id) token_ref = token_model.KeystoneToken(token_id, token_data) subject = token_ref.user_name roles = token_ref.role_names if not token_ref.project_scoped: action = _("Use a project scoped token when attempting to create " "a SAML assertion") raise exception.ForbiddenAction(action=action) project = token_ref.project_name generator = keystone_idp.SAMLGenerator() response = generator.samlize_token(issuer, recipient, subject, roles, project) return wsgi.render_response( body=response.to_string(), status=("200", "OK"), headers=[("Content-Type", "text/xml")] )
def create_service_provider(self, context, sp_id, service_provider): service_provider = self._normalize_dict(service_provider) service_provider.setdefault('enabled', False) ServiceProvider.check_immutable_params(service_provider) sp_ref = self.federation_api.create_sp(sp_id, service_provider) response = ServiceProvider.wrap_member(context, sp_ref) return wsgi.render_response(body=response, status=('201', 'Created'))
def process_request(self, request): if request.environ.get('REMOTE_USER', None) is not None: # authenticated upstream return self.application if not self.is_applicable(request): return self.application params = request.environ.get(PARAMS_ENV) casCredentials = params["auth"]["casCredentials"] ticket = casCredentials.get("ticket", None) service = casCredentials.get("service", None) if not ticket: # this is asking for the server_url return wsgi.render_response({"cas_login_url": self._get_login_url(service)}) user_ref = self._validate_cas_ticket(ticket, service) if not user_ref: # Wrong authentication? return self.application user_name = user_ref["name"] try: self.identity_api.get_user_by_name( self.identity_api, user_name, self.domain) except exception.UserNotFound: if CONF.cas.autocreate_users: self._do_create_user(user_ref) request.environ['REMOTE_USER'] = user_name
def test_render_response_no_body(self): resp = wsgi.render_response() self.assertEqual(resp.status, "204 No Content") self.assertEqual(resp.status_int, 204) self.assertEqual(resp.body, b"") self.assertEqual(resp.headers.get("Content-Length"), "0") self.assertIsNone(resp.headers.get("Content-Type"))
def create_implied_role(self, request, prior_role_id, implied_role_id): self.role_api.create_implied_role(prior_role_id, implied_role_id) return wsgi.render_response( self.get_implied_role(request, prior_role_id, implied_role_id), status=(201, 'Created'))
def create_mapping(self, request, mapping_id, mapping): ref = self._normalize_dict(mapping) utils.validate_mapping_structure(ref) mapping_ref = self.federation_api.create_mapping(mapping_id, ref) response = MappingController.wrap_member(request.context_dict, mapping_ref) return wsgi.render_response(body=response, status=('201', 'Created'))
def test_render_response_no_body(self): resp = wsgi.render_response() self.assertEqual(resp.status, '204 No Content') self.assertEqual(resp.status_int, 204) self.assertEqual(resp.body, '') self.assertEqual(resp.headers.get('Content-Length'), '0') self.assertEqual(resp.headers.get('Content-Type'), None)
def create_protocol(self, context, idp_id, protocol_id, protocol): ref = self._normalize_dict(protocol) keys = self._mutable_parameters.copy() FederationProtocol.check_immutable_params(ref, keys=keys) ref = self.federation_api.create_protocol(idp_id, protocol_id, ref) response = FederationProtocol.wrap_member(context, ref) return wsgi.render_response(body=response, status=('201', 'Created'))
def test_render_response_no_body(self): resp = wsgi.render_response() self.assertEqual("204 No Content", resp.status) self.assertEqual(http_client.NO_CONTENT, resp.status_int) self.assertEqual(b"", resp.body) self.assertEqual("0", resp.headers.get("Content-Length")) self.assertIsNone(resp.headers.get("Content-Type"))
def get_versions(self, context): identity_url = self._get_identity_url(context) if not identity_url.endswith('/'): identity_url = identity_url + '/' return wsgi.render_response(status=(300, 'Multiple Choices'), body={ "versions": { "values": [{ "id": "v2.0", "status": "beta", "updated": "2011-11-19T00:00:00Z", "links": [{ "rel": "self", "href": identity_url, }, { "rel": "describedby", "type": "text/html", "href": "http://docs.openstack.org/api/openstack-" "identity-service/2.0/content/" }, { "rel": "describedby", "type": "application/pdf", "href": "http://docs.openstack.org/api/openstack-" "identity-service/2.0/identity-dev-guide-" "2.0.pdf" }], "media-types": [{ "base": "application/json", "type": "application/vnd.openstack.identity-v2.0" "+json" }] }] } })
def test_render_response_no_body(self): resp = wsgi.render_response() self.assertEqual('204 No Content', resp.status) self.assertEqual(http_client.NO_CONTENT, resp.status_int) self.assertEqual(b'', resp.body) self.assertEqual('0', resp.headers.get('Content-Length')) self.assertIsNone(resp.headers.get('Content-Type'))
def test_render_response_non_str_headers_converted(self): resp = wsgi.render_response(headers=[("Byte-Header", "Byte-Value"), (u"Unicode-Header", u"Unicode-Value")]) # assert that all headers are identified. self.assertThat(resp.headers, matchers.HasLength(4)) self.assertEqual("Unicode-Value", resp.headers.get("Unicode-Header")) # assert that unicode value is converted, the expected type is str # on both python2 and python3. self.assertEqual(str, type(resp.headers.get("Unicode-Header")))
def get_version_v3(self, context): versions = self._get_versions_list(context) if 'v3' in _VERSIONS: return wsgi.render_response(body={ 'version': versions['v3'] }) else: raise exception.VersionNotFound(version='v3')
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 render_token_data_response(self, token_id, token_data): """Render token data HTTP response. Note: We neither want nor need to send back the token id. """ status = (http_client.OK, http_client.responses[http_client.OK]) return wsgi.render_response(body=token_data, status=status)
def create_service_provider(self, context, sp_id, 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) ServiceProvider.check_immutable_params(service_provider) sp_ref = self.federation_api.create_sp(sp_id, service_provider) response = ServiceProvider.wrap_member(context, sp_ref) return wsgi.render_response(body=response, status=("201", "Created"))
def set_user_password(self, context, user_id, user): token_id = context.get("token_id") user_ref = self.token_manager_api.get_token(context=context, token_id=token_id) user_id_from_token = user_ref["user"]["id"] if user_id_from_token != user_id: return render_response(status=(403,"Not Authorized"), body={"error": {"message": "You are not authorized", "code": 403, "title": "Not Authorized"}}) update_dict = sanitize_dict(user, ["id", "password"]) self.identity_manager_api.update_user(context, user_id, update_dict) return render_response(status=(200,"OK"), body={"user":update_dict})
def create_region(self, context, region): ref = self._normalize_dict(region) if not ref.get("id"): ref = self._assign_unique_id(ref) ref = self.catalog_api.create_region(ref) return wsgi.render_response(RegionV3.wrap_member(context, ref), status=(201, "Created"))
def create_service_provider(self, request, sp_id, 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=('201', 'Created'))
def get_version_v2(self, request): versions = self._get_versions_list(request.context_dict) if 'v2.0' in _VERSIONS: return wsgi.render_response(body={ 'version': versions['v2.0'] }) else: raise exception.VersionNotFound(version='v2.0')
def test_render_response_no_body(self): resp = wsgi.render_response() self.assertEqual('204 No Content', resp.status) self.assertEqual(http_client.NO_CONTENT, resp.status_int) self.assertEqual(b'', resp.body) self.assertIsNone(resp.headers.get('Content-Type'))
def test_render_response_head_with_body(self): resp = wsgi.render_response({'id': uuid.uuid4().hex}, method='HEAD') self.assertEqual(http_client.OK, resp.status_int) self.assertEqual(b'', resp.body) self.assertNotEqual('0', resp.headers.get('Content-Length')) self.assertEqual('application/json', resp.headers.get('Content-Type'))
def create_authorization_code(self, context, user_auth): request_validator = validator.OAuth2Validator() server = core.Server(request_validator) # Validate request headers = context['headers'] body = user_auth uri = self.base_url(context, context['path']) http_method = 'POST' # Fetch authorized scopes from the request scopes = body.get('scopes') if not scopes: raise exception.ValidationError(attribute='scopes', target='request') # Fetch the credentials saved in the pre authorization phase client_id = body.get('client_id') if not client_id: raise exception.ValidationError(attribute='client_id', target='request') user_id = body.get('user_id') if not user_id: # Try to extract the user_id from the token user_id = self._extract_user_id_from_token(context['token_id']) credentials = self.oauth2_api.get_consumer_credentials( client_id, user_id) try: headers, body, status = server.create_authorization_response( uri, http_method, body, headers, scopes, credentials) # headers = {'Location': 'https://foo.com/welcome_back?code=somera # ndomstring&state=xyz '}, this might change to include suggested # headers related to cache best practices etc. # body = '', this might be set in future custom grant types # status = 302, suggested HTTP status code response = wsgi.render_response(body, status=(302, 'Found'), headers=headers.items()) LOG.info( 'OAUTH2: Created Authorization Code to consumer %(consumer)s \ for user %(user)s with scope %(scope)s. Redirecting to %(uri)s', { 'consumer': client_id, 'user': user_id, 'scope': scopes, 'uri': headers['Location'] }) return response except FatalClientError as e: # NOTE(garcianavalon) form the OAuthLib documentation and comments: # Errors during authorization where user should not be redirected back. # If the request fails due to a missing, invalid, or mismatching # redirection URI, or if the client identifier is missing or invalid, # the authorization server SHOULD inform the resource owner of the # error and MUST NOT automatically redirect the user-agent to the # invalid redirection URI. # Instead the user should be informed of the error by the provider itself. # Fatal errors occur when the client_id or redirect_uri is invalid or # missing. These must be caught by the provider and handled, how this # is done is outside of the scope of OAuthLib but showing an error # page describing the issue is a good ideaself. msg = e.json LOG.warning('OAUTH2: FatalClientError %s' % msg) raise exception.ValidationError(message=msg)
def create_mapping(self, context, mapping_id, mapping): ref = self._normalize_dict(mapping) utils.validate_mapping_structure(ref) mapping_ref = self.federation_api.create_mapping(mapping_id, ref) response = MappingController.wrap_member(context, mapping_ref) return wsgi.render_response(body=response, status=('201', 'Created'))
def create_access_token(self, context): headers = context['headers'] oauth_headers = oauth1.get_oauth_headers(headers) consumer_id = oauth_headers.get('oauth_consumer_key') request_token_id = oauth_headers.get('oauth_token') oauth_verifier = oauth_headers.get('oauth_verifier') if not consumer_id: raise exception.ValidationError(attribute='oauth_consumer_key', target='request') if not request_token_id: raise exception.ValidationError(attribute='oauth_token', target='request') if not oauth_verifier: raise exception.ValidationError(attribute='oauth_verifier', target='request') consumer = self.oauth_api._get_consumer(consumer_id) req_token = self.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')) consumer_obj = oauth1.Consumer(key=consumer['id'], secret=consumer['secret']) req_token_obj = oauth1.Token(key=req_token['id'], secret=req_token['request_secret']) req_token_obj.set_verifier(oauth_verifier) url = oauth1.rebuild_url(context['path']) oauth_request = oauth1.Request.from_request( http_method='POST', http_url=url, headers=context['headers'], query_string=context['query_string']) oauth_server = oauth1.Server() oauth_server.add_signature_method(oauth1.SignatureMethod_HMAC_SHA1()) params = oauth_server.verify_request(oauth_request, consumer_obj, token=req_token_obj) if len(params) != 0: msg = _('There should not be any non-oauth parameters') raise exception.Unauthorized(message=msg) if req_token['consumer_id'] != consumer_id: msg = _('provided consumer key does not match stored consumer key') raise exception.Unauthorized(message=msg) if req_token['verifier'] != oauth_verifier: msg = _('provided verifier does not match stored verifier') raise exception.Unauthorized(message=msg) if req_token['id'] != request_token_id: msg = _('provided request key does not match stored request key') raise exception.Unauthorized(message=msg) if not req_token.get('authorizing_user_id'): msg = _('Request Token does not have an authorizing user id') raise exception.Unauthorized(message=msg) access_token_duration = CONF.oauth1.access_token_duration token_ref = self.oauth_api.create_access_token(request_token_id, access_token_duration) result = ('oauth_token=%(key)s&oauth_token_secret=%(secret)s' % { 'key': token_ref['id'], 'secret': token_ref['access_secret'] }) if CONF.oauth1.access_token_duration: expiry_bit = '&oauth_expires_at=%s' % (token_ref['expires_at']) result += expiry_bit headers = [('Content-Type', 'application/x-www-urlformencoded')] response = wsgi.render_response(result, status=(201, 'Created'), headers=headers) return response
def create_implied_role(self, request, prior_role_id, implied_role_id): PROVIDERS.role_api.create_implied_role(prior_role_id, implied_role_id) return wsgi.render_response(self.get_implied_role( request, prior_role_id, implied_role_id), status=(201, 'Created'))
def update_domain_config( self, request, domain_id, config, group, option): PROVIDERS.resource_api.get_domain(domain_id) ref = PROVIDERS.domain_config_api.update_config( domain_id, config, group, option) return wsgi.render_response(body={self.member_name: ref})
def create_access_token(self, context): headers = context['headers'] oauth_headers = oauth1.get_oauth_headers(headers) consumer_id = oauth_headers.get('oauth_consumer_key') request_token_id = oauth_headers.get('oauth_token') oauth_verifier = oauth_headers.get('oauth_verifier') if not consumer_id: raise exception.ValidationError(attribute='oauth_consumer_key', target='request') if not request_token_id: raise exception.ValidationError(attribute='oauth_token', target='request') if not oauth_verifier: raise exception.ValidationError(attribute='oauth_verifier', target='request') req_token = self.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')) url = self.base_url(context, context['path']) access_verifier = oauth1.AccessTokenEndpoint( request_validator=validator.OAuthValidator(), token_generator=oauth1.token_generator) h, b, s = access_verifier.create_access_token_response( url, http_method='POST', body=context['query_string'], headers=headers) params = oauth1.extract_non_oauth_params(b) if len(params) != 0: msg = _('There should not be any non-oauth parameters') raise exception.Unauthorized(message=msg) if req_token['consumer_id'] != consumer_id: msg = _('provided consumer key does not match stored consumer key') raise exception.Unauthorized(message=msg) if req_token['verifier'] != oauth_verifier: msg = _('provided verifier does not match stored verifier') raise exception.Unauthorized(message=msg) if req_token['id'] != request_token_id: msg = _('provided request key does not match stored request key') raise exception.Unauthorized(message=msg) if not req_token.get('authorizing_user_id'): msg = _('Request Token does not have an authorizing user id') raise exception.Unauthorized(message=msg) access_token_duration = CONF.oauth1.access_token_duration initiator = notifications._get_request_audit_info(context) token_ref = self.oauth_api.create_access_token(request_token_id, access_token_duration, initiator) result = ('oauth_token=%(key)s&oauth_token_secret=%(secret)s' % { 'key': token_ref['id'], 'secret': token_ref['access_secret'] }) if CONF.oauth1.access_token_duration: expiry_bit = '&oauth_expires_at=%s' % (token_ref['expires_at']) result += expiry_bit headers = [('Content-Type', 'application/x-www-urlformencoded')] response = wsgi.render_response(result, status=(201, 'Created'), headers=headers) return response
def create_protocol(self, context, idp_id, protocol_id, protocol): ref = self._normalize_dict(protocol) FederationProtocol.check_immutable_params(ref) ref = self.federation_api.create_protocol(idp_id, protocol_id, ref) response = FederationProtocol.wrap_member(context, ref) return wsgi.render_response(body=response, status=('201', 'Created'))
def create_identity_provider(self, context, idp_id, identity_provider): identity_provider = self._normalize_dict(identity_provider) identity_provider.setdefault('enabled', False) idp_ref = self.federation_api.create_idp(idp_id, identity_provider) response = IdentityProvider.wrap_member(context, idp_ref) return wsgi.render_response(body=response, status=('201', 'Created'))
def create_access_token(self, context, token_request): request_validator = validator.OAuth2Validator() server = core.Server(request_validator) # Validate request headers = context['headers'] # NOTE(garcianavalon) Work around the keystone limitation with content types # Keystone only accepts JSON bodies while OAuth2.0 (RFC 6749) requires # x-www-form-urlencoded # We leave it like this to support future versions where the use of # x-www-form-urlencoded is accepted if headers['Content-Type'] == 'application/x-www-form-urlencoded': body = context['query_string'] elif headers['Content-Type'] == 'application/json': # TODO(garcianavalon) are these checks really necessary or # can we delegate them to oauthlib? grant_type = token_request.get('grant_type', None) if not grant_type: msg = _('grant_type missing in request body: {0}').format( token_request) raise exception.ValidationError(message=msg) if (grant_type == 'authorization_code' and not 'code' in token_request): msg = _('code missing in request body: %s') % token_request raise exception.ValidationError(message=msg) body = urllib.urlencode(token_request) else: msg = _( 'Content-Type: %s is not supported') % headers['Content-Type'] raise exception.ValidationError(message=msg) # check headers for authentication authmethod, auth = headers['Authorization'].split(' ', 1) if authmethod.lower() != 'basic': msg = _('Authorization error: %s. Only HTTP Basic is supported' ) % headers['Authorization'] raise exception.ValidationError(message=msg) uri = self.base_url(context, context['path']) http_method = 'POST' # Extra credentials you wish to include credentials = None # TODO(garcianavalon) headers, body, status = server.create_token_response( uri, http_method, body, headers, credentials) # headers will contain some suggested headers to add to your response # { # 'Content-Type': 'application/json', # 'Cache-Control': 'no-store', # 'Pragma': 'no-cache', # } # body will contain the token in json format and expiration from now # in seconds. # { # 'access_token': 'sldafh309sdf', # 'refresh_token': 'alsounguessablerandomstring', # 'expires_in': 3600, # 'scope': 'https://example.com/userProfile https://example.com/pictures', # 'token_type': 'Bearer' # } # body will contain an error code and possibly an error description if # the request failed, also in json format. # { # 'error': 'invalid_grant_type', # 'description': 'athorizatoin_coed is not a valid grant type' # } # status will be a suggested status code, 200 on ok, 400 on bad request # and 401 if client is trying to use an invalid authorization code, # fail to authenticate etc. # NOTE(garcianavalon) oauthlib returns the body as a JSON string already, # and the Keystone base controlers expect a dictionary body = json.loads(body) # TODO(garcianavalon) body contains scope instead of scopes and is only a # space separated string instead of a list. We can wait for a change in # Oauthlib or implement our own TokenProvider if status == 200: response = wsgi.render_response(body, status=(status, 'OK'), headers=headers.items()) LOG.info('OAUTH2: Created Access Token %s' % body['access_token']) return response # Build the error message and raise the corresponding error msg = _(body['error']) if hasattr(body, 'description'): msg = msg + ': ' + _(body['description']) LOG.warning('OAUTH2: Error creating Access Token %s' % msg) if status == 400: raise exception.ValidationError(message=msg) elif status == 401: # TODO(garcianavalon) custom exception class raise exception.Unauthorized(message=msg)
def test_render_response_custom_status(self): resp = wsgi.render_response( status=(http_client.NOT_IMPLEMENTED, http_client.responses[http_client.NOT_IMPLEMENTED])) self.assertEqual('501 Not Implemented', resp.status) self.assertEqual(http_client.NOT_IMPLEMENTED, resp.status_int)
def update_domain_config(self, context, domain_id, config, group, option): self.resource_api.get_domain(domain_id) ref = self.domain_config_api.update_config(domain_id, config, group, option) return wsgi.render_response(body={self.member_name: ref})
def create_request_token(self, context): headers = context['headers'] oauth_headers = oauth1.get_oauth_headers(headers) consumer_id = oauth_headers.get('oauth_consumer_key') requested_role_ids = headers.get('Requested-Role-Ids') requested_project_id = headers.get('Requested-Project-Id') if not consumer_id: raise exception.ValidationError(attribute='oauth_consumer_key', target='request') if not requested_role_ids: raise exception.ValidationError(attribute='requested_role_ids', target='request') if not requested_project_id: raise exception.ValidationError(attribute='requested_project_id', target='request') req_role_ids = requested_role_ids.split(',') consumer_ref = self.oauth_api._get_consumer(consumer_id) consumer = oauth1.Consumer(key=consumer_ref['id'], secret=consumer_ref['secret']) url = oauth1.rebuild_url(context['path']) oauth_request = oauth1.Request.from_request( http_method='POST', http_url=url, headers=context['headers'], query_string=context['query_string'], parameters={ 'requested_role_ids': requested_role_ids, 'requested_project_id': requested_project_id }) oauth_server = oauth1.Server() oauth_server.add_signature_method(oauth1.SignatureMethod_HMAC_SHA1()) params = oauth_server.verify_request(oauth_request, consumer, token=None) project_params = params['requested_project_id'] if project_params != requested_project_id: msg = _('Non-oauth parameter - project, do not match') raise exception.Unauthorized(message=msg) roles_params = params['requested_role_ids'] roles_params_list = roles_params.split(',') if roles_params_list != req_role_ids: msg = _('Non-oauth parameter - roles, do not match') raise exception.Unauthorized(message=msg) req_role_list = list() all_roles = self.identity_api.list_roles() for role in all_roles: for req_role in req_role_ids: if role['id'] == req_role: req_role_list.append(role) if len(req_role_list) == 0: msg = _('could not find matching roles for provided role ids') raise exception.Unauthorized(message=msg) json_roles = jsonutils.dumps(req_role_list) request_token_duration = CONF.oauth1.request_token_duration token_ref = self.oauth_api.create_request_token( consumer_id, json_roles, requested_project_id, request_token_duration) result = ('oauth_token=%(key)s&oauth_token_secret=%(secret)s' % { 'key': token_ref['id'], 'secret': token_ref['request_secret'] }) if CONF.oauth1.request_token_duration: expiry_bit = '&oauth_expires_at=%s' % token_ref['expires_at'] result += expiry_bit headers = [('Content-Type', 'application/x-www-urlformencoded')] response = wsgi.render_response(result, status=(201, 'Created'), headers=headers) return response
def get_version_v3(self, context): versions = self._get_versions_list(context) if 'v3' in _VERSIONS: return wsgi.render_response(body={'version': versions['v3']}) else: raise exception.VersionNotFound(version='v3')
def get_version_v2(self, request): versions = self._get_versions_list(request.context_dict) if 'v2.0' in _VERSIONS: return wsgi.render_response(body={'version': versions['v2.0']}) else: raise exception.VersionNotFound(version='v2.0')
def test_render_response_custom_status(self): resp = wsgi.render_response(status=(501, 'Not Implemented')) self.assertEqual(resp.status, '501 Not Implemented') self.assertEqual(resp.status_int, 501)
def test_render_response_custom_headers(self): resp = wsgi.render_response(headers=[('Custom-Header', 'Some-Value')]) self.assertEqual(resp.headers.get('Custom-Header'), 'Some-Value') self.assertEqual(resp.headers.get('Vary'), 'X-Auth-Token')
def create_access_token(self, request): oauth_headers = oauth1.get_oauth_headers(request.headers) consumer_id = oauth_headers.get('oauth_consumer_key') request_token_id = oauth_headers.get('oauth_token') oauth_verifier = oauth_headers.get('oauth_verifier') if not consumer_id: raise exception.ValidationError(attribute='oauth_consumer_key', target='request') if not request_token_id: raise exception.ValidationError(attribute='oauth_token', target='request') if not oauth_verifier: raise exception.ValidationError(attribute='oauth_verifier', target='request') 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')) url = self._update_url_scheme(request) access_verifier = oauth1.AccessTokenEndpoint( request_validator=validator.OAuthValidator(), token_generator=oauth1.token_generator) try: h, b, s = access_verifier.create_access_token_response( url, http_method='POST', body=request.params, headers=request.headers) except NotImplementedError: # Client key or request token validation failed, since keystone # does not yet support dummy client or dummy request token, # so we will raise Unauthorized exception instead. try: PROVIDERS.oauth_api.get_consumer(consumer_id) except exception.NotFound: msg = _('Provided consumer does not exist.') LOG.warning(msg) raise exception.Unauthorized(message=msg) if req_token['consumer_id'] != consumer_id: msg = _('Provided consumer key does not match stored ' 'consumer key.') LOG.warning(msg) raise exception.Unauthorized(message=msg) # The response body is empty since either one of the following reasons if not b: if req_token['verifier'] != oauth_verifier: msg = _('Provided verifier does not match stored verifier') else: msg = _('Invalid signature.') LOG.warning(msg) raise exception.Unauthorized(message=msg) # show the details of the failure. oauth1.validate_oauth_params(b) if not req_token.get('authorizing_user_id'): msg = _('Request Token does not have an authorizing user id.') LOG.warning(msg) raise exception.Unauthorized(message=msg) access_token_duration = CONF.oauth1.access_token_duration token_ref = PROVIDERS.oauth_api.create_access_token( request_token_id, access_token_duration, initiator=request.audit_initiator) result = ('oauth_token=%(key)s&oauth_token_secret=%(secret)s' % { 'key': token_ref['id'], 'secret': token_ref['access_secret'] }) if CONF.oauth1.access_token_duration > 0: expiry_bit = '&oauth_expires_at=%s' % (token_ref['expires_at']) result += expiry_bit headers = [('Content-Type', 'application/x-www-form-urlencoded')] response = wsgi.render_response( result, status=(http_client.CREATED, http_client.responses[http_client.CREATED]), headers=headers) return response
def test_render_response_head_with_body(self): resp = wsgi.render_response({'id': uuid.uuid4().hex}, method='HEAD') self.assertEqual(resp.status_int, 200) self.assertEqual(resp.body, b'') self.assertNotEqual(resp.headers.get('Content-Length'), '0') self.assertEqual(resp.headers.get('Content-Type'), 'application/json')
def create_implied_role(self, context, prior_role_id, implied_role_id): self.role_api.create_implied_role(prior_role_id, implied_role_id) return wsgi.render_response(self.get_implied_role( context, prior_role_id, implied_role_id), status=(201, 'Created'))