def _authenticate_external(self, request, auth): """Try to authenticate an external user via REMOTE_USER variable. Returns auth_token_data, (user_ref, tenant_ref, metadata_ref) """ username = request.environ.get('REMOTE_USER') if not username: raise ExternalAuthNotApplicable() try: user_ref = self.identity_api.get_user_by_name( username, CONF.identity.default_domain_id) user_id = user_ref['id'] except exception.UserNotFound as e: raise exception.Unauthorized(e) metadata_ref = {} tenant_id = self._get_project_id_from_auth(auth) tenant_ref, metadata_ref['roles'] = self._get_project_roles_and_ref( user_id, tenant_id) expiry = provider.default_expire_time() bind = None if ('kerberos' in CONF.token.bind and request.environ.get( 'AUTH_TYPE', '').lower() == 'negotiate'): bind = {'kerberos': username} audit_id = None return (user_ref, tenant_ref, metadata_ref, expiry, bind, audit_id)
def _populate_token_dates(self, token_data, expires=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 _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 _authenticate_external(self, request, auth): """Try to authenticate an external user via REMOTE_USER variable. Returns auth_token_data, (user_ref, tenant_ref, metadata_ref) """ username = request.environ.get('REMOTE_USER') if not username: raise ExternalAuthNotApplicable() try: user_ref = self.identity_api.get_user_by_name( username, CONF.identity.default_domain_id) user_id = user_ref['id'] except exception.UserNotFound as e: raise exception.Unauthorized(e) metadata_ref = {} tenant_id = self._get_project_id_from_auth(auth) tenant_ref, metadata_ref['roles'] = self._get_project_roles_and_ref( user_id, tenant_id) expiry = provider.default_expire_time() bind = None if ('kerberos' in CONF.token.bind and request.environ.get('AUTH_TYPE', '').lower() == 'negotiate'): bind = {'kerberos': username} audit_id = None return (user_ref, tenant_ref, metadata_ref, expiry, bind, audit_id)
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 = timeutils.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) return data_copy
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 _authenticate_external(self, context, auth): """Try to authenticate an external user via REMOTE_USER variable. Returns auth_token_data, (user_ref, tenant_ref, metadata_ref) """ environment = context.get('environment', {}) if not environment.get('REMOTE_USER'): raise ExternalAuthNotApplicable() # NOTE(jamielennox): xml and json differ and get confused about what # empty auth should look like so just reset it. if not auth: auth = {} username = environment['REMOTE_USER'] try: user_ref = self.identity_api.get_user_by_name( username, CONF.identity.default_domain_id) user_id = user_ref['id'] except exception.UserNotFound as e: raise exception.Unauthorized(e) metadata_ref = {} tenant_id = self._get_project_id_from_auth(auth) tenant_ref, metadata_ref['roles'] = self._get_project_roles_and_ref( user_id, tenant_id) expiry = provider.default_expire_time() bind = None if ('kerberos' in CONF.token.bind and environment.get('AUTH_TYPE', '').lower() == 'negotiate'): bind = {'kerberos': username} audit_id = None return (user_ref, tenant_ref, metadata_ref, expiry, bind, audit_id)
def _authenticate_external(self, context, auth): """Try to authenticate an external user via REMOTE_USER variable. Returns auth_token_data, (user_ref, tenant_ref, metadata_ref) """ environment = context.get('environment', {}) if not environment.get('REMOTE_USER'): raise ExternalAuthNotApplicable() # NOTE(jamielennox): xml and json differ and get confused about what # empty auth should look like so just reset it. if not auth: auth = {} username = environment['REMOTE_USER'] try: user_ref = self.identity_api.get_user_by_name( username, CONF.identity.default_domain_id) user_id = user_ref['id'] except exception.UserNotFound as e: raise exception.Unauthorized(e) metadata_ref = {} tenant_id = self._get_project_id_from_auth(auth) tenant_ref, metadata_ref['roles'] = self._get_project_roles_and_ref( user_id, tenant_id) expiry = provider.default_expire_time() bind = None if ('kerberos' in CONF.token.bind and environment.get('AUTH_TYPE', '').lower() == 'negotiate'): bind = {'kerberos': username} return (user_ref, tenant_ref, metadata_ref, expiry, bind)
def _authenticate_local(self, context, auth): """Try to authenticate against the identity backend. Returns auth_token_data, (user_ref, tenant_ref, metadata_ref) """ if 'passwordCredentials' not in auth: raise exception.ValidationError( attribute='passwordCredentials', target='auth') if "password" not in auth['passwordCredentials']: raise exception.ValidationError( attribute='password', target='passwordCredentials') password = auth['passwordCredentials']['password'] if password and len(password) > CONF.identity.max_password_length: raise exception.ValidationSizeError( attribute='password', size=CONF.identity.max_password_length) if (not auth['passwordCredentials'].get("userId") and not auth['passwordCredentials'].get("username")): raise exception.ValidationError( attribute='username or userId', target='passwordCredentials') user_id = auth['passwordCredentials'].get('userId') if user_id and len(user_id) > CONF.max_param_size: raise exception.ValidationSizeError(attribute='userId', size=CONF.max_param_size) username = auth['passwordCredentials'].get('username', '') if username: if len(username) > CONF.max_param_size: raise exception.ValidationSizeError(attribute='username', size=CONF.max_param_size) try: user_ref = self.identity_api.get_user_by_name( username, CONF.identity.default_domain_id) user_id = user_ref['id'] except exception.UserNotFound as e: raise exception.Unauthorized(e) try: user_ref = self.identity_api.authenticate( context, user_id=user_id, password=password) except AssertionError as e: raise exception.Unauthorized(e.args[0]) metadata_ref = {} tenant_id = self._get_project_id_from_auth(auth) tenant_ref, metadata_ref['roles'] = self._get_project_roles_and_ref( user_id, tenant_id) expiry = provider.default_expire_time() bind = None audit_id = None return (user_ref, tenant_ref, metadata_ref, expiry, bind, audit_id)
def format_token(cls, token_ref, roles_ref=None, catalog_ref=None, trust_ref=None): audit_info = None user_ref = token_ref["user"] metadata_ref = token_ref["metadata"] if roles_ref is None: roles_ref = [] expires = token_ref.get("expires", provider.default_expire_time()) if expires is not None: if not isinstance(expires, six.text_type): expires = utils.isotime(expires) token_data = token_ref.get("token_data") if token_data: token_audit = token_data.get("access", token_data).get("token", {}).get("audit_ids") audit_info = token_audit if audit_info is None: audit_info = provider.audit_info(token_ref.get("parent_audit_id")) o = { "access": { "token": { "id": token_ref["id"], "expires": expires, "issued_at": utils.strtime(), "audit_ids": audit_info, }, "user": { "id": user_ref["id"], "name": user_ref["name"], "username": user_ref["name"], "roles": roles_ref, "roles_links": metadata_ref.get("roles_links", []), }, } } if "bind" in token_ref: o["access"]["token"]["bind"] = token_ref["bind"] if "tenant" in token_ref and token_ref["tenant"]: token_ref["tenant"]["enabled"] = True o["access"]["token"]["tenant"] = token_ref["tenant"] if catalog_ref is not None: o["access"]["serviceCatalog"] = V2TokenDataHelper.format_catalog(catalog_ref) if metadata_ref: if "is_admin" in metadata_ref: o["access"]["metadata"] = {"is_admin": metadata_ref["is_admin"]} else: o["access"]["metadata"] = {"is_admin": 0} if "roles" in metadata_ref: o["access"]["metadata"]["roles"] = metadata_ref["roles"] if CONF.trust.enabled and trust_ref: o["access"]["trust"] = { "trustee_user_id": trust_ref["trustee_user_id"], "id": trust_ref["id"], "trustor_user_id": trust_ref["trustor_user_id"], "impersonation": trust_ref["impersonation"], } return o
def format_token(cls, token_ref, roles_ref=None, catalog_ref=None): audit_info = None user_ref = token_ref['user'] metadata_ref = token_ref['metadata'] if roles_ref is None: roles_ref = [] expires = token_ref.get('expires', provider.default_expire_time()) if expires is not None: if not isinstance(expires, six.text_type): expires = timeutils.isotime(expires) token_data = token_ref.get('token_data') if token_data: token_audit = token_data.get( 'access', token_data).get('token', {}).get('audit_ids') audit_info = token_audit if audit_info is None: audit_info = provider.audit_info(token_ref.get('parent_audit_id')) o = {'access': {'token': {'id': token_ref['id'], 'expires': expires, 'issued_at': timeutils.strtime(), 'audit_ids': audit_info }, 'user': {'id': user_ref['id'], 'name': user_ref['name'], 'username': user_ref['name'], 'roles': roles_ref, 'roles_links': metadata_ref.get('roles_links', []) } } } if 'bind' in token_ref: o['access']['token']['bind'] = token_ref['bind'] if 'tenant' in token_ref and token_ref['tenant']: token_ref['tenant']['enabled'] = True o['access']['token']['tenant'] = token_ref['tenant'] if catalog_ref is not None: o['access']['serviceCatalog'] = V2TokenDataHelper.format_catalog( catalog_ref) if metadata_ref: if 'is_admin' in metadata_ref: o['access']['metadata'] = {'is_admin': metadata_ref['is_admin']} else: o['access']['metadata'] = {'is_admin': 0} if 'roles' in metadata_ref: o['access']['metadata']['roles'] = metadata_ref['roles'] if CONF.trust.enabled and 'trust_id' in metadata_ref: o['access']['trust'] = {'trustee_user_id': metadata_ref['trustee_user_id'], 'id': metadata_ref['trust_id'] } return o
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 create_token(self, token_id, data): data_copy = copy.deepcopy(data) 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'] token_ref = TokenModel.from_dict(data_copy) token_ref.valid = True with sql.session_for_write() as session: session.add(token_ref) return token_ref.to_dict()
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(timeutils.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(len(events), 1) self.assertReportedEventMatchesRecorded(events[0], sample, before_time)
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 create_token(self, token_id, data): data_copy = copy.deepcopy(data) 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"] token_ref = TokenModel.from_dict(data_copy) token_ref.valid = True session = sql.get_session() with session.begin(): session.add(token_ref) return token_ref.to_dict()
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(timeutils.isotime(expires_at, subsecond=True)) 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(len(events), 1) self.assertReportedEventMatchesRecorded(events[0], sample, before_time)
def format_token(cls, token_ref, roles_ref=None, catalog_ref=None): user_ref = token_ref['user'] metadata_ref = token_ref['metadata'] if roles_ref is None: roles_ref = [] expires = token_ref.get('expires', provider.default_expire_time()) if expires is not None: if not isinstance(expires, six.text_type): expires = timeutils.isotime(expires) o = { 'access': { 'token': { 'id': token_ref['id'], 'expires': expires, 'issued_at': timeutils.strtime() }, 'user': { 'id': user_ref['id'], 'name': user_ref['name'], 'username': user_ref['name'], 'roles': roles_ref, 'roles_links': metadata_ref.get('roles_links', []) } } } if 'bind' in token_ref: o['access']['token']['bind'] = token_ref['bind'] if 'tenant' in token_ref and token_ref['tenant']: token_ref['tenant']['enabled'] = True o['access']['token']['tenant'] = token_ref['tenant'] if catalog_ref is not None: o['access']['serviceCatalog'] = V2TokenDataHelper.format_catalog( catalog_ref) if metadata_ref: if 'is_admin' in metadata_ref: o['access']['metadata'] = { 'is_admin': metadata_ref['is_admin'] } else: o['access']['metadata'] = {'is_admin': 0} if 'roles' in metadata_ref: o['access']['metadata']['roles'] = metadata_ref['roles'] if CONF.trust.enabled and 'trust_id' in metadata_ref: o['access']['trust'] = { 'trustee_user_id': metadata_ref['trustee_user_id'], 'id': metadata_ref['trust_id'] } return o
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 = timeutils.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 create_token(self, token_id, data): data_copy = copy.deepcopy(data) 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'] token_ref = TokenModel.from_dict(data_copy) token_ref.valid = True # NOTE(garcianavalon) TOO big!! if 'token_data' in token_ref['extra']: if 'token' in token_ref['extra']['token_data']: token_ref['extra']['token_data']['token'].pop('catalog', None) if 'access' in token_ref['extra']['token_data']: token_ref['extra']['token_data']['access'].pop('serviceCatalog', None) # LOG.warning('TOKEN EXTRA: %s for token id %s', token_ref['extra'], token_ref['id']) session = sql.get_session() with session.begin(): session.add(token_ref) return token_ref.to_dict()
def create_token(self, token_id, data): data_copy = copy.deepcopy(data) 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'] token_ref = TokenModel.from_dict(data_copy) token_ref.valid = True # NOTE(garcianavalon) TOO big!! if 'token_data' in token_ref['extra']: if 'token' in token_ref['extra']['token_data']: token_ref['extra']['token_data']['token'].pop('catalog', None) if 'access' in token_ref['extra']['token_data']: token_ref['extra']['token_data']['access'].pop( 'serviceCatalog', None) # LOG.warning('TOKEN EXTRA: %s for token id %s', token_ref['extra'], token_ref['id']) session = sql.get_session() with session.begin(): session.add(token_ref) return token_ref.to_dict()
def test_verify_token_with_multiple_public_keys_present(self): 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) 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) # make sure we iterate through all public keys on disk and we can still # validate the token self.provider.validate_token(token_id)
def format_token(cls, token_ref, roles_ref=None, catalog_ref=None, trust_ref=None): audit_info = None user_ref = token_ref['user'] metadata_ref = token_ref['metadata'] if roles_ref is None: roles_ref = [] expires = token_ref.get('expires', provider.default_expire_time()) if expires is not None: if not isinstance(expires, six.text_type): expires = utils.isotime(expires) token_data = token_ref.get('token_data') if token_data: token_audit = token_data.get('access', token_data).get('token', {}).get('audit_ids') audit_info = token_audit if audit_info is None: audit_info = provider.audit_info(token_ref.get('parent_audit_id')) o = { 'access': { 'token': { 'id': token_ref['id'], 'expires': expires, 'issued_at': utils.isotime(subsecond=True), 'audit_ids': audit_info }, 'user': { 'id': user_ref['id'], 'name': user_ref['name'], 'username': user_ref['name'], 'roles': roles_ref, 'roles_links': metadata_ref.get('roles_links', []) } } } if 'bind' in token_ref: o['access']['token']['bind'] = token_ref['bind'] if 'tenant' in token_ref and token_ref['tenant']: token_ref['tenant']['enabled'] = True o['access']['token']['tenant'] = token_ref['tenant'] if catalog_ref is not None: o['access']['serviceCatalog'] = V2TokenDataHelper.format_catalog( catalog_ref) if metadata_ref: if 'is_admin' in metadata_ref: o['access']['metadata'] = { 'is_admin': metadata_ref['is_admin'] } else: o['access']['metadata'] = {'is_admin': 0} if 'roles' in metadata_ref: o['access']['metadata']['roles'] = metadata_ref['roles'] if CONF.trust.enabled and trust_ref: o['access']['trust'] = { 'trustee_user_id': trust_ref['trustee_user_id'], 'id': trust_ref['id'], 'trustor_user_id': trust_ref['trustor_user_id'], 'impersonation': trust_ref['impersonation'] } return o
def default_expire_time(): return provider.default_expire_time()