def test_token_expire_timezone(self): @test_utils.timezone def _create_token(expire_time): token_id = uuid.uuid4().hex user_id = six.text_type(uuid.uuid4().hex) data = {'id': token_id, 'a': 'b', 'user': {'id': user_id}, 'expires': expire_time } self.token_api.create_token(token_id, data) return data for d in ['+0', '-11', '-8', '-5', '+5', '+8', '+14']: test_utils.TZ = 'UTC' + d expire_time = timeutils.utcnow() + \ datetime.timedelta(minutes=1) data_in = _create_token(expire_time) data_get = None data_get = self.token_api.get_token(data_in['id']) self.assertIsNotNone(data_get, "TZ=%s" % test_utils.TZ) self.assertEqual(data_in['id'], data_get['id'], "TZ=%s" % test_utils.TZ) expire_time_expired = timeutils.utcnow() + \ datetime.timedelta(minutes=-1) data_in = _create_token(expire_time_expired) self.assertRaises(exception.TokenNotFound, self.token_api.get_token, data_in['id'])
def _inner(): if initial_delay: greenthread.sleep(initial_delay) try: while self._running: start = timeutils.utcnow() self.f(*self.args, **self.kw) end = timeutils.utcnow() if not self._running: break delay = interval - timeutils.delta_seconds(start, end) if delay <= 0: LOG.warn(_LW('task run outlasted interval by %s sec') % -delay) greenthread.sleep(delay if delay > 0 else 0) except LoopingCallDone as e: self.stop() done.send(e.retvalue) except Exception: LOG.exception(_LE('in fixed duration looping call')) done.send_exception(*sys.exc_info()) return else: done.send(True)
def _get_doc_date(self): if self.ttl_seconds > 0: expire_delta = datetime.timedelta(seconds=self.ttl_seconds) doc_date = timeutils.utcnow() + expire_delta else: doc_date = timeutils.utcnow() return doc_date
def test_list_since(self): self.revoke_api.revoke_by_user(user_id=1) self.revoke_api.revoke_by_user(user_id=2) past = timeutils.utcnow() - datetime.timedelta(seconds=1000) self.assertEqual(2, len(self.revoke_api.get_events(past))) future = timeutils.utcnow() + datetime.timedelta(seconds=1000) self.assertEqual(0, len(self.revoke_api.get_events(future)))
def _format_token(self, token_ref, roles_ref, catalog_ref=None): user_ref = token_ref['user'] metadata_ref = token_ref['metadata'] expires = token_ref['expires'] issue_time = timeutils.utcnow().time().isoformat() if expires is not None: if not isinstance(expires, unicode): expires = timeutils.isotime(expires) o = {'access': {'token': {'id': token_ref['id'], 'expires': expires, 'issued_at': issue_time }, 'user': {'id': user_ref['id'], 'name': user_ref['name'], 'username': user_ref['name'], 'roles': roles_ref, 'roles_links': metadata_ref.get('roles_links', []) } } } 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'] = self._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'] return o
def _filter_trust(ref): if ref["deleted"]: return None if ref.get("expires_at") and timeutils.utcnow() > ref["expires_at"]: return None ref = copy.deepcopy(ref) return ref
def _filter_trust(ref): if ref['deleted']: return None if ref.get('expires_at') and timeutils.utcnow() > ref['expires_at']: return None ref = copy.deepcopy(ref) return ref
def authenticate(self, context, auth_info, auth_context): """Turn a signed request with an access key into a keystone token.""" if not self.oauth_api: raise exception.Unauthorized(_("%s not supported") % self.method) headers = context["headers"] oauth_headers = oauth.get_oauth_headers(headers) access_token_id = oauth_headers.get("oauth_token") if not access_token_id: raise exception.ValidationError(attribute="oauth_token", target="request") acc_token = self.oauth_api.get_access_token(access_token_id) expires_at = acc_token["expires_at"] if expires_at: now = timeutils.utcnow() expires = timeutils.normalize_time(timeutils.parse_isotime(expires_at)) if now > expires: raise exception.Unauthorized(_("Access token is expired")) url = controller.V3Controller.base_url(context, context["path"]) access_verifier = oauth.ResourceEndpoint( request_validator=validator.OAuthValidator(), token_generator=oauth.token_generator ) result, request = access_verifier.validate_protected_resource_request( url, http_method="POST", body=context["query_string"], headers=headers, realms=None ) if not result: msg = _("Could not validate the access token") raise exception.Unauthorized(msg) auth_context["user_id"] = acc_token["authorizing_user_id"] auth_context["access_token_id"] = access_token_id auth_context["project_id"] = acc_token["project_id"]
def _is_valid_token(self, token): """Verify the token is valid format and has not expired.""" current_time = timeutils.normalize_time(timeutils.utcnow()) try: # Get the data we need from the correct location (V2 and V3 tokens # differ in structure, Try V3 first, fall back to V2 second) token_data = token.get('token', token.get('access')) expires_at = token_data.get('expires_at', token_data.get('expires')) if not expires_at: expires_at = token_data['token']['expires'] expiry = timeutils.normalize_time( timeutils.parse_isotime(expires_at)) except Exception: LOG.exception(_('Unexpected error or malformed token determining ' 'token expiry: %s'), token) raise exception.TokenNotFound(_('Failed to validate token')) if current_time < expiry: self.check_revocation(token) # Token has not expired and has not been revoked. return None else: raise exception.TokenNotFound(_('Failed to validate token'))
def test_cleanup_user_index_on_create(self): valid_token_id = uuid.uuid4().hex second_valid_token_id = uuid.uuid4().hex expired_token_id = uuid.uuid4().hex user_id = unicode(uuid.uuid4().hex) expire_delta = datetime.timedelta(seconds=86400) valid_data = {'id': valid_token_id, 'a': 'b', 'user': {'id': user_id}} second_valid_data = {'id': second_valid_token_id, 'a': 'b', 'user': {'id': user_id}} expired_data = {'id': expired_token_id, 'a': 'b', 'user': {'id': user_id}} self.token_api.create_token(valid_token_id, valid_data) self.token_api.create_token(expired_token_id, expired_data) # NOTE(morganfainberg): Directly access the data cache since we need to # get expired tokens as well as valid tokens. token_api.list_tokens() # will not return any expired tokens in the list. user_key = self.token_api.driver._prefix_user_id(user_id) user_record = self.token_api.driver.client.get(user_key) user_token_list = jsonutils.loads('[%s]' % user_record) self.assertEquals(len(user_token_list), 2) expired_token_ptk = self.token_api.driver._prefix_token_id( expired_token_id) expired_token = self.token_api.driver.client.get(expired_token_ptk) expired_token['expires'] = (timeutils.utcnow() - expire_delta) self.token_api.driver.client.set(expired_token_ptk, expired_token) self.token_api.create_token(second_valid_token_id, second_valid_data) user_record = self.token_api.driver.client.get(user_key) user_token_list = jsonutils.loads('[%s]' % user_record) self.assertEquals(len(user_token_list), 2)
def _convert_user_index_from_json(self, token_list, user_key): try: # NOTE(morganfainberg): Try loading in the old format # of the list. token_list = jsonutils.loads('[%s]' % token_list) # NOTE(morganfainberg): Build a delta based upon the # token TTL configured. Since we are using the old # format index-list, we will create a "fake" expiration # that should be further in the future than the actual # expiry. To avoid locking up keystone trying to # communicate to memcached, it is better to use a fake # value. The logic that utilizes this list already # knows how to handle the case of tokens that are # no longer valid being included. delta = datetime.timedelta( seconds=CONF.token.expiration) new_expiry = timeutils.normalize_time( timeutils.utcnow()) + delta for idx, token_id in enumerate(token_list): token_list[idx] = (token_id, new_expiry) except Exception: # NOTE(morganfainberg): Catch any errors thrown here. There is # nothing the admin or operator needs to do in this case, but # it should be logged that there was an error and some action was # taken to correct it LOG.exception(_('Error converting user-token-index to new format; ' 'clearing user token index record "%s".'), user_key) token_list = [] return token_list
def create_access_token(self, request_token_id, token_duration, access_token_id=None, access_token_secret=None): if access_token_id is None: access_token_id = uuid.uuid4().hex if access_token_secret is None: access_token_secret = uuid.uuid4().hex session = sql.get_session() with session.begin(): req_token_ref = self._get_request_token(session, request_token_id) token_dict = req_token_ref.to_dict() expiry_date = None if token_duration: now = timeutils.utcnow() future = now + datetime.timedelta(seconds=token_duration) expiry_date = timeutils.isotime(future, subsecond=True) # add Access Token ref = {} ref['id'] = access_token_id ref['access_secret'] = access_token_secret ref['authorizing_user_id'] = token_dict['authorizing_user_id'] ref['project_id'] = token_dict['requested_project_id'] ref['role_ids'] = token_dict['role_ids'] ref['consumer_id'] = token_dict['consumer_id'] ref['expires_at'] = expiry_date token_ref = AccessToken.from_dict(ref) session.add(token_ref) # remove request token, it's been used session.delete(req_token_ref) return token_ref.to_dict()
def new_trust_ref(self, trustor_user_id, trustee_user_id, project_id=None, impersonation=None, expires=None, role_ids=None, role_names=None, remaining_uses=None): ref = self.new_ref() ref['trustor_user_id'] = trustor_user_id ref['trustee_user_id'] = trustee_user_id ref['impersonation'] = impersonation or False ref['project_id'] = project_id ref['remaining_uses'] = remaining_uses if isinstance(expires, six.string_types): ref['expires_at'] = expires elif isinstance(expires, dict): ref['expires_at'] = timeutils.strtime( timeutils.utcnow() + datetime.timedelta(**expires), fmt=TIME_FORMAT) elif expires is None: pass else: raise NotImplementedError('Unexpected value for "expires"') role_ids = role_ids or [] role_names = role_names or [] if role_ids or role_names: ref['roles'] = [] for role_id in role_ids: ref['roles'].append({'id': role_id}) for role_name in role_names: ref['roles'].append({'name': role_name}) return ref
def create_access_token(self, request_token_id, token_duration): session = self.get_session() with session.begin(): req_token_ref = self._get_request_token(session, request_token_id) token_dict = req_token_ref.to_dict() expiry_date = None if token_duration: now = timeutils.utcnow() future = now + datetime.timedelta(seconds=token_duration) expiry_date = timeutils.isotime(future, subsecond=True) # add Access Token ref = {} access_token_id = uuid.uuid4().hex ref['id'] = access_token_id ref['access_secret'] = uuid.uuid4().hex ref['authorizing_user_id'] = token_dict['authorizing_user_id'] ref['project_id'] = token_dict['requested_project_id'] ref['requested_roles'] = token_dict['requested_roles'] 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 q = session.query(RequestToken) q = q.filter_by(id=request_token_id) q.delete(False) session.delete(req_token_ref) session.flush() return token_ref.to_dict()
def _is_valid_token(self, token): # Verify the token has not expired. current_time = timeutils.normalize_time(timeutils.utcnow()) try: # Get the data we need from the correct location (V2 and V3 tokens # differ in structure, Try V3 first, fall back to V2 second) token_data = token.get('token', token.get('access')) expires_at = token_data.get('expires_at', token_data.get('expires')) if not expires_at: expires_at = token_data['token']['expires'] expiry = timeutils.normalize_time( timeutils.parse_isotime(expires_at)) if current_time < expiry: # Token is has not expired and has not been revoked. return None except Exception: LOG.exception(_('Unexpected error or malformed token determining ' 'token expiry: %s') % token) # FIXME(morganfainberg): This error message needs to be updated to # reflect the token couldn't be found, but this change needs to wait # until Icehouse due to string freeze in Havana. This should be: # "Failed to find valid token" or something similar. raise exception.TokenNotFound(_('Failed to validate token'))
def delete_tokens(self, user_id, tenant_id=None, trust_id=None): """Deletes all tokens in one session The user_id will be ignored if the trust_id is specified. user_id will always be specified. If using a trust, the token's user_id is set to the trustee's user ID or the trustor's user ID, so will use trust_id to query the tokens. """ session = self.get_session() with session.begin(): now = timeutils.utcnow() query = session.query(TokenModel) query = query.filter_by(valid=True) query = query.filter(TokenModel.expires > now) if trust_id: query = query.filter(TokenModel.trust_id == trust_id) else: query = query.filter(TokenModel.user_id == user_id) for token_ref in query.all(): if tenant_id: token_ref_dict = token_ref.to_dict() if not self._tenant_matches(tenant_id, token_ref_dict): continue token_ref.valid = False session.flush()
def test_cleanup_user_index_on_create(self): valid_token_id = uuid.uuid4().hex second_valid_token_id = uuid.uuid4().hex expired_token_id = uuid.uuid4().hex user_id = six.text_type(uuid.uuid4().hex) expire_delta = datetime.timedelta(seconds=CONF.token.expiration) valid_data = {'id': valid_token_id, 'a': 'b', 'user': {'id': user_id}} second_valid_data = {'id': second_valid_token_id, 'a': 'b', 'user': {'id': user_id}} expired_data = {'id': expired_token_id, 'a': 'b', 'user': {'id': user_id}} self.token_api.create_token(valid_token_id, valid_data) self.token_api.create_token(expired_token_id, expired_data) # NOTE(morganfainberg): Directly access the data cache since we need to # get expired tokens as well as valid tokens. token_api._list_tokens() # will not return any expired tokens in the list. user_key = self.token_api.driver._prefix_user_id(user_id) user_token_list = self.token_api.driver.client.get(user_key) self.assertEqual(len(user_token_list), 2) # user_token_list is a list of (token, expiry) tuples expired_idx = [i[0] for i in user_token_list].index(expired_token_id) # set the token as expired. user_token_list[expired_idx] = (user_token_list[expired_idx][0], timeutils.utcnow() - expire_delta) self.token_api.driver.client.set(user_key, user_token_list) self.token_api.create_token(second_valid_token_id, second_valid_data) user_token_list = self.token_api.driver.client.get(user_key) self.assertEqual(len(user_token_list), 2)
def test_expired_token(self): token_id = uuid.uuid4().hex expire_time = timeutils.utcnow() - datetime.timedelta(minutes=1) data = {"id_hash": token_id, "id": token_id, "a": "b", "expires": expire_time, "user": {"id": "testuserid"}} data_ref = self.token_api.create_token(token_id, data) self.assertDictEqual(data_ref, data) self.assertRaises(exception.TokenNotFound, self.token_api.get_token, token_id)
def delete_trust(self, trust_id): session = db_session.get_session() with session.begin(): trust_ref = session.query(TrustModel).get(trust_id) if not trust_ref: raise exception.TrustNotFound(trust_id=trust_id) trust_ref.deleted_at = timeutils.utcnow()
def setUp(self): super(AuthWithTrust, self).setUp() self.opt_in_group('trust', enabled=True) trust.Manager() self.trust_controller = trust.controllers.TrustV3() self.auth_v3_controller = auth.controllers.Auth() self.trustor = self.user_foo self.trustee = self.user_two self.assigned_roles = [self.role_member['id'], self.role_browser['id']] for assigned_role in self.assigned_roles: self.assignment_api.add_role_to_user_and_project( self.trustor['id'], self.tenant_bar['id'], assigned_role) self.sample_data = {'trustor_user_id': self.trustor['id'], 'trustee_user_id': self.trustee['id'], 'project_id': self.tenant_bar['id'], 'impersonation': True, 'roles': [{'id': self.role_browser['id']}, {'name': self.role_member['name']}]} expires_at = timeutils.strtime(timeutils.utcnow() + datetime.timedelta(minutes=10), fmt=TIME_FORMAT) self.create_trust(expires_at=expires_at)
def get(self, key): """Retrieves the value for a key or None.""" self.check_key(key) obj = self.cache.get(key) now = utils.unixtime(timeutils.utcnow()) if obj and (obj[1] == 0 or obj[1] > now): return obj[0]
def create_request_token(self, consumer_id, roles, project_id, token_duration): expiry_date = None if token_duration: now = timeutils.utcnow() future = now + datetime.timedelta(seconds=token_duration) expiry_date = timeutils.isotime(future, subsecond=True) ref = {} request_token_id = uuid.uuid4().hex ref['id'] = request_token_id ref['request_secret'] = uuid.uuid4().hex ref['verifier'] = None ref['authorizing_user_id'] = None ref['requested_project_id'] = project_id ref['requested_roles'] = roles ref['consumer_id'] = consumer_id ref['expires_at'] = expiry_date self.db.set('request_token-%s' % request_token_id, ref) # add req token to the list that containers the consumers req tokens consumer_requests = set(self.db.get('consumer-%s-requests' % consumer_id, [])) consumer_requests.add(request_token_id) self.db.set('consumer-%s-requests' % consumer_id, list(consumer_requests)) return ref
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 = timeutils.isotime(future, subsecond=True) ref = {} ref['id'] = request_token_id ref['request_secret'] = request_token_secret ref['verifier'] = None ref['authorizing_user_id'] = None ref['requested_project_id'] = project_id ref['role_ids'] = None ref['consumer_id'] = consumer_id ref['expires_at'] = expiry_date session = sql.get_session() with session.begin(): token_ref = RequestToken.from_dict(ref) session.add(token_ref) return token_ref.to_dict()
def flush_expired_tokens(self): session = self.get_session() query = session.query(TokenModel) query = query.filter(TokenModel.expires < timeutils.utcnow()) query.delete(synchronize_session=False) session.flush()
def create_v3_token(): return { "token": { "methods": [], "expires_at": timeutils.isotime(timeutils.utcnow() + FUTURE_DELTA), "issued_at": "2013-05-21T00:02:43.941473Z", } }
def _get_default_expire_time(self): """Determine when a token should expire based on the config. :returns: a naive utc datetime.datetime object """ expire_delta = datetime.timedelta(seconds=CONF.token.expiration) return timeutils.utcnow() + expire_delta
def get_token(self, token_id): session = self.get_session() token_ref = session.query(TokenModel).filter_by(id=token_id).first() now = timeutils.utcnow() if token_ref and (not token_ref.expires or now < token_ref.expires): return token_ref.to_dict() else: raise exception.TokenNotFound(token_id=token_id)
def __init__(self, **kwargs): for k in REVOKE_KEYS: v = kwargs.get(k, None) setattr(self, k, v) if self.revoked_at is None: self.revoked_at = timeutils.utcnow() if self.issued_before is None: self.issued_before = self.revoked_at
def will_expire_soon(expiry): """ Determines if expiration is about to occur. :param expiry: a datetime of the expected expiration :returns: boolean : true if expiration is within 30 seconds """ soon = (timeutils.utcnow() + datetime.timedelta(seconds=30)) return expiry < soon
def test_expired_token(self): token_id = uuid.uuid4().hex expire_time = timeutils.utcnow() - datetime.timedelta(minutes=1) data = {'id': token_id, 'a': 'b', 'expires': expire_time} data_ref = self.token_api.create_token(token_id, data) self.assertDictEqual(data_ref, data) self.assertRaises(exception.TokenNotFound, self.token_api.get_token, token_id)
def get_trust(self, trust_id): session = db_session.get_session() ref = (session.query(TrustModel). filter_by(deleted_at=None). filter_by(id=trust_id).first()) if ref is None: return None if ref.expires_at is not None: now = timeutils.utcnow() if now > ref.expires_at: return None # Do not return trusts that can't be used anymore if ref.remaining_uses is not None: if ref.remaining_uses <= 0: return None trust_dict = ref.to_dict() self._add_roles(trust_id, session, trust_dict) return trust_dict
def test_by_user_expiration(self): future_time = _future_time() user_id = 1 event = self._revoke_by_expiration(user_id, future_time) token_data_1 = _sample_blank_token() token_data_1['user_id'] = user_id token_data_1['expires_at'] = future_time self._assertTokenRevoked(token_data_1) token_data_2 = _sample_blank_token() token_data_2['user_id'] = user_id expire_delta = datetime.timedelta(seconds=2000) future_time = timeutils.utcnow() + expire_delta token_data_2['expires_at'] = future_time self._assertTokenNotRevoked(token_data_2) self.removeEvent(event) self._assertTokenNotRevoked(token_data_1)
def list_tokens(self, user_id, tenant_id=None): tokens = [] now = timeutils.utcnow() for token, ref in self.db.items(): if not token.startswith('token-'): continue if 'user' not in ref: continue if ref['user'].get('id') != user_id: continue if ref.get('expires') and ref.get('expires') < now: continue if tenant_id is not None: if 'tenant' not in ref: continue if ref['tenant'].get('id') != tenant_id: continue tokens.append(token.split('-', 1)[1]) return tokens
def _list_tokens_for_user(self, user_id, tenant_id=None): def user_matches(user_id, ref): return ref.get('user') and ref['user'].get('id') == user_id def tenant_matches(tenant_id, ref): return ((tenant_id is None) or (ref.get('tenant') and ref['tenant'].get('id') == tenant_id)) tokens = [] now = timeutils.utcnow() for token, ref in self.db.items(): if not token.startswith('token-') or self.is_expired(now, ref): continue else: if (user_matches(user_id, ref) and tenant_matches(tenant_id, ref)): tokens.append(token.split('-', 1)[1]) return tokens
def _list_tokens_for_user(self, user_id, tenant_id=None): def tenant_matches(tenant_id, token_ref_dict): return ((tenant_id is None) or (token_ref_dict.get('tenant') and token_ref_dict['tenant'].get('id') == tenant_id)) session = self.get_session() tokens = [] now = timeutils.utcnow() query = session.query(TokenModel) query = query.filter(TokenModel.expires > now) query = query.filter(TokenModel.user_id == user_id) token_references = query.filter_by(valid=True) for token_ref in token_references: token_ref_dict = token_ref.to_dict() if tenant_matches(tenant_id, token_ref_dict): tokens.append(token_ref['id']) return tokens
def test_cleanup_user_index_on_create(self): valid_token_id = uuid.uuid4().hex second_valid_token_id = uuid.uuid4().hex expired_token_id = uuid.uuid4().hex user_id = unicode(uuid.uuid4().hex) expire_delta = datetime.timedelta(seconds=86400) valid_data = {'id': valid_token_id, 'a': 'b', 'user': {'id': user_id}} second_valid_data = { 'id': second_valid_token_id, 'a': 'b', 'user': { 'id': user_id } } expired_data = { 'id': expired_token_id, 'a': 'b', 'user': { 'id': user_id } } self.token_api.create_token(valid_token_id, valid_data) self.token_api.create_token(expired_token_id, expired_data) # NOTE(morganfainberg): Directly access the data cache since we need to # get expired tokens as well as valid tokens. token_api.list_tokens() # will not return any expired tokens in the list. user_key = self.token_api.driver._prefix_user_id(user_id) user_record = self.token_api.driver.client.get(user_key) user_token_list = jsonutils.loads('[%s]' % user_record) self.assertEquals(len(user_token_list), 2) expired_token_ptk = self.token_api.driver._prefix_token_id( expired_token_id) expired_token = self.token_api.driver.client.get(expired_token_ptk) expired_token['expires'] = (timeutils.utcnow() - expire_delta) self.token_api.driver.client.set(expired_token_ptk, expired_token) self.token_api.create_token(second_valid_token_id, second_valid_data) user_record = self.token_api.driver.client.get(user_key) user_token_list = jsonutils.loads('[%s]' % user_record) self.assertEquals(len(user_token_list), 2)
def _prune_expired_events_and_get(self, last_fetch=None, new_event=None): pruned = [] results = [] expire_delta = datetime.timedelta(seconds=CONF.token.expiration) oldest = timeutils.utcnow() - expire_delta # TODO(ayoung): Store the time of the oldest event so that the # prune process can be skipped if none of the events have timed out. with self._store.get_lock(_EVENT_KEY) as lock: events = self._get_event() if new_event is not None: events.append(new_event) for event in events: revoked_at = event.revoked_at if revoked_at > oldest: pruned.append(event) if last_fetch is None or revoked_at > last_fetch: results.append(event) self._store.set(_EVENT_KEY, pruned, lock) return results
def authenticate(self, context, auth_info, auth_context): """Turn a signed request with an access key into a keystone token.""" if not self.oauth_api: raise exception.Unauthorized(_('%s not supported') % self.method) headers = context['headers'] oauth_headers = oauth.get_oauth_headers(headers) access_token_id = oauth_headers.get('oauth_token') if not access_token_id: raise exception.ValidationError(attribute='oauth_token', target='request') acc_token = self.oauth_api.get_access_token(access_token_id) expires_at = acc_token['expires_at'] if expires_at: now = timeutils.utcnow() expires = timeutils.normalize_time( timeutils.parse_isotime(expires_at)) if now > expires: raise exception.Unauthorized(_('Access token is expired')) url = controller.V3Controller.base_url(context, context['path']) access_verifier = oauth.ResourceEndpoint( request_validator=validator.OAuthValidator(), token_generator=oauth.token_generator) result, request = access_verifier.validate_protected_resource_request( url, http_method='POST', body=context['query_string'], headers=headers, realms=None) if not result: msg = _('Could not validate the access token') raise exception.Unauthorized(msg) auth_context['user_id'] = acc_token['authorizing_user_id'] auth_context['access_token_id'] = access_token_id auth_context['project_id'] = acc_token['project_id']
def __init__(self, **kwargs): for k in REVOKE_KEYS: v = kwargs.get(k, None) setattr(self, k, v) if self.domain_id and self.expires_at: # This is revoking a domain-scoped token. self.domain_scope_id = self.domain_id self.domain_id = None else: # This is revoking all tokens for a domain. self.domain_scope_id = None if self.expires_at is not None: # Trim off the expiration time because MySQL timestamps are only # accurate to the second. self.expires_at = self.expires_at.replace(microsecond=0) if self.revoked_at is None: self.revoked_at = timeutils.utcnow() if self.issued_before is None: self.issued_before = self.revoked_at
def create_access_token(self, request_token_id, token_duration, access_token_id=None, access_token_secret=None): if access_token_id is None: access_token_id = uuid.uuid4().hex if access_token_secret is None: access_token_secret = uuid.uuid4().hex session = sql.get_session() with session.begin(): req_token_ref = self._get_request_token(session, request_token_id) token_dict = req_token_ref.to_dict() expiry_date = None if token_duration: now = timeutils.utcnow() future = now + datetime.timedelta(seconds=token_duration) expiry_date = timeutils.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 q = session.query(RequestToken) q = q.filter_by(id=request_token_id) q.delete(False) session.delete(req_token_ref) return token_ref.to_dict()
def list_tokens(self, user_id, tenant_id=None): session = self.get_session() tokens = [] now = timeutils.utcnow() query = session.query(TokenModel) query = query.filter(TokenModel.expires > now) token_references = query.filter_by(valid=True) for token_ref in token_references: token_ref_dict = token_ref.to_dict() user = token_ref_dict.get('user') if not user: continue if user.get('id') != user_id: continue if tenant_id is not None: tenant = token_ref_dict.get('tenant') if not tenant: continue if tenant.get('id') != tenant_id: continue tokens.append(token_ref['id']) return tokens
def create_request_token(self, consumer_id, project_id, token_duration): expiry_date = None if token_duration: now = timeutils.utcnow() future = now + datetime.timedelta(seconds=token_duration) expiry_date = timeutils.isotime(future, subsecond=True) ref = {} request_token_id = uuid.uuid4().hex ref['id'] = request_token_id ref['request_secret'] = uuid.uuid4().hex 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 = self.get_session() with session.begin(): token_ref = RequestToken.from_dict(ref) session.add(token_ref) session.flush() return token_ref.to_dict()
def delete_tokens(self, user_id, tenant_id=None, trust_id=None, consumer_id=None): """Deletes all tokens in one session The user_id will be ignored if the trust_id is specified. user_id will always be specified. If using a trust, the token's user_id is set to the trustee's user ID or the trustor's user ID, so will use trust_id to query the tokens. """ session = self.get_session() with session.begin(): now = timeutils.utcnow() query = session.query(TokenModel) query = query.filter_by(valid=True) query = query.filter(TokenModel.expires > now) if trust_id: query = query.filter(TokenModel.trust_id == trust_id) else: query = query.filter(TokenModel.user_id == user_id) for token_ref in query.all(): if tenant_id: token_ref_dict = token_ref.to_dict() if not self._tenant_matches(tenant_id, token_ref_dict): continue if consumer_id: token_ref_dict = token_ref.to_dict() if not self._consumer_matches(consumer_id, token_ref_dict): continue token_ref.valid = False session.flush()
def __call__(self, request): data = { 'remote_addr': request.remote_addr, 'remote_user': request.remote_user or '-', 'method': request.method, 'url': request.url, 'http_version': request.http_version, 'status': 500, 'content_length': '-'} try: response = request.get_response(self.application) data['status'] = response.status_int data['content_length'] = len(response.body) or '-' finally: # must be calculated *after* the application has been called now = timeutils.utcnow() # timeutils may not return UTC, so we can't hardcode +0000 data['datetime'] = '%s %s' % (now.strftime(APACHE_TIME_FORMAT), now.strftime('%z') or '+0000') LOG.info(APACHE_LOG_FORMAT, data) return response
def _is_valid_token(self, token): """Verify the token is valid format and has not expired.""" current_time = timeutils.normalize_time(timeutils.utcnow()) try: # Get the data we need from the correct location (V2 and V3 tokens # differ in structure, Try V3 first, fall back to V2 second) token_data = token.get('token', token.get('access')) expires_at = token_data.get('expires_at', token_data.get('expires')) if not expires_at: expires_at = token_data['token']['expires'] expiry = timeutils.normalize_time( timeutils.parse_isotime(expires_at)) if current_time < expiry: # Token is has not expired and has not been revoked. return None except Exception: LOG.exception( _('Unexpected error or malformed token determining ' 'token expiry: %s'), token) raise exception.TokenNotFound(_("The token is malformed or expired."))
def create_access_token(self, context): headers = context['headers'] oauth_headers = oauth1.get_oauth_headers(headers) consumer_id = oauth_headers.get('oauth_consumer_key') request_token_id = oauth_headers.get('oauth_token') oauth_verifier = oauth_headers.get('oauth_verifier') if not consumer_id: raise exception.ValidationError(attribute='oauth_consumer_key', target='request') if not request_token_id: raise exception.ValidationError(attribute='oauth_token', target='request') if not oauth_verifier: raise exception.ValidationError(attribute='oauth_verifier', target='request') consumer = self.oauth_api._get_consumer(consumer_id) req_token = self.oauth_api.get_request_token(request_token_id) expires_at = req_token['expires_at'] if expires_at: now = timeutils.utcnow() expires = timeutils.normalize_time( timeutils.parse_isotime(expires_at)) if now > expires: raise exception.Unauthorized(_('Request token is expired')) consumer_obj = oauth1.Consumer(key=consumer['id'], secret=consumer['secret']) req_token_obj = oauth1.Token(key=req_token['id'], secret=req_token['request_secret']) req_token_obj.set_verifier(oauth_verifier) url = oauth1.rebuild_url(context['path']) oauth_request = oauth1.Request.from_request( http_method='POST', http_url=url, headers=context['headers'], query_string=context['query_string']) oauth_server = oauth1.Server() oauth_server.add_signature_method(oauth1.SignatureMethod_HMAC_SHA1()) params = oauth_server.verify_request(oauth_request, consumer_obj, token=req_token_obj) if len(params) != 0: msg = _('There should not be any non-oauth parameters') raise exception.Unauthorized(message=msg) if req_token['consumer_id'] != consumer_id: msg = _('provided consumer key does not match stored consumer key') raise exception.Unauthorized(message=msg) if req_token['verifier'] != oauth_verifier: msg = _('provided verifier does not match stored verifier') raise exception.Unauthorized(message=msg) if req_token['id'] != request_token_id: msg = _('provided request key does not match stored request key') raise exception.Unauthorized(message=msg) if not req_token.get('authorizing_user_id'): msg = _('Request Token does not have an authorizing user id') raise exception.Unauthorized(message=msg) access_token_duration = CONF.oauth1.access_token_duration token_ref = self.oauth_api.create_access_token(request_token_id, access_token_duration) result = ('oauth_token=%(key)s&oauth_token_secret=%(secret)s' % { 'key': token_ref['id'], 'secret': token_ref['access_secret'] }) if CONF.oauth1.access_token_duration: expiry_bit = '&oauth_expires_at=%s' % (token_ref['expires_at']) result += expiry_bit headers = [('Content-Type', 'application/x-www-urlformencoded')] response = wsgi.render_response(result, status=(201, 'Created'), headers=headers) return response
def _validate_expiration(self, token_ref): if timeutils.utcnow() > token_ref['expires']: raise exception.Unauthorized(_('Federation token is expired'))
def _future_time(): expire_delta = datetime.timedelta(seconds=1000) future_time = timeutils.utcnow() + expire_delta return future_time
def flush_expired_tokens(self): now = timeutils.utcnow() for token, token_ref in self.db.items(): if self.is_expired(now, token_ref): self.db.delete(token)
def _sample_blank_token(): issued_delta = datetime.timedelta(minutes=-2) issued_at = timeutils.utcnow() + issued_delta token_data = model.blank_token_data(issued_at) return token_data
def authorize_request_token(self, context, request_token_id, roles): """An authenticated user is going to authorize a request token. As a security precaution, the requested roles must match those in the request token. Because this is in a CLI-only world at the moment, there is not another easy way to make sure the user knows which roles are being requested before authorizing. """ auth_context = context.get('environment', {}).get('KEYSTONE_AUTH_CONTEXT', {}) if auth_context.get('is_delegated_auth'): raise exception.Forbidden( _('Cannot authorize a request token' ' with a token issued via delegation.')) req_token = self.oauth_api.get_request_token(request_token_id) expires_at = req_token['expires_at'] if expires_at: now = timeutils.utcnow() expires = timeutils.normalize_time( timeutils.parse_isotime(expires_at)) if now > expires: raise exception.Unauthorized(_('Request token is expired')) # put the roles in a set for easy comparison authed_roles = set() for role in roles: authed_roles.add(role['id']) # verify the authorizing user has the roles user_token = self.token_api.get_token(context['token_id']) user_id = user_token['user'].get('id') project_id = req_token['requested_project_id'] user_roles = self.assignment_api.get_roles_for_user_and_project( user_id, project_id) cred_set = set(user_roles) if not cred_set.issuperset(authed_roles): msg = _('authorizing user does not have role required') raise exception.Unauthorized(message=msg) # create list of just the id's for the backend role_list = list(authed_roles) # verify the user has the project too req_project_id = req_token['requested_project_id'] user_projects = self.assignment_api.list_projects_for_user(user_id) for user_project in user_projects: if user_project['id'] == req_project_id: break else: msg = _("User is not a member of the requested project") raise exception.Unauthorized(message=msg) # finally authorize the token authed_token = self.oauth_api.authorize_request_token( request_token_id, user_id, role_list) to_return = {'token': {'oauth_verifier': authed_token['verifier']}} return to_return
def soft_delete(self, session=None): """Mark this object as deleted.""" self.deleted = self.id self.deleted_at = timeutils.utcnow() self.save(session=session)
def _future_time_string(): expire_delta = datetime.timedelta(seconds=1000) future_time = timeutils.utcnow() + expire_delta return timeutils.isotime(future_time)
def _assert_valid(self, token_id, token_ref): """Raise TokenNotFound if the token is expired.""" current_time = timeutils.normalize_time(timeutils.utcnow()) expires = token_ref.get('expires') if not expires or current_time > timeutils.normalize_time(expires): raise exception.TokenNotFound(token_id=token_id)
def _determine_expiration_time(self, expires_in): if expires_in is None: expires_in = CONF.saml.assertion_expiration_time now = timeutils.utcnow() future = now + datetime.timedelta(seconds=expires_in) return timeutils.isotime(future, subsecond=True)
def _past_time(): expire_delta = datetime.timedelta(days=-1000) past_time = timeutils.utcnow() + expire_delta return past_time
import datetime from keystone import config from keystone import exception from keystone.openstack.common import timeutils from keystone import tests from keystone.tests import default_fixtures from keystone import token from keystone.token.providers import pki CONF = config.CONF FUTURE_DELTA = datetime.timedelta(seconds=CONF.token.expiration) CURRENT_DATE = timeutils.utcnow() SAMPLE_V2_TOKEN = { "access": { "trust": { "id": "abc123", "trustee_user_id": "123456" }, "serviceCatalog": [ { "endpoints": [ { "adminURL": "http://localhost:8774/v1.1/01257", "id": "51934fe63a5b4ac0a32664f64eb462c3", "internalURL": "http://localhost:8774/v1.1/01257", "publicURL": "http://localhost:8774/v1.1/01257",
def create_access_token(self, context): headers = context['headers'] oauth_headers = oauth1.get_oauth_headers(headers) consumer_id = oauth_headers.get('oauth_consumer_key') request_token_id = oauth_headers.get('oauth_token') oauth_verifier = oauth_headers.get('oauth_verifier') if not consumer_id: raise exception.ValidationError( attribute='oauth_consumer_key', target='request') if not request_token_id: raise exception.ValidationError( attribute='oauth_token', target='request') if not oauth_verifier: raise exception.ValidationError( attribute='oauth_verifier', target='request') req_token = self.oauth_api.get_request_token( request_token_id) expires_at = req_token['expires_at'] if expires_at: now = timeutils.utcnow() expires = timeutils.normalize_time( timeutils.parse_isotime(expires_at)) if now > expires: raise exception.Unauthorized(_('Request token is expired')) url = oauth1.rebuild_url(context['path']) access_verifier = oauth1.AccessTokenEndpoint( request_validator=validator.OAuthValidator(), token_generator=oauth1.token_generator) h, b, s = access_verifier.create_access_token_response( url, http_method='POST', body=context['query_string'], headers=headers) params = oauth1.extract_non_oauth_params(b) if len(params) != 0: msg = _('There should not be any non-oauth parameters') raise exception.Unauthorized(message=msg) if req_token['consumer_id'] != consumer_id: msg = _('provided consumer key does not match stored consumer key') raise exception.Unauthorized(message=msg) if req_token['verifier'] != oauth_verifier: msg = _('provided verifier does not match stored verifier') raise exception.Unauthorized(message=msg) if req_token['id'] != request_token_id: msg = _('provided request key does not match stored request key') raise exception.Unauthorized(message=msg) if not req_token.get('authorizing_user_id'): msg = _('Request Token does not have an authorizing user id') raise exception.Unauthorized(message=msg) access_token_duration = CONF.oauth1.access_token_duration token_ref = self.oauth_api.create_access_token(request_token_id, access_token_duration) result = ('oauth_token=%(key)s&oauth_token_secret=%(secret)s' % {'key': token_ref['id'], 'secret': token_ref['access_secret']}) if CONF.oauth1.access_token_duration: expiry_bit = '&oauth_expires_at=%s' % (token_ref['expires_at']) result += expiry_bit headers = [('Content-Type', 'application/x-www-urlformencoded')] response = wsgi.render_response(result, status=(201, 'Created'), headers=headers) return response
def soft_delete(self, synchronize_session='evaluate'): return self.update({'deleted': literal_column('id'), 'updated_at': literal_column('updated_at'), 'deleted_at': timeutils.utcnow()}, synchronize_session=synchronize_session)