def test_event_save(self): initiator_id = ''.join([c for c in str(uuid.uuid4()) if c != '-']) observer_id = ''.join([c for c in str(uuid.uuid4()) if c != '-']) target_id = ''.join([c for c in str(uuid.uuid4()) if c != '-']) e = event.Event( eventType=cadftype.EVENTTYPE_ACTIVITY, action=cadftaxonomy.ACTION_READ, outcome=cadftaxonomy.OUTCOME_SUCCESS, initiatorId=initiator_id, targetId=target_id, observerId=observer_id, name="test event") pyobj = CADFEventDocType(e) isinstance(pyobj, CADFEventDocType) new_event = event.Event() isinstance(new_event, event.Event) trait_dict = pyobj._get_traits_dict(new_event) isinstance(trait_dict, dict) assert('id' in trait_dict['traits']) assert('eventTime' in trait_dict['traits']) event_saved_flag = pyobj.save(pyobj) assert(event_saved_flag)
def test_event_unique(self): ev = event.Event(eventType='activity', initiator=resource.Resource(typeURI='storage'), action='read', target=resource.Resource(typeURI='storage'), observer=resource.Resource(id='target'), outcome='success') time.sleep(1) ev2 = event.Event(eventType='activity', initiator=resource.Resource(typeURI='storage'), action='read', target=resource.Resource(typeURI='storage'), observer=resource.Resource(id='target'), outcome='success') self.assertNotEqual(ev.id, ev2.id) self.assertNotEqual(ev.eventTime, ev2.eventTime)
def new_event(self, eventType=cadftype.EVENTTYPE_ACTIVITY, **kwargs): # for now, construct a base ('activity') event as the default event_val = event.Event(**kwargs) if not cadftype.is_valid_eventType(eventType): raise ValueError(ERROR_UNKNOWN_EVENTTYPE) event_val.eventType = eventType # TODO(mrutkows): CADF is only being used for basic # 'activity' auditing (on APIs), An IF-ELIF will # become more meaningful as we add support for other # event types. # elif eventType == cadftype.EVENTTYPE_MONITOR: # # TODO(mrutkows): If we add support for standard (NIST) # # monitoring messages, we will would have a "monitor" # # subclass of the CADF Event type and create it here # event_val.set_eventType(cadftype.EVENTTYPE_MONITOR) # elif eventType == cadftype.EVENTTYPE_CONTROL: # # TODO(mrutkows): If we add support for standard (NIST) # # monitoring messages, we will would have a "control" # # subclass of the CADF Event type and create it here # event_val.set_eventType(cadftype.EVENTTYPE_CONTROL) return event_val
def test_event_resource_shortform_not_self(self): self.assertRaises(ValueError, lambda: event.Event( eventType='activity', initiator=resource.Resource(typeURI='storage'), action='read', target=resource.Resource(id='target'), observer=resource.Resource(id='target'), outcome='success')) self.assertRaises(ValueError, lambda: event.Event( eventType='activity', initiator=resource.Resource(id='initiator'), action='read', target=resource.Resource(typeURI='storage'), observer=resource.Resource(id='target'), outcome='success'))
def test_cadf_event(self): initiator_id = ''.join([c for c in str(uuid.uuid4()) if c != '-']) observer_id = ''.join([c for c in str(uuid.uuid4()) if c != '-']) target_id = ''.join([c for c in str(uuid.uuid4()) if c != '-']) # create a CADF event something like (using .as_dict()): # {'action': 'read', # 'eventTime': '2015-12-21T18:47:50.275715+0000', # 'eventType': 'activity', # 'id': '2f38134e-c880-5a38-8b3e-101554a71e37', # 'initiatorId': '46e4be801e0b4c2ab373b26dceedce1a', # 'name': 'test event', # 'observerId': 'a6b012069d174d4fbf9acee03367f068', # 'outcome': 'success', # 'targetId': '005343040e084c3ba90f7bac1b97e1ae', # 'typeURI': 'http://schemas.dmtf.org/cloud/audit/1.0/event'} e = event.Event( eventType=cadftype.EVENTTYPE_ACTIVITY, action=cadftaxonomy.ACTION_READ, outcome=cadftaxonomy.OUTCOME_SUCCESS, initiatorId=initiator_id, targetId=target_id, observerId=observer_id, name="test event") cadf = CADFEventDocType(event=e) result = cadf.save() self.assertTrue(result) # force flush the index so our test has a chance to succeed. cadf._doc_type.using.indices.flush(cadf.meta.index) ge = CADFEventDocType.get(id=cadf.meta.id, index=cadf.meta.index) self.assertEqual(cadf.traits['initiatorId'], ge.traits['initiatorId']) self.assertEqual(cadf.traits['eventTime'], ge.traits['eventTime']) self.assertIsInstance(ge, CADFEventDocType) s = CADFEventDocType.search() s = s.filter('term', ** {'traits.initiatorId': initiator_id})\ .execute() self.assertIsInstance(s, Response) self.assertEqual(len(s.hits), 1) # let's make sure we can delete an object result = cadf.delete() self.assertIsNone(result) # force flush the index so our test has a chance to succeed. cadf._doc_type.using.indices.flush(cadf.meta.index) # we should not be able to find the record now. s2 = CADFEventDocType.search() # Alternate form of filter/query expression since we have a nested # field. r2 = s2.filter('term', ** {'traits.initiatorId': initiator_id})\ .execute() self.assertEqual(len(r2.hits), 0)
def emit_auth_event(ra_name, username, result): success = result is not None params = _event_defaults(success) params['action'] = 'authenticate' params['initiator'] = _user_resource(username, result) auth_res = _auth_resource(ra_name) params['observer'] = auth_res params['target'] = auth_res _emit_event('audit.auth', event.Event(**params))
def emit_signing_event(ra_name, username, result, fingerprint=None): params = _event_defaults(result) params['action'] = 'evaluate' params['initiator'] = _user_resource(username, result) params['observer'] = _policy_resource(ra_name) params['target'] = _certificate_resource(fingerprint) # add when pycadf merges event names # params['name'] = "certificate signing" _emit_event('audit.sign', event.Event(**params))
def test_event(self): ev = event.Event(eventType='activity', id=identifier.generate_uuid(), eventTime=timestamp.get_utc_now(), initiator=resource.Resource(typeURI='storage'), initiatorId=identifier.generate_uuid(), action='read', target=resource.Resource(typeURI='storage'), targetId=identifier.generate_uuid(), observer=resource.Resource(id='target'), observerId=identifier.generate_uuid(), outcome='success', reason=reason.Reason(reasonType='HTTP', reasonCode='200'), severity='high') ev.add_measurement( measurement.Measurement(result='100', metricId=identifier.generate_uuid())), ev.add_tag(tag.generate_name_value_tag('name', 'val')) ev.add_attachment(attachment.Attachment(typeURI='attachURI', content='content', name='attachment_name')) ev.observer = resource.Resource(typeURI='service/security') ev.add_reporterstep(reporterstep.Reporterstep( role='observer', reporter=resource.Resource(typeURI='service/security'))) ev.add_reporterstep(reporterstep.Reporterstep( reporterId=identifier.generate_uuid())) self.assertEqual(ev.is_valid(), False) dict_ev = ev.as_dict() for key in event.EVENT_KEYNAMES: self.assertIn(key, dict_ev) ev = event.Event(eventType='activity', id=identifier.generate_uuid(), eventTime=timestamp.get_utc_now(), initiator=resource.Resource(typeURI='storage'), action='read', target=resource.Resource(typeURI='storage'), observer=resource.Resource(id='target'), outcome='success') self.assertEqual(ev.is_valid(), True) ev = event.Event(eventType='activity', id=identifier.generate_uuid(), eventTime=timestamp.get_utc_now(), initiatorId=identifier.generate_uuid(), action='read', targetId=identifier.generate_uuid(), observerId=identifier.generate_uuid(), outcome='success') self.assertEqual(ev.is_valid(), True) ev = event.Event(eventType='activity', id=identifier.generate_uuid(), eventTime=timestamp.get_utc_now(), initiator=resource.Resource(typeURI='storage'), action='read', targetId=identifier.generate_uuid(), observer=resource.Resource(id='target'), outcome='success') self.assertEqual(ev.is_valid(), True)
def emit_event(self, env, bytes_received, bytes_sent, outcome='success'): path = urlparse.quote(env['PATH_INFO']) method = env['REQUEST_METHOD'] headers = {} for header in env: if header.startswith('HTTP_') and env[header]: key = header[5:] if isinstance(env[header], six.text_type): headers[key] = six.text_type(env[header]) else: headers[key] = str(env[header]) try: container = obj = None version, account, remainder = path.replace('/', '', 1).split('/', 2) if not version or not account: raise ValueError('Invalid path: %s' % path) if remainder: if '/' in remainder: container, obj = remainder.split('/', 1) else: container = remainder except ValueError: return now = timeutils.utcnow().isoformat() resource_metadata = { "path": path, "version": version, "container": container, "object": obj, } for header in self.metadata_headers: if header.upper() in headers: resource_metadata['http_header_%s' % header] = headers.get( header.upper()) # build object store details target = cadf_resource.Resource(typeURI='service/storage/object', id=account.partition( self.reseller_prefix)[2]) target.metadata = resource_metadata target.action = method.lower() # build user details initiator = cadf_resource.Resource( typeURI='service/security/account/user', id=env.get('HTTP_X_USER_ID')) initiator.project_id = env.get('HTTP_X_TENANT_ID') # build notification body event = cadf_event.Event(eventTime=now, outcome=outcome, initiator=initiator, target=target, observer=cadf_resource.Resource(id='target')) # measurements if bytes_received: event.add_measurement( cadf_measurement.Measurement( result=bytes_received, metric=cadf_metric.Metric( name='storage.objects.incoming.bytes', unit='B'))) if bytes_sent: event.add_measurement( cadf_measurement.Measurement( result=bytes_sent, metric=cadf_metric.Metric( name='storage.objects.outgoing.bytes', unit='B'))) self._notifier.info(context.get_admin_context().to_dict(), 'objectstore.http.request', event.as_dict())
def emit_event(self, env, bytes_received, bytes_sent, outcome='success'): if ((env.get('HTTP_X_SERVICE_PROJECT_ID') or env.get('HTTP_X_PROJECT_ID') or env.get('HTTP_X_TENANT_ID')) in self.ignore_projects or env.get('swift.source') is not None): return path = urlparse.quote(env['PATH_INFO']) method = env['REQUEST_METHOD'] headers = {} for header in env: if header.startswith('HTTP_') and env[header]: key = header[5:] if isinstance(env[header], six.text_type): headers[key] = six.text_type(env[header]) else: headers[key] = str(env[header]) try: container = obj = None path = path.replace('/', '', 1) version, account, remainder = path.split('/', 2) except ValueError: try: version, account = path.split('/', 1) remainder = None except ValueError: return try: if not version or not account: raise ValueError('Invalid path: %s' % path) if remainder: if '/' in remainder: container, obj = remainder.split('/', 1) else: container = remainder except ValueError: return now = datetime.datetime.utcnow().isoformat() resource_metadata = { "path": path, "version": version, "container": container, "object": obj, } for header in self.metadata_headers: if header.upper() in headers: resource_metadata['http_header_%s' % header] = headers.get( header.upper()) # build object store details if self.reseller_prefix: target = cadf_resource.Resource( typeURI='service/storage/object', id=account.partition(self.reseller_prefix)[2] or path) else: target = cadf_resource.Resource( typeURI='service/storage/object', id=account) target.metadata = resource_metadata target.action = method.lower() # build user details initiator = cadf_resource.Resource( typeURI='service/security/account/user', id=env.get('HTTP_X_USER_ID')) initiator.project_id = (env.get('HTTP_X_PROJECT_ID') or env.get('HTTP_X_TENANT_ID')) # build notification body event = cadf_event.Event(eventTime=now, outcome=outcome, action=api.convert_req_action(method), initiator=initiator, target=target, observer=cadf_resource.Resource(id='target')) # measurements if bytes_received: event.add_measurement(cadf_measurement.Measurement( result=bytes_received, metric=cadf_metric.Metric( name='storage.objects.incoming.bytes', unit='B'))) if bytes_sent: event.add_measurement(cadf_measurement.Measurement( result=bytes_sent, metric=cadf_metric.Metric( name='storage.objects.outgoing.bytes', unit='B'))) # api call request_metric_name = self.get_request_metric_name(method.lower()) if request_metric_name: event.add_measurement(cadf_measurement.Measurement( result=1, metric=cadf_metric.Metric( name=request_metric_name, unit='request'))) if self.nonblocking_notify: try: Swift.event_queue.put(event, False) if not Swift.event_sender.is_alive(): Swift.threadLock.acquire() self.start_sender_thread() Swift.threadLock.release() except queue.Full: LOG.warning('Send queue FULL: Event %s not added', event.id) else: Swift.send_notification(self._notifier, event)