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 _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 _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( _('Token `%s` is expired, not adding to the ' 'revocation list.'), data['id']) return revoked_token_data['expires'] = timeutils.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( _('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( _('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 build_token_values(token_data): token_expires_at = timeutils.parse_isotime(token_data['expires_at']) # Trim off the microseconds because the revocation event only has # expirations accurate to the second. token_expires_at = token_expires_at.replace(microsecond=0) token_values = { 'expires_at': timeutils.normalize_time(token_expires_at), 'issued_at': timeutils.normalize_time( timeutils.parse_isotime(token_data['issued_at']))} user = token_data.get('user') if user is not None: token_values['user_id'] = user['id'] token_values['identity_domain_id'] = user['domain']['id'] else: token_values['user_id'] = None token_values['identity_domain_id'] = None project = token_data.get('project', token_data.get('tenant')) if project is not None: token_values['project_id'] = project['id'] token_values['assignment_domain_id'] = project['domain']['id'] else: token_values['project_id'] = None domain = token_data.get('domain') if domain is not None: token_values['assignment_domain_id'] = domain['id'] else: token_values['assignment_domain_id'] = None role_list = [] roles = token_data.get('roles') if roles is not None: for role in roles: role_list.append(role['id']) token_values['roles'] = role_list trust = token_data.get('OS-TRUST:trust') if trust is None: token_values['trust_id'] = None token_values['trustor_id'] = None token_values['trustee_id'] = None else: token_values['trust_id'] = trust['id'] token_values['trustor_id'] = trust['trustor_user']['id'] token_values['trustee_id'] = trust['trustee_user']['id'] oauth1 = token_data.get('OS-OAUTH1') if oauth1 is None: token_values['consumer_id'] = None token_values['access_token_id'] = None else: token_values['consumer_id'] = oauth1['consumer_id'] token_values['access_token_id'] = oauth1['access_token_id'] return token_values
def assertServerUsage(self, server, launched_at, terminated_at): resp_launched_at = timeutils.parse_isotime( server.get('%slaunched_at' % self.prefix)) self.assertEqual(timeutils.normalize_time(resp_launched_at), launched_at) resp_terminated_at = timeutils.parse_isotime( server.get('%sterminated_at' % self.prefix)) self.assertEqual(timeutils.normalize_time(resp_terminated_at), terminated_at)
def test_destroy_stubbed(self): self.mox.StubOutWithMock(db, "instance_destroy") deleted_at = datetime.datetime(1955, 11, 6) fake_inst = fake_instance.fake_db_instance(deleted_at=deleted_at, deleted=True) db.instance_destroy(self.context, "fake-uuid", constraint=None).AndReturn(fake_inst) self.mox.ReplayAll() inst = instance.Instance(id=1, uuid="fake-uuid", host="foo") inst.destroy(self.context) self.assertEqual(timeutils.normalize_time(inst.deleted_at), timeutils.normalize_time(deleted_at)) self.assertTrue(inst.deleted)
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(_('Token `%s` is expired, not adding to the ' 'revocation list.'), data['id']) return revoked_token_data['expires'] = timeutils.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(_('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(_('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 test_touch_conductor(self, mock_utcnow): test_time = datetime.datetime(2000, 1, 1, 0, 0) mock_utcnow.return_value = test_time c = self._create_test_cdr() self.assertEqual(test_time, timeutils.normalize_time(c.updated_at)) test_time = datetime.datetime(2000, 1, 1, 0, 1) mock_utcnow.return_value = test_time self.dbapi.touch_conductor(c.hostname) c = self.dbapi.get_conductor(c.hostname) self.assertEqual(test_time, timeutils.normalize_time(c.updated_at))
def build_token_values(token_data): token_values = { 'expires_at': timeutils.normalize_time( timeutils.parse_isotime(token_data['expires_at'])), 'issued_at': timeutils.normalize_time( timeutils.parse_isotime(token_data['issued_at'])) } user = token_data.get('user') if user is not None: token_values['user_id'] = user['id'] token_values['identity_domain_id'] = user['domain']['id'] else: token_values['user_id'] = None token_values['identity_domain_id'] = None project = token_data.get('project', token_data.get('tenant')) if project is not None: token_values['project_id'] = project['id'] token_values['assignment_domain_id'] = project['domain']['id'] else: token_values['project_id'] = None token_values['assignment_domain_id'] = None role_list = [] roles = token_data.get('roles') if roles is not None: for role in roles: role_list.append(role['id']) token_values['roles'] = role_list trust = token_data.get('OS-TRUST:trust') if trust is None: token_values['trust_id'] = None token_values['trustor_id'] = None token_values['trustee_id'] = None else: token_values['trust_id'] = trust['id'] token_values['trustor_id'] = trust['trustor_user']['id'] token_values['trustee_id'] = trust['trustee_user']['id'] oauth1 = token_data.get('OS-OAUTH1') if oauth1 is None: token_values['consumer_id'] = None token_values['access_token_id'] = None else: token_values['consumer_id'] = oauth1['consumer_id'] token_values['access_token_id'] = oauth1['access_token_id'] return token_values
def build_token_values_v2(access, default_domain_id): token_data = access['token'] token_expires_at = timeutils.parse_isotime(token_data['expires']) # Trim off the microseconds because the revocation event only has # expirations accurate to the second. token_expires_at = token_expires_at.replace(microsecond=0) token_values = { 'expires_at': timeutils.normalize_time(token_expires_at), 'issued_at': timeutils.normalize_time( timeutils.parse_isotime(token_data['issued_at'])), 'audit_id': token_data.get('audit_ids', [None])[0], 'audit_chain_id': token_data.get('audit_ids', [None])[-1], } token_values['user_id'] = access.get('user', {}).get('id') project = token_data.get('tenant') if project is not None: token_values['project_id'] = project['id'] else: token_values['project_id'] = None token_values['identity_domain_id'] = default_domain_id token_values['assignment_domain_id'] = default_domain_id trust = token_data.get('trust') if trust is None: token_values['trust_id'] = None token_values['trustor_id'] = None token_values['trustee_id'] = None else: token_values['trust_id'] = trust['id'] token_values['trustor_id'] = trust['trustor_id'] token_values['trustee_id'] = trust['trustee_id'] token_values['consumer_id'] = None token_values['access_token_id'] = None role_list = [] # Roles are by ID in metadata and by name in the user section roles = access.get('metadata', {}).get('roles', []) for role in roles: role_list.append(role) token_values['roles'] = role_list return token_values
def build_token_values(token_data): token_values = { 'expires_at': timeutils.normalize_time( timeutils.parse_isotime(token_data['expires_at'])), 'issued_at': timeutils.normalize_time( timeutils.parse_isotime(token_data['issued_at']))} user = token_data.get('user') if user is not None: token_values['user_id'] = user['id'] token_values['identity_domain_id'] = user['domain']['id'] else: token_values['user_id'] = None token_values['identity_domain_id'] = None project = token_data.get('project', token_data.get('tenant')) if project is not None: token_values['project_id'] = project['id'] token_values['assignment_domain_id'] = project['domain']['id'] else: token_values['project_id'] = None token_values['assignment_domain_id'] = None role_list = [] roles = token_data.get('roles') if roles is not None: for role in roles: role_list.append(role['id']) token_values['roles'] = role_list trust = token_data.get('OS-TRUST:trust') if trust is None: token_values['trust_id'] = None token_values['trustor_id'] = None token_values['trustee_id'] = None else: token_values['trust_id'] = trust['id'] token_values['trustor_id'] = trust['trustor_user']['id'] token_values['trustee_id'] = trust['trustee_user']['id'] oauth1 = token_data.get('OS-OAUTH1') if oauth1 is None: token_values['consumer_id'] = None token_values['access_token_id'] = None else: token_values['consumer_id'] = oauth1['consumer_id'] token_values['access_token_id'] = oauth1['access_token_id'] return token_values
def sanitize_timestamp(timestamp): """Return a naive utc datetime object.""" if not timestamp: return timestamp if not isinstance(timestamp, datetime.datetime): timestamp = timeutils.parse_isotime(timestamp) return timeutils.normalize_time(timestamp)
def record_metering_data(self, data): # We may have receive only one counter on the wire if not isinstance(data, list): data = [data] for meter in data: LOG.debug(_( 'metering data %(counter_name)s ' 'for %(resource_id)s @ %(timestamp)s: %(counter_volume)s') % ({'counter_name': meter['counter_name'], 'resource_id': meter['resource_id'], 'timestamp': meter.get('timestamp', 'NO TIMESTAMP'), 'counter_volume': meter['counter_volume']})) if publisher_utils.verify_signature( meter, self.conf.publisher.metering_secret): try: # Convert the timestamp to a datetime instance. # Storage engines are responsible for converting # that value to something they can store. if meter.get('timestamp'): ts = timeutils.parse_isotime(meter['timestamp']) meter['timestamp'] = timeutils.normalize_time(ts) self.meter_conn.record_metering_data(meter) except Exception as err: LOG.exception(_('Failed to record metering data: %s'), err) else: LOG.warning(_( 'message signature invalid, discarding message: %r'), meter)
def get_events(self, event_filter): iclient = es.client.IndicesClient(self.conn) indices = iclient.get_mapping('%s_*' % self.index_name).keys() if indices: filter_args = self._make_dsl_from_filter(indices, event_filter) results = self.conn.search( fields=['_id', 'timestamp', '_type', '_source'], sort='timestamp:asc', **filter_args) trait_mappings = {} for record in results['hits']['hits']: trait_list = [] if not record['_type'] in trait_mappings: trait_mappings[record['_type']] = list( self.get_trait_types(record['_type'])) for key in record['_source']['traits'].keys(): value = record['_source']['traits'][key] for t_map in trait_mappings[record['_type']]: if t_map['name'] == key: dtype = t_map['data_type'] break trait_list.append( models.Trait(name=key, dtype=dtype, value=models.Trait.convert_value( dtype, value))) gen_ts = timeutils.normalize_time( timeutils.parse_isotime(record['_source']['timestamp'])) yield models.Event(message_id=record['_id'], event_type=record['_type'], generated=gen_ts, traits=sorted( trait_list, key=operator.attrgetter('dtype')))
def test_update_node_provision(self, mock_utcnow): mocked_time = datetime.datetime(2000, 1, 1, 0, 0) mock_utcnow.return_value = mocked_time n = utils.create_test_node() res = self.dbapi.update_node(n['id'], {'provision_state': 'fake'}) self.assertEqual(mocked_time, timeutils.normalize_time(res['provision_updated_at']))
def test_trusted_filter_update_cache_timezone(self, req_mock): oat_data = {"hosts": [{"host_name": "node1", "trust_lvl": "untrusted", "vtime": "2012-09-09T05:10:40-04:00"}]} req_mock.return_value = requests.codes.OK, oat_data extra_specs = {'trust:trusted_host': 'untrusted'} filter_properties = {'context': mock.sentinel.ctx, 'instance_type': {'memory_mb': 1024, 'extra_specs': extra_specs}} host = fakes.FakeHostState('host1', 'node1', {}) timeutils.set_time_override( timeutils.normalize_time( timeutils.parse_isotime("2012-09-09T09:10:40Z"))) self.filt_cls.host_passes(host, filter_properties) # Fill the caches req_mock.reset_mock() self.filt_cls.host_passes(host, filter_properties) self.assertFalse(req_mock.called) req_mock.reset_mock() timeutils.advance_time_seconds( CONF.trusted_computing.attestation_auth_timeout - 10) self.filt_cls.host_passes(host, filter_properties) self.assertFalse(req_mock.called) timeutils.clear_time_override()
def test_update_node_provision(self, mock_utcnow): mocked_time = datetime.datetime(2000, 1, 1, 0, 0) mock_utcnow.return_value = mocked_time n = self._create_test_node() res = self.dbapi.update_node(n['id'], {'provision_state': 'fake'}) self.assertEqual(mocked_time, timeutils.normalize_time(res['provision_updated_at']))
def record_metering_data(self, data): # We may have receive only one counter on the wire if not isinstance(data, list): data = [data] for meter in data: LOG.debug( _('metering data %(counter_name)s ' 'for %(resource_id)s @ %(timestamp)s: %(counter_volume)s') % ({ 'counter_name': meter['counter_name'], 'resource_id': meter['resource_id'], 'timestamp': meter.get('timestamp', 'NO TIMESTAMP'), 'counter_volume': meter['counter_volume'] })) if publisher_utils.verify_signature( meter, self.conf.publisher.metering_secret): try: # Convert the timestamp to a datetime instance. # Storage engines are responsible for converting # that value to something they can store. if meter.get('timestamp'): ts = timeutils.parse_isotime(meter['timestamp']) meter['timestamp'] = timeutils.normalize_time(ts) self.storage_conn.record_metering_data(meter) except Exception as err: LOG.exception(_('Failed to record metering data: %s'), err) else: LOG.warning( _('message signature invalid, discarding message: %r'), meter)
def authenticate(self, context, auth_payload, user_context): try: if 'id' not in auth_payload: raise exception.ValidationError(attribute='id', target=self.method) token_id = auth_payload['id'] response = self.token_provider_api.validate_token(token_id) # For V3 tokens, the essential data is under the 'token' value. # For V2, the comparable data was nested under 'access'. token_ref = response.get('token', response.get('access')) # Do not allow tokens used for delegation to # create another token, or perform any changes of # state in Keystone. To do so is to invite elevation of # privilege attacks if 'OS-TRUST:trust' in token_ref: raise exception.Forbidden() if 'trust' in token_ref: raise exception.Forbidden() if 'trust_id' in token_ref.get('metadata', {}): raise exception.Forbidden() if 'OS-OAUTH1' in token_ref: raise exception.Forbidden() wsgi.validate_token_bind(context, token_ref) # New tokens maintain the audit_id of the original token in the # chain (if possible) as the second element in the audit data # structure. Look for the last element in the audit data structure # which will be either the audit_id of the token (in the case of # a token that has not been rescoped) or the audit_chain id (in # the case of a token that has been rescoped). try: token_audit_id = token_ref.get('audit_ids', [])[-1] except IndexError: # NOTE(morganfainberg): In the case this is a token that was # issued prior to audit id existing, the chain is not tracked. token_audit_id = None # New tokens are not allowed to extend the expiration # time of an old token, otherwise, they could be extened # forever. The expiration value was stored at different # locations in v2 and v3 tokens. expires_at = token_ref.get('expires_at') if not expires_at: expires_at = token_ref.get('expires') if not expires_at: expires_at = timeutils.normalize_time( timeutils.parse_isotime(token_ref['token']['expires'])) user_context.setdefault('expires_at', expires_at) user_context['audit_id'] = token_audit_id user_context.setdefault('user_id', token_ref['user']['id']) user_context['extras'].update(token_ref.get('extras', {})) user_context['method_names'].extend(token_ref.get('methods', [])) except AssertionError as e: LOG.error(e) raise exception.Unauthorized(e)
def convert_value(cls, trait_type, value): if trait_type is cls.INT_TYPE: return int(value) if trait_type is cls.FLOAT_TYPE: return float(value) if trait_type is cls.DATETIME_TYPE: return timeutils.normalize_time(timeutils.parse_isotime(value)) return str(value)
def _init_cache_entry(self, host): self.compute_nodes[host] = { 'trust_lvl': 'unknown', 'vtime': timeutils.normalize_time( timeutils.parse_isotime("1970-01-01T00:00:00Z")) }
def will_expire_soon(self, best_before=BEST_BEFORE_SECONDS): """Determines if expiration is about to occur. :return: boolean : true if expiration is within the given duration """ norm_expires = timeutils.normalize_time(self.expires) soon = (timeutils.utcnow() + datetime.timedelta(seconds=best_before)) return norm_expires < soon
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 = token_model.KeystoneToken( token_id=context["token_id"], token_data=self.token_provider_api.validate_token(context["token_id"]) ) user_id = user_token.user_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 build_token_values_v2(access, default_domain_id): token_data = access['token'] token_values = { 'expires_at': timeutils.normalize_time(timeutils.parse_isotime( token_data['expires'])), 'issued_at': timeutils.normalize_time( timeutils.parse_isotime(token_data['issued_at'])) } token_values['user_id'] = access.get('user', {}).get('id') project = token_data.get('tenant') if project is not None: token_values['project_id'] = project['id'] else: token_values['project_id'] = None token_values['identity_domain_id'] = default_domain_id token_values['assignment_domain_id'] = default_domain_id trust = token_data.get('trust') if trust is None: token_values['trust_id'] = None token_values['trustor_id'] = None token_values['trustee_id'] = None else: token_values['trust_id'] = trust['id'] token_values['trustor_id'] = trust['trustor_id'] token_values['trustee_id'] = trust['trustee_id'] token_values['consumer_id'] = None token_values['access_token_id'] = None role_list = [] # Roles are by ID in metadata and by name in the user section roles = access.get('metadata', {}).get('roles', []) for role in roles: role_list.append(role) token_values['roles'] = role_list return token_values
def _extract_when(body): """Extract the generated datetime from the notification.""" # NOTE: I am keeping the logic the same as it was in the collector, # However, *ALL* notifications should have a 'timestamp' field, it's # part of the notification envelope spec. If this was put here because # some openstack project is generating notifications without a # timestamp, then that needs to be filed as a bug with the offending # project (mdragon) when = body.get('timestamp', body.get('_context_timestamp')) if when: return timeutils.normalize_time(timeutils.parse_isotime(when)) return timeutils.utcnow()
def build_token_values_v2(access, default_domain_id): token_data = access['token'] token_values = { 'expires_at': timeutils.normalize_time( timeutils.parse_isotime(token_data['expires'])), 'issued_at': timeutils.normalize_time( timeutils.parse_isotime(token_data['issued_at']))} token_values['user_id'] = access.get('user', {}).get('id') project = token_data.get('tenant') if project is not None: token_values['project_id'] = project['id'] else: token_values['project_id'] = None token_values['identity_domain_id'] = default_domain_id token_values['assignment_domain_id'] = default_domain_id trust = token_data.get('trust') if trust is None: token_values['trust_id'] = None token_values['trustor_id'] = None token_values['trustee_id'] = None else: token_values['trust_id'] = trust['id'] token_values['trustor_id'] = trust['trustor_id'] token_values['trustee_id'] = trust['trustee_id'] token_values['consumer_id'] = None token_values['access_token_id'] = None role_list = [] # Roles are by ID in metadata and by name in the user section roles = access.get('metadata', {}).get('roles', []) for role in roles: role_list.append(role) token_values['roles'] = role_list return token_values
def _create_token(self, token_id, token_data): try: if isinstance(token_data["expires"], six.string_types): token_data["expires"] = timeutils.normalize_time(timeutils.parse_isotime(token_data["expires"])) self._persistence.create_token(token_id, token_data) except Exception: exc_info = sys.exc_info() # an identical token may have been created already. # if so, return the token_data as it is also identical try: self._persistence.get_token(token_id) except exception.TokenNotFound: six.reraise(*exc_info)
def _create_token(self, token_id, token_data): try: if isinstance(token_data['expires'], six.string_types): token_data['expires'] = timeutils.normalize_time( timeutils.parse_isotime(token_data['expires'])) self.persistence.create_token(token_id, token_data) except Exception: exc_info = sys.exc_info() # an identical token may have been created already. # if so, return the token_data as it is also identical try: self.persistence.get_token(token_id) except exception.TokenNotFound: six.reraise(*exc_info)
def _update_cache_entry(self, state): entry = {} host = state['host_name'] entry['trust_lvl'] = state['trust_lvl'] try: # Normalize as naive object to interoperate with utcnow(). entry['vtime'] = timeutils.normalize_time( timeutils.parse_isotime(state['vtime'])) except ValueError: try: # Mt. Wilson does not necessarily return an ISO8601 formatted # `vtime`, so we should try to parse it as a string formatted # datetime. vtime = timeutils.parse_strtime(state['vtime'], fmt="%c") entry['vtime'] = timeutils.normalize_time(vtime) except ValueError: # Mark the system as un-trusted if get invalid vtime. entry['trust_lvl'] = 'unknown' entry['vtime'] = timeutils.utcnow() self.compute_nodes[host] = entry
def will_expire_soon(self, stale_duration=None): """Determines if expiration is about to occur. :returns: boolean : true if expiration is within the given duration """ stale_duration = (STALE_TOKEN_DURATION if stale_duration is None else stale_duration) norm_expires = timeutils.normalize_time(self.expires) # (gyee) should we move auth_token.will_expire_soon() to timeutils # instead of duplicating code here? soon = (timeutils.utcnow() + datetime.timedelta( seconds=stale_duration)) return norm_expires < soon
def terminate_unneeded_clusters(self, ctx): LOG.debug('Terminating unneeded transient clusters') ctx = context.get_admin_context() context.set_ctx(ctx) for cluster in conductor.cluster_get_all(ctx, status='Active'): if not cluster.is_transient: continue jc = conductor.job_execution_count(ctx, end_time=None, cluster_id=cluster.id) if jc > 0: continue cluster_updated_at = timeutils.normalize_time( timeutils.parse_isotime(cluster.updated_at)) current_time = timeutils.utcnow() spacing = timeutils.delta_seconds(cluster_updated_at, current_time) if spacing < CONF.min_transient_cluster_active_time: continue if CONF.use_identity_api_v3: trusts.use_os_admin_auth_token(cluster) LOG.info( _LI('Terminating transient cluster %(cluster)s ' 'with id %(id)s'), { 'cluster': cluster.name, 'id': cluster.id }) try: ops.terminate_cluster(cluster.id) except Exception as e: LOG.info( _LI('Failed to terminate transient cluster ' '%(cluster)s with id %(id)s: %(error)s.'), { 'cluster': cluster.name, 'id': cluster.id, 'error': six.text_type(e) }) else: if cluster.status != 'AwaitingTermination': conductor.cluster_update( ctx, cluster, {'status': 'AwaitingTermination'}) context.set_ctx(None)
def test_get_events(self): data = self.get_json(self.PATH, headers=headers) self.assertEqual(3, len(data)) # We expect to get native UTC generated time back expected_generated = timeutils.strtime( at=timeutils.normalize_time(self.trait_time), fmt=timeutils._ISO8601_TIME_FORMAT) for event in data: self.assertTrue(event['event_type'] in ['Foo', 'Bar', 'Zoo']) self.assertEqual(4, len(event['traits'])) self.assertEqual(expected_generated, event['generated']) for trait_name in ['trait_A', 'trait_B', 'trait_C', 'trait_D']: self.assertTrue(trait_name in map(lambda x: x['name'], event['traits']))
def publish_samples(self, context, samples): if not isinstance(samples, list): samples = [samples] # Transform the Sample objects into a list of dicts meters = [ utils.meter_message_from_counter( sample, cfg.CONF.publisher.metering_secret) for sample in samples ] for meter in meters: if meter.get('timestamp'): ts = timeutils.parse_isotime(meter['timestamp']) meter['timestamp'] = timeutils.normalize_time(ts) self.meter_conn.record_metering_data(meter)
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.' % ( timeutils.isotime(event_issued_before, subsecond=True), timeutils.isotime(before_time, subsecond=True))) self.assertTrue( event_issued_before <= after_time, 'invalid event issued_before time; %s is not earlier than %s.' % ( timeutils.isotime(event_issued_before, subsecond=True), timeutils.isotime(after_time, subsecond=True))) del (event['issued_before']) self.assertEqual(sample, event)
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.' % (timeutils.isotime(event_issued_before, subsecond=True), timeutils.isotime(before_time, subsecond=True))) self.assertTrue( event_issued_before <= after_time, 'invalid event issued_before time; %s is not earlier than %s.' % (timeutils.isotime(event_issued_before, subsecond=True), timeutils.isotime(after_time, subsecond=True))) del (event['issued_before']) self.assertEqual(sample, event)
def create_trust(self, trust_id, trust, roles): with sql.transaction() as session: ref = TrustModel.from_dict(trust) ref["id"] = trust_id if ref.get("expires_at") and ref["expires_at"].tzinfo is not None: ref["expires_at"] = timeutils.normalize_time(ref["expires_at"]) session.add(ref) added_roles = [] for role in roles: trust_role = TrustRole() trust_role.trust_id = trust_id trust_role.role_id = role["id"] added_roles.append({"id": role["id"]}) session.add(trust_role) trust_dict = ref.to_dict() trust_dict["roles"] = added_roles return trust_dict
def create_trust(self, trust_id, trust, roles): with sql.transaction() as session: ref = TrustModel.from_dict(trust) ref['id'] = trust_id if ref.get('expires_at') and ref['expires_at'].tzinfo is not None: ref['expires_at'] = timeutils.normalize_time(ref['expires_at']) session.add(ref) added_roles = [] for role in roles: trust_role = TrustRole() trust_role.trust_id = trust_id trust_role.role_id = role['id'] added_roles.append({'id': role['id']}) session.add(trust_role) trust_dict = ref.to_dict() trust_dict['roles'] = added_roles return trust_dict
def terminate_unneeded_clusters(self, ctx): LOG.debug('Terminating unneeded transient clusters') ctx = context.get_admin_context() context.set_ctx(ctx) for cluster in conductor.cluster_get_all(ctx, status='Active'): if not cluster.is_transient: continue jc = conductor.job_execution_count(ctx, end_time=None, cluster_id=cluster.id) if jc > 0: continue cluster_updated_at = timeutils.normalize_time( timeutils.parse_isotime(cluster.updated_at)) current_time = timeutils.utcnow() spacing = timeutils.delta_seconds(cluster_updated_at, current_time) if spacing < CONF.min_transient_cluster_active_time: continue if CONF.use_identity_api_v3: trusts.use_os_admin_auth_token(cluster) LOG.info(_LI('Terminating transient cluster %(cluster)s ' 'with id %(id)s'), {'cluster': cluster.name, 'id': cluster.id}) try: ops.terminate_cluster(cluster.id) except Exception as e: LOG.info(_LI('Failed to terminate transient cluster ' '%(cluster)s with id %(id)s: %(error)s.'), {'cluster': cluster.name, 'id': cluster.id, 'error': six.text_type(e)}) else: if cluster.status != 'AwaitingTermination': conductor.cluster_update( ctx, cluster, {'status': 'AwaitingTermination'}) context.set_ctx(None)
def authenticate(self, context, auth_payload, user_context): try: if 'id' not in auth_payload: raise exception.ValidationError(attribute='id', target=self.method) token_id = auth_payload['id'] response = self.token_provider_api.validate_token(token_id) # For V3 tokens, the essential data is under the 'token' value. # For V2, the comparable data was nested under 'access'. token_ref = response.get('token', response.get('access')) # Do not allow tokens used for delegation to # create another token, or perform any changes of # state in Keystone. To do so is to invite elevation of # privilege attacks if 'OS-TRUST:trust' in token_ref: raise exception.Forbidden() if 'trust' in token_ref: raise exception.Forbidden() if 'trust_id' in token_ref.get('metadata', {}): raise exception.Forbidden() if 'OS-OAUTH1' in token_ref: raise exception.Forbidden() wsgi.validate_token_bind(context, token_ref) # New tokens are not allowed to extend the expiration # time of an old token, otherwise, they could be extened # forever. The expiration value was stored at different # locations in v2 and v3 tokens. expires_at = token_ref.get('expires_at') if not expires_at: expires_at = token_ref.get('expires') if not expires_at: expires_at = timeutils.normalize_time( timeutils.parse_isotime(token_ref['token']['expires'])) user_context.setdefault('expires_at', expires_at) user_context.setdefault('user_id', token_ref['user']['id']) user_context['extras'].update(token_ref.get('extras', {})) user_context['method_names'].extend(token_ref.get('methods', [])) except AssertionError as e: LOG.error(e) raise exception.Unauthorized(e)
def _format_token_index_item(self, item): try: token_id, expires = item except (TypeError, ValueError): LOG.debug(('Invalid token entry expected tuple of ' '`(<token_id>, <expires>)` got: `%(item)r`'), dict(item=item)) raise try: expires = timeutils.normalize_time( timeutils.parse_isotime(expires)) except ValueError: LOG.debug(('Invalid expires time on token `%(token_id)s`:' ' %(expires)r'), dict(token_id=token_id, expires=expires)) raise return token_id, expires
def authenticate(self, context, auth_payload, user_context): try: if "id" not in auth_payload: raise exception.ValidationError(attribute="id", target=self.method) token_id = auth_payload["id"] response = self.token_provider_api.validate_token(token_id) # For V3 tokens, the essential data is under the 'token' value. # For V2, the comparable data was nested under 'access'. token_ref = response.get("token", response.get("access")) # Do not allow tokens used for delegation to # create another token, or perform any changes of # state in Keystone. To do so is to invite elevation of # privilege attacks if "OS-TRUST:trust" in token_ref: raise exception.Forbidden() if "trust" in token_ref: raise exception.Forbidden() if "trust_id" in token_ref.get("metadata", {}): raise exception.Forbidden() if "OS-OAUTH1" in token_ref: raise exception.Forbidden() wsgi.validate_token_bind(context, token_ref) # New tokens are not allowed to extend the expiration # time of an old token, otherwise, they could be extened # forever. The expiration value was stored at different # locations in v2 and v3 tokens. expires_at = token_ref.get("expires_at") if not expires_at: expires_at = token_ref.get("expires") if not expires_at: expires_at = timeutils.normalize_time(timeutils.parse_isotime(token_ref["token"]["expires"])) user_context.setdefault("expires_at", expires_at) user_context.setdefault("user_id", token_ref["user"]["id"]) user_context["extras"].update(token_ref.get("extras", {})) user_context["method_names"].extend(token_ref.get("methods", [])) except AssertionError as e: LOG.error(e) raise exception.Unauthorized(e)
def create_trust(self, trust_id, trust, roles): trust_ref = copy.deepcopy(trust) trust_ref['id'] = trust_id trust_ref['deleted_at'] = None trust_ref['roles'] = roles if (trust_ref.get('expires_at') and trust_ref['expires_at'].tzinfo is not None): trust_ref['expires_at'] = (timeutils.normalize_time (trust_ref['expires_at'])) self.db.set('trust-%s' % trust_id, trust_ref) trustee_user_id = trust_ref['trustee_user_id'] trustee_list = self.db.get('trustee-%s' % trustee_user_id, []) trustee_list.append(trust_id) self.db.set('trustee-%s' % trustee_user_id, trustee_list) trustor_user_id = trust_ref['trustor_user_id'] trustor_list = self.db.get('trustor-%s' % trustor_user_id, []) trustor_list.append(trust_id) self.db.set('trustor-%s' % trustor_user_id, trustor_list) return trust_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 list_revoke_events(self, context): since = context['query_string'].get('since') last_fetch = None if since: try: last_fetch = timeutils.normalize_time( timeutils.parse_isotime(since)) except ValueError: raise exception.ValidationError( message=_('invalid date format %s') % since) events = self.revoke_api.get_events(last_fetch=last_fetch) # Build the links by hand as the standard controller calls require ids response = {'events': [event.to_dict() for event in events], 'links': { 'next': None, 'self': RevokeController.base_url( context, path=context['path']), 'previous': None} } return response
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 list_revoke_events(self, context): since = context['query_string'].get('since') last_fetch = None if since: try: last_fetch = timeutils.normalize_time( timeutils.parse_isotime(since)) except ValueError: raise exception.ValidationError( message=_('invalid date format %s') % since) events = self.revoke_api.get_events(last_fetch=last_fetch) # Build the links by hand as the standard controller calls require ids response = { 'events': [event.to_dict() for event in events], 'links': { 'next': None, 'self': RevokeController.base_url(context, path=context['path']), 'previous': None } } return response
def verify_message_stats(self, message): """Verifies the oldest & newest message stats :param message: oldest (or) newest message returned by queue_name/stats. """ expected_keys = ['age', 'created', 'href'] response_keys = message.keys() response_keys = sorted(response_keys) self.assertEqual(response_keys, expected_keys) # Verify that age has valid values age = message['age'] self.assertTrue(0 <= age <= self.limits.max_message_ttl, msg='Invalid Age {0}'.format(age)) # Verify that GET on href returns 200 path = message['href'] result = self.client.get(path) self.assertEqual(result.status_code, 200) # Verify that created time falls within the last 10 minutes # NOTE(malini): The messages are created during the test. created_time = message['created'] created_time = timeutils.normalize_time( timeutils.parse_isotime(created_time)) now = timeutils.utcnow() delta = timeutils.delta_seconds(before=created_time, after=now) # NOTE(malini): The 'int()' below is a work around for the small time # difference between julianday & UTC. # (needed to pass this test on sqlite driver) delta = int(delta) msg = ('Invalid Time Delta {0}, Created time {1}, Now {2}'.format( delta, created_time, now)) self.assertTrue(0 <= delta <= 6000, msg)
def test_trusted_filter_update_cache_timezone(self, req_mock): oat_data = { "hosts": [{ "host_name": "node1", "trust_lvl": "untrusted", "vtime": "2012-09-09T05:10:40-04:00" }] } req_mock.return_value = requests.codes.OK, oat_data extra_specs = {'trust:trusted_host': 'untrusted'} filter_properties = { 'context': mock.sentinel.ctx, 'instance_type': { 'memory_mb': 1024, 'extra_specs': extra_specs } } host = fakes.FakeHostState('host1', 'node1', {}) timeutils.set_time_override( timeutils.normalize_time( timeutils.parse_isotime("2012-09-09T09:10:40Z"))) self.filt_cls.host_passes(host, filter_properties) # Fill the caches req_mock.reset_mock() self.filt_cls.host_passes(host, filter_properties) self.assertFalse(req_mock.called) req_mock.reset_mock() timeutils.advance_time_seconds( CONF.trusted_computing.attestation_auth_timeout - 10) self.filt_cls.host_passes(host, filter_properties) self.assertFalse(req_mock.called) timeutils.clear_time_override()
def _tenant_usages_for_period(self, context, period_start, period_stop, tenant_id=None, detailed=True): instances = objects.InstanceList.get_active_by_window_joined( context, period_start, period_stop, tenant_id, expected_attrs=instance_obj.INSTANCE_DEFAULT_FIELDS) rval = {} flavors = {} for instance in instances: info = {} info['hours'] = self._hours_for(instance, period_start, period_stop) flavor = self._get_flavor(context, instance, flavors) if not flavor: info['flavor'] = '' else: info['flavor'] = flavor.name info['instance_id'] = instance.uuid info['name'] = instance.display_name info['memory_mb'] = instance.memory_mb info['local_gb'] = instance.root_gb + instance.ephemeral_gb info['vcpus'] = instance.vcpus info['tenant_id'] = instance.project_id # NOTE(mriedem): We need to normalize the start/end times back # to timezone-naive so the response doesn't change after the # conversion to objects. info['started_at'] = timeutils.normalize_time(instance.launched_at) info['ended_at'] = (timeutils.normalize_time( instance.terminated_at) if instance.terminated_at else None) if info['ended_at']: info['state'] = 'terminated' else: info['state'] = instance.vm_state now = timeutils.utcnow() if info['state'] == 'terminated': delta = info['ended_at'] - info['started_at'] else: delta = now - info['started_at'] info['uptime'] = delta.days * 24 * 3600 + delta.seconds if info['tenant_id'] not in rval: summary = {} summary['tenant_id'] = info['tenant_id'] if detailed: summary['server_usages'] = [] summary['total_local_gb_usage'] = 0 summary['total_vcpus_usage'] = 0 summary['total_memory_mb_usage'] = 0 summary['total_hours'] = 0 summary['start'] = timeutils.normalize_time(period_start) summary['stop'] = timeutils.normalize_time(period_stop) rval[info['tenant_id']] = summary summary = rval[info['tenant_id']] summary['total_local_gb_usage'] += info['local_gb'] * info['hours'] summary['total_vcpus_usage'] += info['vcpus'] * info['hours'] summary['total_memory_mb_usage'] += (info['memory_mb'] * info['hours']) summary['total_hours'] += info['hours'] if detailed: summary['server_usages'].append(info) return rval.values()
def _get_current_time(self): return timeutils.normalize_time(timeutils.utcnow())