Example #1
0
 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)
Example #3
0
    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)
Example #4
0
 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
Example #5
0
    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
Example #6
0
 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))
Example #7
0
 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)
Example #9
0
    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))
Example #10
0
 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)
Example #11
0
    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)
Example #13
0
    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'])
Example #16
0
    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"])
Example #19
0
    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()
Example #20
0
    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)
Example #22
0
    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()
Example #23
0
 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)
Example #24
0
 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)
Example #25
0
    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
Example #26
0
    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
Example #27
0
    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}
Example #28
0
    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)
Example #30
0
 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)
Example #31
0
 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)
Example #32
0
def create_v3_token():
    return {
        "token": {
            'methods': [],
            "expires_at": utils.isotime(timeutils.utcnow() + FUTURE_DELTA),
            "issued_at": "2013-05-21T00:02:43.941473Z",
        }
    }
def create_v3_token():
    return {
        "token": {
            'methods': [],
            "expires_at": utils.isotime(timeutils.utcnow() + FUTURE_DELTA),
            "issued_at": "2013-05-21T00:02:43.941473Z",
        }
    }
Example #34
0
    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)
Example #35
0
    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)
Example #36
0
 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)
Example #37
0
    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))
Example #39
0
 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))
Example #40
0
 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)
Example #41
0
    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)
Example #42
0
    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)
Example #44
0
 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
Example #45
0
    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
Example #46
0
    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)
Example #47
0
 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)
Example #48
0
    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)
Example #49
0
    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
Example #50
0
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"
                }
            }
        }
    }
Example #51
0
 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}
Example #53
0
    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)
Example #55
0
    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)
Example #56
0
    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)
Example #57
0
    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'])
Example #58
0
    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)
Example #60
0
 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