def _populate_token_dates(self, token_data, expires=None, trust=None, issued_at=None): if not expires: expires = provider.default_expire_time() if not isinstance(expires, six.string_types): expires = utils.isotime(expires, subsecond=True) token_data["expires_at"] = expires token_data["issued_at"] = issued_at or utils.isotime(subsecond=True)
def test_time_string_to_float_conversions(self): payload_cls = token_formatters.BasePayload original_time_str = utils.isotime(subsecond=True) time_obj = timeutils.parse_isotime(original_time_str) expected_time_float = ( (timeutils.normalize_time(time_obj) - datetime.datetime.utcfromtimestamp(0)).total_seconds()) # NOTE(lbragstad): The token expiration time for Fernet tokens is # passed in the payload of the token. This is different from the token # creation time, which is handled by Fernet and doesn't support # subsecond precision because it is a timestamp integer. self.assertIsInstance(expected_time_float, float) actual_time_float = payload_cls._convert_time_string_to_float( original_time_str) self.assertIsInstance(actual_time_float, float) self.assertEqual(expected_time_float, actual_time_float) # Generate expected_time_str using the same time float. Using # original_time_str from utils.isotime will occasionally fail due to # floating point rounding differences. time_object = datetime.datetime.utcfromtimestamp(actual_time_float) expected_time_str = utils.isotime(time_object, subsecond=True) actual_time_str = payload_cls._convert_float_to_time_string( actual_time_float) self.assertEqual(expected_time_str, actual_time_str)
def validate_token(self, token): """Validates a Fernet token and returns the payload attributes. :type token: six.text_type """ serialized_payload = self.unpack(token) versioned_payload = msgpack.unpackb(serialized_payload) version, payload = versioned_payload[0], versioned_payload[1:] for payload_class in PAYLOAD_CLASSES: if version == payload_class.version: ( user_id, methods, project_id, domain_id, expires_at, audit_ids, trust_id, federated_info, ) = payload_class.disassemble(payload) break else: # If the token_format is not recognized, raise ValidationError. raise exception.ValidationError(_("This is not a recognized Fernet payload version: %s") % version) # rather than appearing in the payload, the creation time is encoded # into the token format itself created_at = TokenFormatter.creation_time(token) created_at = ks_utils.isotime(at=created_at, subsecond=True) expires_at = timeutils.parse_isotime(expires_at) expires_at = ks_utils.isotime(at=expires_at, subsecond=True) return (user_id, methods, audit_ids, domain_id, project_id, trust_id, federated_info, created_at, expires_at)
def to_dict(self): keys = ['user_id', 'role_id', 'domain_id', 'domain_scope_id', 'project_id', 'audit_id', 'audit_chain_id', ] event = {key: self.__dict__[key] for key in keys if self.__dict__[key] is not None} if self.trust_id is not None: event['OS-TRUST:trust_id'] = self.trust_id if self.consumer_id is not None: event['OS-OAUTH1:consumer_id'] = self.consumer_id if self.access_token_id is not None: event['OS-OAUTH1:access_token_id'] = self.access_token_id if self.expires_at is not None: event['expires_at'] = utils.isotime(self.expires_at) if self.issued_before is not None: event['issued_before'] = utils.isotime(self.issued_before, subsecond=True) if self.revoked_at is not None: event['revoked_at'] = utils.isotime(self.revoked_at, subsecond=True) return event
def issue_token(self, user_id, method_names, expires_at=None, system=None, project_id=None, domain_id=None, auth_context=None, trust_id=None, app_cred_id=None, parent_audit_id=None): # NOTE(lbragstad): Grab a blank token object and use composition to # build the token according to the authentication and authorization # context. This cuts down on the amount of logic we have to stuff into # the TokenModel's __init__() method. token = token_model.TokenModel() token.methods = method_names token.system = system token.domain_id = domain_id token.project_id = project_id token.trust_id = trust_id token.application_credential_id = app_cred_id token.audit_id = random_urlsafe_str() token.parent_audit_id = parent_audit_id if auth_context: if constants.IDENTITY_PROVIDER in auth_context: token.is_federated = True token.protocol_id = auth_context[constants.PROTOCOL] idp_id = auth_context[constants.IDENTITY_PROVIDER] if isinstance(idp_id, bytes): idp_id = idp_id.decode('utf-8') token.identity_provider_id = idp_id token.user_id = auth_context['user_id'] token.federated_groups = [ {'id': group} for group in auth_context['group_ids'] ] if 'access_token_id' in auth_context: token.access_token_id = auth_context['access_token_id'] if not token.user_id: token.user_id = user_id token.user_domain_id = token.user['domain_id'] if isinstance(expires_at, datetime.datetime): token.expires_at = utils.isotime(expires_at, subsecond=True) if isinstance(expires_at, six.string_types): token.expires_at = expires_at elif not expires_at: token.expires_at = utils.isotime( default_expire_time(), subsecond=True ) token_id, issued_at = self.driver.generate_id_and_issued_at(token) token.mint(token_id, issued_at) # cache the token object and with ID if CONF.token.cache_on_issue or CONF.token.caching: # NOTE(amakarov): here and above TOKENS_REGION is to be passed # to serve as required positional "self" argument. It's ignored, # so I've put it here for convenience - any placeholder is fine. self._validate_token.set(token, self, token.id) return token
def _populate_token_dates(self, token_data, expires=None, issued_at=None): if not expires: expires = default_expire_time() if not isinstance(expires, six.string_types): expires = utils.isotime(expires, subsecond=True) token_data['expires_at'] = expires token_data['issued_at'] = (issued_at or utils.isotime(subsecond=True))
def _populate_token_dates(self, token_data, expires=None, trust=None, issued_at=None): if not expires: expires = provider.default_expire_time() elif isinstance(expires, six.string_types): expires = datetime.datetime.strptime(expires, const.TIME_FORMAT) token_data['expires_at'] = utils.isotime(expires, subsecond=True) if issued_at and isinstance(issued_at, six.string_types): issued = datetime.datetime.strptime(issued_at, const.TIME_FORMAT) issued_at = utils.isotime(issued, subsecond=True) token_data['issued_at'] = (issued_at or utils.isotime(subsecond=True))
def validate_token(self, token): """Validates a Fernet token and returns the payload attributes.""" # Convert v2 unicode token to a string if not isinstance(token, six.binary_type): token = token.encode('ascii') serialized_payload = self.unpack(token) versioned_payload = msgpack.unpackb(serialized_payload) version, payload = versioned_payload[0], versioned_payload[1:] # depending on the formatter, these may or may not be defined domain_id = None project_id = None trust_id = None federated_info = None if version == UnscopedPayload.version: (user_id, methods, expires_at, audit_ids) = ( UnscopedPayload.disassemble(payload)) elif version == DomainScopedPayload.version: (user_id, methods, domain_id, expires_at, audit_ids) = ( DomainScopedPayload.disassemble(payload)) elif version == ProjectScopedPayload.version: (user_id, methods, project_id, expires_at, audit_ids) = ( ProjectScopedPayload.disassemble(payload)) elif version == TrustScopedPayload.version: (user_id, methods, project_id, expires_at, audit_ids, trust_id) = ( TrustScopedPayload.disassemble(payload)) elif version == FederatedUnscopedPayload.version: (user_id, methods, expires_at, audit_ids, federated_info) = ( FederatedUnscopedPayload.disassemble(payload)) elif version == FederatedProjectScopedPayload.version: (user_id, methods, project_id, expires_at, audit_ids, federated_info) = FederatedProjectScopedPayload.disassemble( payload) elif version == FederatedDomainScopedPayload.version: (user_id, methods, domain_id, expires_at, audit_ids, federated_info) = FederatedDomainScopedPayload.disassemble( payload) else: # If the token_format is not recognized, raise ValidationError. raise exception.ValidationError(_( 'This is not a recognized Fernet payload version: %s') % version) # rather than appearing in the payload, the creation time is encoded # into the token format itself created_at = TokenFormatter.creation_time(token) created_at = ks_utils.isotime(at=created_at, subsecond=True) expires_at = timeutils.parse_isotime(expires_at) expires_at = ks_utils.isotime(at=expires_at, subsecond=True) return (user_id, methods, audit_ids, domain_id, project_id, trust_id, federated_info, created_at, expires_at)
def test_provider_token_expiration_validation(self): token = token_model.TokenModel() token.issued_at = "2013-05-21T00:02:43.941473Z" token.expires_at = utils.isotime(CURRENT_DATE) self.assertRaises(exception.TokenNotFound, PROVIDERS.token_provider_api._is_valid_token, token) token = token_model.TokenModel() token.issued_at = "2013-05-21T00:02:43.941473Z" token.expires_at = utils.isotime(timeutils.utcnow() + FUTURE_DELTA) self.assertIsNone(PROVIDERS.token_provider_api._is_valid_token(token))
def assertReportedEventMatchesRecorded(self, event, sample, before_time): after_time = timeutils.utcnow() event_issued_before = timeutils.normalize_time(timeutils.parse_isotime(event["issued_before"])) self.assertTrue( before_time <= event_issued_before, "invalid event issued_before time; %s is not later than %s." % (utils.isotime(event_issued_before, subsecond=True), utils.isotime(before_time, subsecond=True)), ) self.assertTrue( event_issued_before <= after_time, "invalid event issued_before time; %s is not earlier than %s." % (utils.isotime(event_issued_before, subsecond=True), utils.isotime(after_time, subsecond=True)), ) del (event["issued_before"]) self.assertEqual(sample, event)
def test_create_validate_federated_scoped_token_non_uuid_user_id(self): exp_user_id = hashlib.sha256().hexdigest() exp_methods = ['password'] exp_expires_at = utils.isotime(timeutils.utcnow(), subsecond=True) exp_audit_ids = [provider.random_urlsafe_str()] exp_federated_group_ids = [{'id': uuid.uuid4().hex}] exp_idp_id = uuid.uuid4().hex exp_protocol_id = uuid.uuid4().hex exp_project_id = uuid.uuid4().hex token_formatter = token_formatters.TokenFormatter() token = token_formatter.create_token(user_id=exp_user_id, expires_at=exp_expires_at, audit_ids=exp_audit_ids, payload_class=token_formatters.FederatedProjectScopedPayload, methods=exp_methods, federated_group_ids=exp_federated_group_ids, identity_provider_id=exp_idp_id, protocol_id=exp_protocol_id, project_id=exp_project_id) (user_id, methods, audit_ids, system, domain_id, project_id, trust_id, federated_group_ids, identity_provider_id, protocol_id, access_token_id, app_cred_id, issued_at, expires_at) = token_formatter.validate_token(token) self.assertEqual(exp_user_id, user_id) self.assertTrue(isinstance(user_id, six.string_types)) self.assertEqual(exp_methods, methods) self.assertEqual(exp_audit_ids, audit_ids) self.assertEqual(exp_project_id, project_id) self.assertEqual(exp_federated_group_ids, federated_group_ids) self.assertEqual(exp_idp_id, identity_provider_id) self.assertEqual(exp_protocol_id, protocol_id)
def setUp(self): super(TestTokenSerialization, self).setUp() self.admin_user_id = self.bootstrapper.admin_user_id self.admin_username = self.bootstrapper.admin_username self.admin_password = self.bootstrapper.admin_password self.project_id = self.bootstrapper.project_id self.project_name = self.bootstrapper.project_name self.admin_role_id = self.bootstrapper.admin_role_id self.member_role_id = self.bootstrapper.member_role_id self.reader_role_id = self.bootstrapper.reader_role_id self.token_id = uuid.uuid4().hex issued_at = datetime.datetime.utcnow() self.issued_at = ks_utils.isotime(at=issued_at, subsecond=True) # Reach into the cache registry and pull out an instance of the # _TokenModelHandler so that we can interact and test it directly (as # opposed to using PROVIDERS or managers to invoke it). token_handler_id = token_model._TokenModelHandler.identity self.token_handler = _context_cache._registry.get(token_handler_id) self.exp_token = token_model.TokenModel() self.exp_token.user_id = self.admin_user_id self.exp_token.project_id = self.project_id self.exp_token.mint(self.token_id, self.issued_at)
def test_unable_to_verify_token_with_missing_public_key(self): # create token, signing with private key token = token_model.TokenModel() token.methods = ['password'] token.user_id = uuid.uuid4().hex token.audit_id = provider.random_urlsafe_str() token.expires_at = utils.isotime( provider.default_expire_time(), subsecond=True ) token_id, issued_at = self.provider.generate_id_and_issued_at(token) # remove the public key for the token we just created current_pub_key = os.path.join( CONF.jwt_tokens.jws_public_key_repository, 'public.pem' ) os.remove(current_pub_key) # create additional public keys for _ in range(2): private_key_path = os.path.join( CONF.jwt_tokens.jws_private_key_repository, uuid.uuid4().hex ) pub_key_path = os.path.join( CONF.jwt_tokens.jws_public_key_repository, uuid.uuid4().hex ) jwt_utils.create_jws_keypair(private_key_path, pub_key_path) # validate token and ensure it returns a 404 self.assertRaises( exception.TokenNotFound, self.provider.validate_token, token_id )
def test_federated_domain_scoped_payload(self): exp_user_id = 'someNonUuidUserId' exp_methods = ['token'] exp_domain_id = uuid.uuid4().hex exp_expires_at = utils.isotime(timeutils.utcnow(), subsecond=True) exp_audit_ids = [provider.random_urlsafe_str()] exp_federated_info = {'group_ids': [{'id': 'someNonUuidGroupId'}], 'idp_id': uuid.uuid4().hex, 'protocol_id': uuid.uuid4().hex} payload = token_formatters.FederatedDomainScopedPayload.assemble( exp_user_id, exp_methods, exp_domain_id, exp_expires_at, exp_audit_ids, exp_federated_info) (user_id, methods, domain_id, expires_at, audit_ids, federated_info) = ( token_formatters.FederatedDomainScopedPayload.disassemble( payload)) self.assertEqual(exp_user_id, user_id) self.assertEqual(exp_methods, methods) self.assertEqual(exp_domain_id, domain_id) self.assertEqual(exp_expires_at, expires_at) self.assertEqual(exp_audit_ids, audit_ids) self.assertDictEqual(exp_federated_info, federated_info)
def _test_federated_payload_with_ids(self, exp_user_id, exp_group_id): exp_methods = ['password'] exp_expires_at = utils.isotime(timeutils.utcnow(), subsecond=True) exp_audit_ids = [provider.random_urlsafe_str()] exp_federated_info = {'group_ids': [{'id': exp_group_id}], 'idp_id': uuid.uuid4().hex, 'protocol_id': uuid.uuid4().hex} payload = token_formatters.FederatedUnscopedPayload.assemble( exp_user_id, exp_methods, exp_expires_at, exp_audit_ids, exp_federated_info) (user_id, methods, expires_at, audit_ids, federated_info) = ( token_formatters.FederatedUnscopedPayload.disassemble(payload)) self.assertEqual(exp_user_id, user_id) self.assertEqual(exp_methods, methods) self.assertEqual(exp_expires_at, expires_at) self.assertEqual(exp_audit_ids, audit_ids) self.assertEqual(exp_federated_info['group_ids'][0]['id'], federated_info['group_ids'][0]['id']) self.assertEqual(exp_federated_info['idp_id'], federated_info['idp_id']) self.assertEqual(exp_federated_info['protocol_id'], federated_info['protocol_id'])
def list_trusts(self, request): trusts = [] trustor_user_id = request.params.get('trustor_user_id') trustee_user_id = request.params.get('trustee_user_id') if not request.params: self.assert_admin(request) trusts += self.trust_api.list_trusts() action = _('Cannot list trusts for another user') if trustor_user_id: if trustor_user_id != request.context.user_id: raise exception.Forbidden(action=action) trusts += self.trust_api.list_trusts_for_trustor(trustor_user_id) if trustee_user_id: if trustee_user_id != request.context.user_id: raise exception.ForbiddenAction(action=action) trusts += self.trust_api.list_trusts_for_trustee(trustee_user_id) for trust in trusts: # get_trust returns roles, list_trusts does not # It seems in some circumstances, roles does not # exist in the query response, so check first if 'roles' in trust: del trust['roles'] if trust.get('expires_at') is not None: trust['expires_at'] = utils.isotime(trust['expires_at'], subsecond=True) return TrustV3.wrap_collection(request.context_dict, trusts)
def _test_payload(self, payload_class, exp_user_id=None, exp_methods=None, exp_system=None, exp_project_id=None, exp_domain_id=None, exp_trust_id=None, exp_federated_info=None, exp_access_token_id=None, exp_app_cred_id=None): exp_user_id = exp_user_id or uuid.uuid4().hex exp_methods = exp_methods or ['password'] exp_expires_at = utils.isotime(timeutils.utcnow(), subsecond=True) exp_audit_ids = [common.random_urlsafe_str()] payload = payload_class.assemble( exp_user_id, exp_methods, exp_system, exp_project_id, exp_domain_id, exp_expires_at, exp_audit_ids, exp_trust_id, exp_federated_info, exp_access_token_id, exp_app_cred_id) (user_id, methods, system, project_id, domain_id, expires_at, audit_ids, trust_id, federated_info, access_token_id, app_cred_id) = payload_class.disassemble(payload) self.assertEqual(exp_user_id, user_id) self.assertEqual(exp_methods, methods) self.assertTimestampsEqual(exp_expires_at, expires_at) self.assertEqual(exp_audit_ids, audit_ids) self.assertEqual(exp_system, system) self.assertEqual(exp_project_id, project_id) self.assertEqual(exp_domain_id, domain_id) self.assertEqual(exp_trust_id, trust_id) self.assertEqual(exp_access_token_id, access_token_id) self.assertEqual(exp_app_cred_id, app_cred_id) if exp_federated_info: self.assertDictEqual(exp_federated_info, federated_info) else: self.assertIsNone(federated_info)
def _test_federated_payload_with_ids(self, exp_user_id, exp_group_id): exp_methods = ["password"] exp_expires_at = utils.isotime(timeutils.utcnow(), subsecond=True) exp_audit_ids = [provider.random_urlsafe_str()] exp_federated_info = { "group_ids": [{"id": exp_group_id}], "idp_id": uuid.uuid4().hex, "protocol_id": uuid.uuid4().hex, } project_id = None domain_id = None trust_id = None payload = token_formatters.FederatedUnscopedPayload.assemble( exp_user_id, exp_methods, project_id, domain_id, exp_expires_at, exp_audit_ids, trust_id, exp_federated_info ) ( user_id, methods, project_id, domain_id, expires_at, audit_ids, trust_id, federated_info, ) = token_formatters.FederatedUnscopedPayload.disassemble(payload) self.assertEqual(exp_user_id, user_id) self.assertEqual(exp_methods, methods) self.assertTimestampsEqual(exp_expires_at, expires_at) self.assertEqual(exp_audit_ids, audit_ids) self.assertEqual(exp_federated_info["group_ids"][0]["id"], federated_info["group_ids"][0]["id"]) self.assertEqual(exp_federated_info["idp_id"], federated_info["idp_id"]) self.assertEqual(exp_federated_info["protocol_id"], federated_info["protocol_id"])
def create_request_token(self, consumer_id, project_id, token_duration, request_token_id=None, request_token_secret=None): if request_token_id is None: request_token_id = uuid.uuid4().hex if request_token_secret is None: request_token_secret = uuid.uuid4().hex expiry_date = None if token_duration: now = timeutils.utcnow() future = now + datetime.timedelta(seconds=token_duration) expiry_date = utils.isotime(future, subsecond=True) ref = {} ref['id'] = request_token_id ref['request_secret'] = request_token_secret ref['verifier'] = None ref['authorizing_user_id'] = None ref['requested_project_id'] = project_id ref['role_ids'] = None ref['consumer_id'] = consumer_id ref['expires_at'] = expiry_date session = sql.get_session() with session.begin(): token_ref = RequestToken.from_dict(ref) session.add(token_ref) return token_ref.to_dict()
def test_federated_payload_with_non_uuid_ids(self): exp_user_id = 'someNonUuidUserId' exp_methods = ['password'] exp_expires_at = utils.isotime(timeutils.utcnow()) exp_audit_ids = [provider.random_urlsafe_str()] exp_federated_info = {'group_ids': [{'id': 'someNonUuidGroupId'}], 'idp_id': uuid.uuid4().hex, 'protocol_id': uuid.uuid4().hex} payload = token_formatters.FederatedPayload.assemble( exp_user_id, exp_methods, exp_expires_at, exp_audit_ids, exp_federated_info) (user_id, methods, expires_at, audit_ids, federated_info) = ( token_formatters.FederatedPayload.disassemble(payload)) self.assertEqual(exp_user_id, user_id) self.assertEqual(exp_methods, methods) self.assertEqual(exp_expires_at, expires_at) self.assertEqual(exp_audit_ids, audit_ids) self.assertEqual(exp_federated_info['group_ids'][0]['id'], federated_info['group_ids'][0]['id']) self.assertEqual(exp_federated_info['idp_id'], federated_info['idp_id']) self.assertEqual(exp_federated_info['protocol_id'], federated_info['protocol_id'])
def _test_domain_scoped_payload_with_user_id(self, exp_user_id): exp_methods = ["password"] exp_domain_id = uuid.uuid4().hex exp_expires_at = utils.isotime(timeutils.utcnow(), subsecond=True) exp_audit_ids = [provider.random_urlsafe_str()] project_id = None trust_id = None federated_info = None payload = token_formatters.DomainScopedPayload.assemble( exp_user_id, exp_methods, project_id, exp_domain_id, exp_expires_at, exp_audit_ids, trust_id, federated_info ) ( user_id, methods, project_id, domain_id, expires_at, audit_ids, trust_id, federated_info, ) = token_formatters.DomainScopedPayload.disassemble(payload) self.assertEqual(exp_user_id, user_id) self.assertEqual(exp_methods, methods) self.assertEqual(exp_domain_id, domain_id) self.assertTimestampsEqual(exp_expires_at, expires_at) self.assertEqual(exp_audit_ids, audit_ids)
def create_access_token(self, request_id, access_token_duration): access_token_id = uuid.uuid4().hex access_token_secret = uuid.uuid4().hex with sql.session_for_write() as session: req_token_ref = self._get_request_token(session, request_id) token_dict = req_token_ref.to_dict() expiry_date = None if access_token_duration: now = timeutils.utcnow() future = (now + datetime.timedelta(seconds=access_token_duration)) expiry_date = utils.isotime(future, subsecond=True) # add Access Token ref = {} ref['id'] = access_token_id ref['access_secret'] = access_token_secret ref['authorizing_user_id'] = token_dict['authorizing_user_id'] ref['project_id'] = token_dict['requested_project_id'] ref['role_ids'] = token_dict['role_ids'] ref['consumer_id'] = token_dict['consumer_id'] ref['expires_at'] = expiry_date token_ref = AccessToken.from_dict(ref) session.add(token_ref) # remove request token, it's been used session.delete(req_token_ref) return token_ref.to_dict()
def list_trusts(self, context): query = context["query_string"] trusts = [] if not query: self.assert_admin(context) trusts += self.trust_api.list_trusts() if "trustor_user_id" in query: user_id = query["trustor_user_id"] calling_user_id = self._get_user_id(context) if user_id != calling_user_id: raise exception.Forbidden() trusts += self.trust_api.list_trusts_for_trustor(user_id) if "trustee_user_id" in query: user_id = query["trustee_user_id"] calling_user_id = self._get_user_id(context) if user_id != calling_user_id: raise exception.Forbidden() trusts += self.trust_api.list_trusts_for_trustee(user_id) for trust in trusts: # get_trust returns roles, list_trusts does not # It seems in some circumstances, roles does not # exist in the query response, so check first if "roles" in trust: del trust["roles"] if trust.get("expires_at") is not None: trust["expires_at"] = utils.isotime(trust["expires_at"], subsecond=True) return TrustV3.wrap_collection(context, trusts)
def list_trusts(self, request): trusts = [] if not request.params: self.assert_admin(request) trusts += self.trust_api.list_trusts() if 'trustor_user_id' in request.params: user_id = request.params['trustor_user_id'] calling_user_id = self._get_user_id(request.context_dict) if user_id != calling_user_id: raise exception.Forbidden() trusts += (self.trust_api. list_trusts_for_trustor(user_id)) if 'trustee_user_id' in request.params: user_id = request.params['trustee_user_id'] calling_user_id = self._get_user_id(request.context_dict) if user_id != calling_user_id: raise exception.Forbidden() trusts += self.trust_api.list_trusts_for_trustee(user_id) for trust in trusts: # get_trust returns roles, list_trusts does not # It seems in some circumstances, roles does not # exist in the query response, so check first if 'roles' in trust: del trust['roles'] if trust.get('expires_at') is not None: trust['expires_at'] = (utils.isotime (trust['expires_at'], subsecond=True)) return TrustV3.wrap_collection(request.context_dict, trusts)
def _create_response(self, issuer, status, assertion, recipient): """Create an object that represents a SAML Response. <ns0:Response Destination="http://beta.com/Shibboleth.sso/SAML2/POST" ID="c5954543230e4e778bc5b92923a0512d" IssueInstant="2014-07-30T03:19:45Z" Version="2.0" /> <ns0:Issuer> ... </ns0:Issuer> <ns0:Assertion> ... </ns0:Assertion> <ns0:Status> ... </ns0:Status> </ns0:Response> :returns: XML <Response> object """ response = samlp.Response() response.id = uuid.uuid4().hex response.destination = recipient response.issue_instant = utils.isotime() response.version = '2.0' response.issuer = issuer response.status = status response.assertion = assertion return response
def _create_assertion(self, issuer, signature, subject, authn_statement, attribute_statement): """Create an object that represents a SAML Assertion. <ns0:Assertion ID="35daed258ba647ba8962e9baff4d6a46" IssueInstant="2014-06-11T15:45:58Z" Version="2.0"> <ns0:Issuer> ... </ns0:Issuer> <ns1:Signature> ... </ns1:Signature> <ns0:Subject> ... </ns0:Subject> <ns0:AuthnStatement> ... </ns0:AuthnStatement> <ns0:AttributeStatement> ... </ns0:AttributeStatement> </ns0:Assertion> :returns: XML <Assertion> object """ assertion = saml.Assertion() assertion.id = self.assertion_id assertion.issue_instant = utils.isotime() assertion.version = '2.0' assertion.issuer = issuer assertion.signature = signature assertion.subject = subject assertion.authn_statement = authn_statement assertion.attribute_statement = attribute_statement return assertion
def revocation_list(self, context, auth=None): if not CONF.token.revoke_by_id: raise exception.Gone() audit_id_only = ('audit_id_only' in context['query_string']) tokens = self.token_provider_api.list_revoked_tokens() for t in tokens: expires = t['expires'] if not (expires and isinstance(expires, six.text_type)): t['expires'] = utils.isotime(expires) if audit_id_only: t.pop('id', None) data = {'revoked': tokens} if audit_id_only: # No need to obfuscate if no token IDs. return data json_data = jsonutils.dumps(data) signed_text = cms.cms_sign_text(json_data, CONF.signing.certfile, CONF.signing.keyfile) return {'signed': signed_text}
def validate_token(self, token): """Validates a Fernet token and returns the payload attributes.""" # Convert v2 unicode token to a string if not isinstance(token, six.binary_type): token = token.encode('ascii') serialized_payload = self.unpack(token) versioned_payload = msgpack.unpackb(serialized_payload) version, payload = versioned_payload[0], versioned_payload[1:] # depending on the formatter, these may or may not be defined domain_id = None project_id = None trust_id = None federated_info = None if version == UnscopedPayload.version: (user_id, methods, expires_at, audit_ids) = ( UnscopedPayload.disassemble(payload)) elif version == DomainScopedPayload.version: (user_id, methods, domain_id, expires_at, audit_ids) = ( DomainScopedPayload.disassemble(payload)) elif version == ProjectScopedPayload.version: (user_id, methods, project_id, expires_at, audit_ids) = ( ProjectScopedPayload.disassemble(payload)) elif version == TrustScopedPayload.version: (user_id, methods, project_id, expires_at, audit_ids, trust_id) = ( TrustScopedPayload.disassemble(payload)) elif version == FederatedPayload.version: (user_id, methods, expires_at, audit_ids, federated_info) = ( FederatedPayload.disassemble(payload)) else: # If the token_format is not recognized, raise ValidationError. raise exception.ValidationError(_( 'This is not a recognized Fernet payload version: %s') % version) # rather than appearing in the payload, the creation time is encoded # into the token format itself created_at = TokenFormatter.creation_time(token) created_at = ks_utils.isotime(at=created_at, subsecond=True) expires_at = timeutils.parse_isotime(expires_at) expires_at = ks_utils.isotime(at=expires_at, subsecond=True) return (user_id, methods, audit_ids, domain_id, project_id, trust_id, federated_info, created_at, expires_at)
def assertReportedEventMatchesRecorded(self, event, sample, before_time): after_time = timeutils.utcnow() event_issued_before = timeutils.normalize_time( timeutils.parse_isotime(event['issued_before'])) self.assertLessEqual( before_time, event_issued_before, 'invalid event issued_before time; %s is not later than %s.' % ( utils.isotime(event_issued_before, subsecond=True), utils.isotime(before_time, subsecond=True))) self.assertLessEqual( event_issued_before, after_time, 'invalid event issued_before time; %s is not earlier than %s.' % ( utils.isotime(event_issued_before, subsecond=True), utils.isotime(after_time, subsecond=True))) del (event['issued_before']) del (event['revoked_at']) self.assertEqual(sample, event)
def _build_issued_at_info(self, token_id, token_data): # NOTE(roxanaghe, lbragstad): We must use the creation time that # Fernet builds into it's token. The Fernet spec details that the # token creation time is built into the token, outside of the payload # provided by Keystone. This is the reason why we don't pass the # issued_at time in the payload. This also means that we shouldn't # return a token reference with a creation time that we created # when Fernet uses a different creation time. We should use the # creation time provided by Fernet because it's the creation time # that we have to rely on when we validate the token. fernet_creation_datetime_obj = self.token_formatter.creation_time(token_id) if token_data.get("access"): token_data["access"]["token"]["issued_at"] = ks_utils.isotime( at=fernet_creation_datetime_obj, subsecond=True ) else: token_data["token"]["issued_at"] = ks_utils.isotime(at=fernet_creation_datetime_obj, subsecond=True)
def create_v3_token(): return { "token": { 'methods': [], "expires_at": utils.isotime(timeutils.utcnow() + FUTURE_DELTA), "issued_at": "2013-05-21T00:02:43.941473Z", } }
def _list_trusts(self): trustor_user_id = flask.request.args.get('trustor_user_id') trustee_user_id = flask.request.args.get('trustee_user_id') if trustor_user_id: target = {'trust': {'trustor_user_id': trustor_user_id}} ENFORCER.enforce_call(action='identity:list_trusts_for_trustor', target_attr=target) elif trustee_user_id: target = {'trust': {'trustee_user_id': trustee_user_id}} ENFORCER.enforce_call(action='identity:list_trusts_for_trustee', target_attr=target) else: ENFORCER.enforce_call(action='identity:list_trusts') trusts = [] # NOTE(cmurphy) As of Train, the default policies enforce the # identity:list_trusts rule and there are new policies in-code to # enforce identity:list_trusts_for_trustor and # identity:list_trusts_for_trustee. However, in case the # identity:list_trusts rule has been locally overridden by the default # that would have been produced by the sample config, we need to # enforce it again and warn that the behavior is changing. rules = policy._ENFORCER._enforcer.rules.get('identity:list_trusts') # rule check_str is "" if isinstance(rules, op_checks.TrueCheck): LOG.warning( "The policy check string for rule \"identity:list_trusts\" has been overridden" "to \"always true\". In the next release, this will cause the" "\"identity:list_trusts\" action to be fully permissive as hardcoded" "enforcement will be removed. To correct this issue, either stop overriding the" "\"identity:list_trusts\" rule in config to accept the defaults, or explicitly" "set a rule that is not empty.") if not flask.request.args: # NOTE(morgan): Admin can list all trusts. ENFORCER.enforce_call(action='admin_required') if not flask.request.args: trusts += PROVIDERS.trust_api.list_trusts() elif trustor_user_id: trusts += PROVIDERS.trust_api.list_trusts_for_trustor( trustor_user_id) elif trustee_user_id: trusts += PROVIDERS.trust_api.list_trusts_for_trustee( trustee_user_id) for trust in trusts: # get_trust returns roles, list_trusts does not # It seems in some circumstances, roles does not # exist in the query response, so check first if 'roles' in trust: del trust['roles'] if trust.get('expires_at') is not None: trust['expires_at'] = utils.isotime(trust['expires_at'], subsecond=True) return self.wrap_collection(trusts)
def _convert_int_to_time_string(cls, time_int): """Convert a timestamp integer to a string. :param time_int: integer representing timestamp :returns: a time formatted strings """ time_object = datetime.datetime.utcfromtimestamp(int(time_int)) return ks_utils.isotime(time_object)
def _build_issued_at_info(self, token_id, token_data): # NOTE(roxanaghe, lbragstad): We must use the creation time that # Fernet builds into it's token. The Fernet spec details that the # token creation time is built into the token, outside of the payload # provided by Keystone. This is the reason why we don't pass the # issued_at time in the payload. This also means that we shouldn't # return a token reference with a creation time that we created # when Fernet uses a different creation time. We should use the # creation time provided by Fernet because it's the creation time # that we have to rely on when we validate the token. fernet_creation_datetime_obj = self.token_formatter.creation_time( token_id) if token_data.get('access'): token_data['access']['token']['issued_at'] = ks_utils.isotime( at=fernet_creation_datetime_obj, subsecond=True) else: token_data['token']['issued_at'] = ks_utils.isotime( at=fernet_creation_datetime_obj, subsecond=True)
def _convert_float_to_time_string(cls, time_float): """Convert a floating point timestamp to a string. :param time_float: integer representing timestamp :returns: a time formatted strings """ time_object = datetime.datetime.utcfromtimestamp(time_float) return ks_utils.isotime(time_object, subsecond=True)
def test_provider_receipt_expiration_validation(self): receipt = receipt_model.ReceiptModel() receipt.issued_at = utils.isotime(CURRENT_DATE) receipt.expires_at = utils.isotime(CURRENT_DATE - DELTA) receipt.id = uuid.uuid4().hex with freezegun.freeze_time(CURRENT_DATE): self.assertRaises(exception.ReceiptNotFound, PROVIDERS.receipt_provider_api._is_valid_receipt, receipt) # confirm a non-expired receipt doesn't throw errors. # returning None, rather than throwing an error is correct. receipt = receipt_model.ReceiptModel() receipt.issued_at = utils.isotime(CURRENT_DATE) receipt.expires_at = utils.isotime(CURRENT_DATE + DELTA) receipt.id = uuid.uuid4().hex with freezegun.freeze_time(CURRENT_DATE): self.assertIsNone( PROVIDERS.receipt_provider_api._is_valid_receipt(receipt))
def test_revoke_by_expiration_project_and_domain_fails(self): user_id = _new_id() expires_at = utils.isotime(_future_time(), subsecond=True) domain_id = _new_id() project_id = _new_id() self.assertThat( lambda: self.revoke_api.revoke_by_expiration( user_id, expires_at, domain_id=domain_id, project_id=project_id), matchers.raises(exception.UnexpectedError))
def test_isotime(self): dt = datetime.datetime(year=1987, month=10, day=13, hour=1, minute=2, second=3) output = utils.isotime(dt) expected = '1987-10-13T01:02:03Z' self.assertEqual(output, expected)
def validate_receipt(self, receipt): """Validate a Fernet receipt and returns the payload attributes. :type receipt: six.text_type """ serialized_payload = self.unpack(receipt) payload = msgpack.unpackb(serialized_payload) (user_id, methods, expires_at) = ReceiptPayload.disassemble(payload) # rather than appearing in the payload, the creation time is encoded # into the receipt format itself issued_at = ReceiptFormatter.creation_time(receipt) issued_at = ks_utils.isotime(at=issued_at, subsecond=True) expires_at = timeutils.parse_isotime(expires_at) expires_at = ks_utils.isotime(at=expires_at, subsecond=True) return (user_id, methods, issued_at, expires_at)
def _add_to_revocation_list(self, data, lock): filtered_list = [] revoked_token_data = {} current_time = self._get_current_time() expires = data['expires'] if isinstance(expires, six.string_types): expires = timeutils.parse_isotime(expires) expires = timeutils.normalize_time(expires) if expires < current_time: LOG.warning(_LW('Token `%s` is expired, not adding to the ' 'revocation list.'), data['id']) return revoked_token_data['expires'] = utils.isotime(expires, subsecond=True) revoked_token_data['id'] = data['id'] token_list = self._get_key_or_default(self.revocation_key, default=[]) if not isinstance(token_list, list): # NOTE(morganfainberg): In the case that the revocation list is not # in a format we understand, reinitialize it. This is an attempt to # not allow the revocation list to be completely broken if # somehow the key is changed outside of keystone (e.g. memcache # that is shared by multiple applications). Logging occurs at error # level so that the cloud administrators have some awareness that # the revocation_list needed to be cleared out. In all, this should # be recoverable. Keystone cannot control external applications # from changing a key in some backends, however, it is possible to # gracefully handle and notify of this event. LOG.error(_LE('Reinitializing revocation list due to error ' 'in loading revocation list from backend. ' 'Expected `list` type got `%(type)s`. Old ' 'revocation list data: %(list)r'), {'type': type(token_list), 'list': token_list}) token_list = [] # NOTE(morganfainberg): on revocation, cleanup the expired entries, try # to keep the list of tokens revoked at the minimum. for token_data in token_list: try: expires_at = timeutils.normalize_time( timeutils.parse_isotime(token_data['expires'])) except ValueError: LOG.warning(_LW('Removing `%s` from revocation list due to ' 'invalid expires data in revocation list.'), token_data.get('id', 'INVALID_TOKEN_DATA')) continue if expires_at > current_time: filtered_list.append(token_data) filtered_list.append(revoked_token_data) self._set_key(self.revocation_key, filtered_list, lock)
def validate_token(self, token): """Validate a Fernet token and returns the payload attributes. :type token: six.text_type """ serialized_payload = self.unpack(token) versioned_payload = msgpack.unpackb(serialized_payload) version, payload = versioned_payload[0], versioned_payload[1:] for payload_class in _PAYLOAD_CLASSES: if version == payload_class.version: (user_id, methods, system, project_id, domain_id, expires_at, audit_ids, trust_id, federated_group_ids, identity_provider_id, protocol_id, access_token_id, app_cred_id) = payload_class.disassemble(payload) break else: # If the token_format is not recognized, raise ValidationError. raise exception.ValidationError(_( 'This is not a recognized Fernet payload version: %s') % version) # FIXME(lbragstad): Without this, certain token validation tests fail # when running with python 3. Once we get further along in this # refactor, we should be better about handling string encoding/types at # the edges of the application. if isinstance(system, bytes): system = system.decode('utf-8') # rather than appearing in the payload, the creation time is encoded # into the token format itself issued_at = TokenFormatter.creation_time(token) issued_at = ks_utils.isotime(at=issued_at, subsecond=True) expires_at = timeutils.parse_isotime(expires_at) expires_at = ks_utils.isotime(at=expires_at, subsecond=True) return (user_id, methods, audit_ids, system, domain_id, project_id, trust_id, federated_group_ids, identity_provider_id, protocol_id, access_token_id, app_cred_id, issued_at, expires_at)
def generate_id_and_issued_at(self, receipt): receipt_id = self.receipt_formatter.create_receipt( receipt.user_id, receipt.methods, receipt.expires_at, ) creation_datetime_obj = self.receipt_formatter.creation_time( receipt_id) issued_at = ks_utils.isotime( at=creation_datetime_obj, subsecond=True ) return receipt_id, issued_at
def issue_receipt(self, user_id, method_names, expires_at=None): receipt = receipt_model.ReceiptModel() receipt.user_id = user_id receipt.methods = method_names if isinstance(expires_at, datetime.datetime): receipt.expires_at = utils.isotime(expires_at, subsecond=True) if isinstance(expires_at, six.string_types): receipt.expires_at = expires_at elif not expires_at: receipt.expires_at = utils.isotime(default_expire_time(), subsecond=True) receipt_id, issued_at = self.driver.generate_id_and_issued_at(receipt) receipt.mint(receipt_id, issued_at) if CONF.receipt.cache_on_issue: self._validate_receipt.set(receipt, RECEIPTS_REGION, receipt_id) return receipt
def _test_payload(self, payload_class, exp_user_id=None, exp_methods=None, exp_system=None, exp_project_id=None, exp_domain_id=None, exp_trust_id=None, exp_federated_group_ids=None, exp_identity_provider_id=None, exp_protocol_id=None, exp_access_token_id=None, exp_app_cred_id=None, encode_ids=False): def _encode_id(value): if value is not None and six.text_type(value) and encode_ids: return value.encode('utf-8') return value exp_user_id = exp_user_id or uuid.uuid4().hex exp_methods = exp_methods or ['password'] exp_expires_at = utils.isotime(timeutils.utcnow(), subsecond=True) exp_audit_ids = [provider.random_urlsafe_str()] payload = payload_class.assemble(_encode_id(exp_user_id), exp_methods, _encode_id(exp_system), _encode_id(exp_project_id), exp_domain_id, exp_expires_at, exp_audit_ids, exp_trust_id, _encode_id(exp_federated_group_ids), _encode_id(exp_identity_provider_id), exp_protocol_id, _encode_id(exp_access_token_id), _encode_id(exp_app_cred_id)) (user_id, methods, system, project_id, domain_id, expires_at, audit_ids, trust_id, federated_group_ids, identity_provider_id, protocol_id, access_token_id, app_cred_id) = payload_class.disassemble(payload) self.assertEqual(exp_user_id, user_id) self.assertEqual(exp_methods, methods) self.assertTimestampsEqual(exp_expires_at, expires_at) self.assertEqual(exp_audit_ids, audit_ids) self.assertEqual(exp_system, system) self.assertEqual(exp_project_id, project_id) self.assertEqual(exp_domain_id, domain_id) self.assertEqual(exp_federated_group_ids, federated_group_ids) self.assertEqual(exp_identity_provider_id, identity_provider_id) self.assertEqual(exp_protocol_id, protocol_id) self.assertEqual(exp_trust_id, trust_id) self.assertEqual(exp_access_token_id, access_token_id) self.assertEqual(exp_app_cred_id, app_cred_id)
def test_revoked_token_in_list(self): user_id = uuid.uuid4().hex expires_at = provider.default_expire_time() sample = self._blank_event() sample['user_id'] = six.text_type(user_id) sample['expires_at'] = six.text_type(utils.isotime(expires_at)) before_time = timeutils.utcnow() self.revoke_api.revoke_by_expiration(user_id, expires_at) resp = self.get('/OS-REVOKE/events') events = resp.json_body['events'] self.assertEqual(1, len(events)) self.assertReportedEventMatchesRecorded(events[0], sample, before_time)
def _test_payload(self, payload_class, exp_user_id=None, exp_methods=None): exp_user_id = exp_user_id or uuid.uuid4().hex exp_methods = exp_methods or ['password'] exp_expires_at = utils.isotime(timeutils.utcnow(), subsecond=True) payload = payload_class.assemble( exp_user_id, exp_methods, exp_expires_at) (user_id, methods, expires_at) = payload_class.disassemble(payload) self.assertEqual(exp_user_id, user_id) self.assertEqual(exp_methods, methods) self.assertTimestampsEqual(exp_expires_at, expires_at)
def create_token(self, user_id, expires_at, audit_ids, methods, system=None, domain_id=None, project_id=None, trust_id=None, federated_group_ids=None, identity_provider_id=None, protocol_id=None, access_token_id=None, app_cred_id=None): issued_at = utils.isotime(subsecond=True) issued_at_int = self._convert_time_string_to_int(issued_at) expires_at_int = self._convert_time_string_to_int(expires_at) payload = { # public claims 'sub': user_id, 'iat': issued_at_int, 'exp': expires_at_int, # private claims 'openstack_methods': methods, 'openstack_audit_ids': audit_ids, 'openstack_system': system, 'openstack_domain_id': domain_id, 'openstack_project_id': project_id, 'openstack_trust_id': trust_id, 'openstack_group_ids': federated_group_ids, 'openstack_idp_id': identity_provider_id, 'openstack_protocol_id': protocol_id, 'openstack_access_token_id': access_token_id, 'openstack_app_cred_id': app_cred_id } # NOTE(lbragstad): Calling .items() on a dictionary in python 2 returns # a list but returns an iterable in python 3. Casting to a list makes # it safe to modify the dictionary while iterating over it, regardless # of the python version. for k, v in list(payload.items()): if v is None: payload.pop(k) token_id = jwt.encode(payload, self.private_key, algorithm=JWSFormatter.algorithm) return token_id, issued_at
def create_v2_token(): return { "access": { "token": { "expires": utils.isotime(timeutils.utcnow() + FUTURE_DELTA), "issued_at": "2013-05-21T00:02:43.941473Z", "tenant": { "enabled": True, "id": "01257", "name": "service" } } } }
def to_dict(self): keys = ['user_id', 'role_id', 'domain_id', 'domain_scope_id', 'project_id', 'audit_id', 'audit_chain_id', ] event = {key: self.__dict__[key] for key in keys if self.__dict__[key] is not None} if self.trust_id is not None: event['OS-TRUST:trust_id'] = self.trust_id if self.consumer_id is not None: event['OS-OAUTH1:consumer_id'] = self.consumer_id if self.consumer_id is not None: event['OS-OAUTH1:access_token_id'] = self.access_token_id if self.expires_at is not None: event['expires_at'] = utils.isotime(self.expires_at) if self.issued_before is not None: event['issued_before'] = utils.isotime(self.issued_before, subsecond=True) return event
def revocation_list(self, context, auth=None): if not CONF.token.revoke_by_id: raise exception.Gone() tokens = self.token_provider_api.list_revoked_tokens() for t in tokens: expires = t['expires'] if not (expires and isinstance(expires, six.text_type)): t['expires'] = utils.isotime(expires) data = {'revoked': tokens} json_data = jsonutils.dumps(data) signed_text = cms.cms_sign_text(json_data, CONF.signing.certfile, CONF.signing.keyfile) return {'signed': signed_text}
def _test_unscoped_payload_with_user_id(self, exp_user_id): exp_methods = ['password'] exp_expires_at = utils.isotime(timeutils.utcnow(), subsecond=True) exp_audit_ids = [provider.random_urlsafe_str()] payload = token_formatters.UnscopedPayload.assemble( exp_user_id, exp_methods, exp_expires_at, exp_audit_ids) (user_id, methods, expires_at, audit_ids) = (token_formatters.UnscopedPayload.disassemble(payload)) self.assertEqual(exp_user_id, user_id) self.assertEqual(exp_methods, methods) self.assertEqual(exp_expires_at, expires_at) self.assertEqual(exp_audit_ids, audit_ids)
def test_cleanup_user_index_on_create(self): user_id = six.text_type(uuid.uuid4().hex) valid_token_id, data = self.create_token_sample_data(user_id=user_id) expired_token_id, expired_data = self.create_token_sample_data( user_id=user_id) expire_delta = datetime.timedelta(seconds=86400) # NOTE(morganfainberg): Directly access the data cache since we need to # get expired tokens as well as valid tokens. token_persistence = self.token_provider_api._persistence user_key = token_persistence.driver._prefix_user_id(user_id) user_token_list = token_persistence.driver._store.get(user_key) valid_token_ref = token_persistence.get_token(valid_token_id) expired_token_ref = token_persistence.get_token(expired_token_id) expected_user_token_list = [ (valid_token_id, utils.isotime(valid_token_ref['expires'], subsecond=True)), (expired_token_id, utils.isotime(expired_token_ref['expires'], subsecond=True)) ] self.assertEqual(expected_user_token_list, user_token_list) new_expired_data = (expired_token_id, utils.isotime((timeutils.utcnow() - expire_delta), subsecond=True)) self._update_user_token_index_direct(user_key, expired_token_id, new_expired_data) valid_token_id_2, valid_data_2 = self.create_token_sample_data( user_id=user_id) valid_token_ref_2 = token_persistence.get_token(valid_token_id_2) expected_user_token_list = [ (valid_token_id, utils.isotime(valid_token_ref['expires'], subsecond=True)), (valid_token_id_2, utils.isotime(valid_token_ref_2['expires'], subsecond=True)) ] user_token_list = token_persistence.driver._store.get(user_key) self.assertEqual(expected_user_token_list, user_token_list) # Test that revoked tokens are removed from the list on create. token_persistence.delete_token(valid_token_id_2) new_token_id, data = self.create_token_sample_data(user_id=user_id) new_token_ref = token_persistence.get_token(new_token_id) expected_user_token_list = [(valid_token_id, utils.isotime(valid_token_ref['expires'], subsecond=True)), (new_token_id, utils.isotime(new_token_ref['expires'], subsecond=True))] user_token_list = token_persistence.driver._store.get(user_key) self.assertEqual(expected_user_token_list, user_token_list)
def test_time_string_to_int_conversions(self): payload_cls = token_formatters.BasePayload expected_time_str = utils.isotime() time_obj = timeutils.parse_isotime(expected_time_str) expected_time_int = ( (timeutils.normalize_time(time_obj) - datetime.datetime.utcfromtimestamp(0)).total_seconds()) actual_time_int = payload_cls._convert_time_string_to_int( expected_time_str) self.assertEqual(expected_time_int, actual_time_int) actual_time_str = payload_cls._convert_int_to_time_string( actual_time_int) self.assertEqual(expected_time_str, actual_time_str)
def test_unscoped_payload(self): exp_user_id = uuid.uuid4().hex exp_methods = ['password'] exp_expires_at = utils.isotime(timeutils.utcnow()) exp_audit_ids = [provider.random_urlsafe_str()] payload = token_formatters.UnscopedPayload.assemble( exp_user_id, exp_methods, exp_expires_at, exp_audit_ids) (user_id, methods, expires_at, audit_ids) = (token_formatters.UnscopedPayload.disassemble(payload)) self.assertEqual(exp_user_id, user_id) self.assertEqual(exp_methods, methods) self.assertEqual(exp_expires_at, expires_at) self.assertEqual(exp_audit_ids, audit_ids)
def test_revoked_at_in_list(self): time = datetime.datetime.utcnow() with freezegun.freeze_time(time) as frozen_datetime: revoked_at = timeutils.utcnow() # Given or not, `revoked_at` will always be set in the backend. self.revoke_api.revoke( revoke_model.RevokeEvent(revoked_at=revoked_at)) frozen_datetime.tick(delta=datetime.timedelta(seconds=1)) resp = self.get('/OS-REVOKE/events') events = resp.json_body['events'] self.assertThat(events, matchers.HasLength(1)) # Strip off the microseconds from `revoked_at`. self.assertTimestampEqual(utils.isotime(revoked_at), events[0]['revoked_at'])
def create_token(self, token_id, data): """Create a token by id and data. It is assumed the caller has performed data validation on the "data" parameter. """ data_copy = copy.deepcopy(data) ptk = self._prefix_token_id(token_id) if not data_copy.get('expires'): data_copy['expires'] = provider.default_expire_time() if not data_copy.get('user_id'): data_copy['user_id'] = data_copy['user']['id'] # NOTE(morganfainberg): for ease of manipulating the data without # concern about the backend, always store the value(s) in the # index as the isotime (string) version so this is where the string is # built. expires_str = utils.isotime(data_copy['expires'], subsecond=True) self._set_key(ptk, data_copy) user_id = data['user']['id'] user_key = self._prefix_user_id(user_id) self._update_user_token_list(user_key, token_id, expires_str) if CONF.trust.enabled and data.get('trust_id'): # NOTE(morganfainberg): If trusts are enabled and this is a trust # scoped token, we add the token to the trustee list as well. This # allows password changes of the trustee to also expire the token. # There is no harm in placing the token in multiple lists, as # _list_tokens is smart enough to handle almost any case of # valid/invalid/expired for a given token. token_data = data_copy['token_data'] if data_copy['token_version'] == token.provider.V2: trustee_user_id = token_data['access']['trust'][ 'trustee_user_id'] elif data_copy['token_version'] == token.provider.V3: trustee_user_id = token_data['OS-TRUST:trust'][ 'trustee_user_id'] else: raise exception.UnsupportedTokenVersionException( _('Unknown token version %s') % data_copy.get('token_version')) trustee_key = self._prefix_user_id(trustee_user_id) self._update_user_token_list(trustee_key, token_id, expires_str) return data_copy
def setUp(self): super(TestReceiptSerialization, self).setUp() self.admin_user_id = self.bootstrapper.admin_user_id self.receipt_id = uuid.uuid4().hex issued_at = datetime.datetime.utcnow() self.issued_at = ks_utils.isotime(at=issued_at, subsecond=True) # Reach into the cache registry and pull out an instance of the # _ReceiptModelHandler so that we can interact and test it directly (as # opposed to using PROVIDERS or managers to invoke it). receipt_handler_id = receipt_model._ReceiptModelHandler.identity self.receipt_handler = _context_cache._registry.get(receipt_handler_id) self.exp_receipt = receipt_model.ReceiptModel() self.exp_receipt.user_id = self.admin_user_id self.exp_receipt.mint(self.receipt_id, self.issued_at)
def generate_id_and_issued_at(self, token): token_id = self.token_formatter.create_token( token.user_id, token.expires_at, token.audit_ids, methods=token.methods, system=token.system, domain_id=token.domain_id, project_id=token.project_id, trust_id=token.trust_id, federated_group_ids=token.federated_groups, identity_provider_id=token.identity_provider_id, protocol_id=token.protocol_id, access_token_id=token.access_token_id, app_cred_id=token.application_credential_id) creation_datetime_obj = self.token_formatter.creation_time(token_id) issued_at = ks_utils.isotime(at=creation_datetime_obj, subsecond=True) return token_id, issued_at