def process_raw_event(self, raw_event): raw_event_d = json.loads(raw_event) # need to find the jamf instance jamf_instance = self.get_jamf_instance(raw_event_d) zentral_log_type = raw_event_d["zentral_log_type"] event = None if zentral_log_type == "zentral.contrib.jamf.jamf_change_management": event = self.build_change_management_event(raw_event_d, jamf_instance) elif zentral_log_type == "zentral.contrib.jamf.jamf_software_server": event = self.build_software_server_event(raw_event_d) elif zentral_log_type == "zentral.contrib.jamf.jss_access": event = self.build_access_event(raw_event_d) elif zentral_log_type == "zentral.contrib.jamf.client": event = self.build_client_event(raw_event_d) else: logger.warning("Unknown zentral_log_type %s", zentral_log_type) return if event: # add EventRequest user_agent, ip_address = get_user_agent_and_ip_address_from_raw_event( raw_event_d) event.metadata.request = EventRequest(user_agent, ip_address) # if possible add jamf instance as EventObserver if jamf_instance: event.metadata.observer = EventObserver.deserialize( jamf_instance.observer_dict()) yield event
def user_login_failed_callback(sender, credentials, **kwargs): request = kwargs.get("request") # introduced in django 1.11 if request: request = EventRequest.build_from_request(request) metadata = EventMetadata(request=request) event = FailedLoginEvent(metadata, {"user": {k: str(v) for k, v in credentials.items() if k in ("username",)}}) event.post()
def post_results(msn, user_agent, ip, results): event_uuid = uuid.uuid4() if user_agent or ip: request = EventRequest(user_agent, ip) else: request = None cc_status_agg = ComplianceCheckStatusAggregator(msn) for index, result in enumerate(_iter_cleaned_up_records(results)): try: event_time = _get_record_created_at(result) except Exception: logger.exception("Could not extract osquery result time") event_time = None metadata = EventMetadata(uuid=event_uuid, index=index, machine_serial_number=msn, request=request, created_at=event_time) event = OsqueryResultEvent(metadata, result) event.post() snapshot = event.payload.get("snapshot") if snapshot is None: # no snapshot, cannot be a compliance check continue try: _, query_pk, query_version = event.parse_result_name() except ValueError as e: logger.warning(str(e)) continue cc_status_agg.add_result(query_pk, query_version, event_time, snapshot) cc_status_agg.commit_and_post_events()
def post_group_membership_updates(request, added_groups, removed_groups, user=None): event_request = EventRequest.build_from_request(request) created_at = datetime.utcnow() event_uuid = uuid.uuid4() event_index = 0 base_payload = {} if user: base_payload["user"] = { "pk": user.pk, "username": user.username, "is_service_account": user.is_service_account } if added_groups: for added_group in added_groups: event_metadata = EventMetadata(request=event_request, uuid=event_uuid, index=event_index, created_at=created_at) payload = base_payload.copy() payload["group"] = {"pk": added_group.pk, "name": added_group.name} event = AddUserToGroupEvent(event_metadata, payload) event.post() event_index += 1 if removed_groups: for removed_group in removed_groups: event_metadata = EventMetadata(request=event_request, uuid=event_uuid, index=event_index, created_at=created_at) payload = base_payload.copy() payload["group"] = {"pk": removed_group.pk, "name": removed_group.name} event = RemoveUserFromGroupEvent(event_metadata, payload) event.post() event_index += 1
def post_event(event_cls, request, user, payload=None): if payload is None: payload = {} metadata = EventMetadata(request=EventRequest.build_from_request(request)) if user and user != request.user: payload["user"] = {"pk": user.pk, "username": user.username} event = event_cls(metadata, payload) event.post()
def post_sync_started_event(instance, serialized_event_request): request = None if serialized_event_request: request = EventRequest.deserialize(serialized_event_request) metadata = EventMetadata(request=request) event = WSOneInstanceSyncStarted( metadata, {"instance": instance.serialize_for_event()}) event.post()
def post_munki_request_event(msn, user_agent, ip, **kwargs): metadata = EventMetadata( machine_serial_number=msn, request=EventRequest(user_agent, ip), incident_updates=kwargs.pop("incident_updates", []) ) event = MunkiRequestEvent(metadata, kwargs) event.post()
def user_login_failed_callback(sender, credentials, **kwargs): request = kwargs.get("request") # introduced in django 1.11 if request: request = EventRequest.build_from_request(request) metadata = EventMetadata(FailedLoginEvent.event_type, request=request, tags=FailedLoginEvent.tags) event = FailedLoginEvent(metadata, credentials) event.post()
def post_enrollment_secret_verification_success(request, model): obj = getattr(request.enrollment_secret, model) event_cls = EnrollmentSecretVerificationEvent metadata = EventMetadata(machine_serial_number=request.serial_number, request=EventRequest(request.user_agent, request.public_ip_address)) payload = {"status": "success", "type": model} payload.update(obj.serialize_for_event()) event = event_cls(metadata, payload) event.post()
def post_monolith_sync_catalogs_request(user_agent, ip): event_class = MonolithSyncCatalogsRequestEvent if user_agent or ip: request = EventRequest(user_agent, ip) else: request = None metadata = EventMetadata(event_class.event_type, request=request, tags=event_class.tags) event = event_class(metadata, {}) event.post()
def post_sync_finished_event(instance, serialized_event_request, result): request = None if serialized_event_request: request = EventRequest.deserialize(serialized_event_request) metadata = EventMetadata(request=request) event = WSOneInstanceSyncFinished( metadata, { "instance": instance.serialize_for_event(), "sync": result }) event.post()
def post_monolith_repository_updates(repository, payloads, request=None): event_class = MonolithRepositoryUpdateEvent repository_serialized_info = repository.serialize_for_event() if request: request = EventRequest.build_from_request(request) event_uuid = uuid.uuid4() for index, payload in enumerate(payloads): metadata = EventMetadata(uuid=event_uuid, index=index, request=request) payload.update({"repository": repository_serialized_info}) event = event_class(metadata, payload) event.post()
def make_event(ip=None, ua=None, with_msn=True): msn = request = None if with_msn: msn = "0123456789" if ip or ua: request = EventRequest(user_agent=ua, ip=ip) else: request = None return TestEvent3( EventMetadata(machine_serial_number=msn, request=request), {"godzilla": "yo"})
def _deserialize_event(self, doc): doc.pop('stored_at') event_type = doc.pop('event_type') payload = doc.pop('payload') user_agent, ip = doc.pop('user_agent'), doc.pop('ip') if user_agent or ip: doc['request'] = EventRequest(user_agent, ip) else: doc['request'] = None event_cls = event_cls_from_type(event_type) event = event_cls(EventMetadata(event_type, **doc), payload) return event
def post_event(event_cls, request, user): request = EventRequest.build_from_request(request) payload = {} # TODO: check if user can be different than request.user # remove the following bit if not eru = EventRequestUser.build_from_user(user) if eru: payload["user"] = eru.serialize() metadata = EventMetadata(event_cls.event_type, request=request, tags=event_cls.tags) event = event_cls(metadata, payload) event.post()
def post_munki_events(msn, user_agent, ip, data): for report in data: events = report.pop('events') metadata = EventMetadata(MunkiEvent.event_type, machine_serial_number=msn, request=EventRequest(user_agent, ip), tags=MunkiEvent.tags) for index, (created_at, payload) in enumerate(events): metadata.index = index metadata.created_at = parser.parse(created_at) payload.update(report) event = MunkiEvent(metadata, payload) event.post()
def make_event(idx=0, first_type=True, with_request=True): if first_type: event_cls = TestEvent1 else: event_cls = TestEvent2 if with_request: request = EventRequest("python_unittest_useragent", "10.0.0.1") else: request = None return event_cls( EventMetadata(event_cls.event_type, machine_serial_number='012356789', request=request), {'idx': idx})
def post(self, request, *args, **kwargs): instance = get_object_or_404(Instance, pk=self.kwargs["pk"]) event_request = EventRequest.build_from_request(request) result = sync_inventory.apply_async( (instance.pk, event_request.serialize())) return Response( { "task_id": result.id, "task_result_url": reverse("base_api:task_result", args=(result.id, )) }, status=status.HTTP_201_CREATED)
def post_osquery_pack_update_events(request, pack_data, pack_queries_data): event_request = EventRequest.build_from_request(request) pack_update_event_metadata = EventMetadata(request=event_request) pack_update_event = OsqueryPackUpdateEvent(pack_update_event_metadata, pack_data) pack_update_event.post() for idx, pack_query_data in enumerate(pack_queries_data): pack_query_update_event_metadata = EventMetadata( request=event_request, uuid=pack_update_event_metadata.uuid, index=idx + 1) pack_query_update_event = OsqueryPackQueryUpdateEvent( pack_query_update_event_metadata, pack_query_data) pack_query_update_event.post()
def post_santa_ruleset_update_events(request, ruleset_data, rules_data): event_request = EventRequest.build_from_request(request) ruleset_update_event_metadata = EventMetadata(request=event_request) ruleset_update_event = SantaRuleSetUpdateEvent( ruleset_update_event_metadata, ruleset_data) ruleset_update_event.post() for idx, rule_data in enumerate(rules_data): rule_update_event_metadata = EventMetadata( request=event_request, uuid=ruleset_update_event_metadata.uuid, index=idx + 1) rule_update_event = SantaRuleUpdateEvent(rule_update_event_metadata, rule_data) rule_update_event.post()
def post_enrollment_secret_verification_failure(model, user_agent, public_ip_address, serial_number, err_msg, enrollment_secret): event_cls = EnrollmentSecretVerificationEvent metadata = EventMetadata(machine_serial_number=serial_number, request=EventRequest(user_agent, public_ip_address)) payload = {"status": "failure", "reason": err_msg, "type": model} if enrollment_secret: obj = getattr(enrollment_secret, model) payload.update(obj.serialize_for_event()) event = event_cls(metadata, payload) event.post()
def post_event(event_cls, request, user, payload=None): if payload is None: payload = {} # TODO: check if user can be different than request.user # remove the following bit if not eru = EventRequestUser.build_from_user(user) if eru: payload["user"] = eru.serialize() seabc = request.session.get_expire_at_browser_close() payload["session"] = {"expire_at_browser_close": seabc} if not seabc: payload["session"].update( {"expiry_age": request.session.get_expiry_age()}) # realm user payload["realm_session"] = False ras_uuid = request.session.get("_realm_authentication_session") if ras_uuid: try: ras = RealmAuthenticationSession.objects.select_related( "realm", "user").get(uuid=ras_uuid) except RealmAuthenticationSession.DoesNotExist: logger.error("Could not find realm authentication session %s", ras_uuid) else: realm = ras.realm payload["realm_session"] = True payload["realm_user"] = { "realm": { "uuid": realm.uuid, "name": str(realm), "backend": realm.backend }, "session": { "uuid": ras.uuid, "created_at": ras.created_at, "updated_at": ras.updated_at, "expires": ras.expires_at is not None, "expires_at": ras.expires_at }, "uuid": ras.user.uuid } event_request = EventRequest.build_from_request(request) metadata = EventMetadata(event_cls.event_type, request=event_request, tags=event_cls.tags) event = event_cls(metadata, payload) event.post()
def post_okta_events(event_hook, data): event_observer = EventObserver(**event_hook.observer_dict()) for event in data["data"]["events"]: event_type = event["eventType"] if event_type == "user.session.start": event_cls = OktaUserSessionStart elif event_type == "user.session.end": event_cls = OktaUserSessionEnd else: logger.error("Unknown Okta event type '%s'", event_type) continue client_d = event.get("client") client_ip = client_d.get("ipAddress") client_user_agent = client_d.get("userAgent", {}).get("rawUserAgent") client_geo = client_d.get("geographicalContext", {}) if client_geo: event_request_geo = EventRequestGeo( country_name=client_geo.get("country"), city_name=client_geo.get("city"), region_name=client_geo.get("state"), location=client_geo.get("geolocation")) else: event_request_geo = None payload = {} event_actor = event.get("actor") if event_actor: payload["actor"] = event_actor event_outcome = event.get("outcome") if event_outcome: payload["outcome"] = event_outcome if not payload: logger.error("Empty event payload from Okta event") continue # event try: created_at = parser.parse(event["published"]) except (KeyError, TypeError, ValueError): logger.error("Could not parse datetime from Okta event") created_at = None event_metadata = EventMetadata(event_cls.event_type, request=EventRequest( client_user_agent, client_ip, geo=event_request_geo), observer=event_observer, created_at=created_at, tags=event_cls.tags) event = event_cls(event_metadata, payload) event.post()
def _deserialize_event(self, doc): doc.pop('stored_at') event_type = doc.pop('event_type') payload = doc.pop('payload') request_d = { k: v for k, v in ((a, doc.pop(a)) for a in ('user_agent', 'ip', 'user')) if v } if request_d: doc['request'] = EventRequest.deserialize(request_d) else: doc['request'] = None event_cls = event_cls_from_type(event_type) event = event_cls(EventMetadata(event_type, **doc), payload) return event
def post_monolith_cache_server_update_request(request, cache_server=None, errors=None): event_class = MonolithUpdateCacheServerRequestEvent event_request = EventRequest.build_from_request(request) metadata = EventMetadata(request=event_request) if cache_server: payload = cache_server.serialize() payload["status"] = 0 else: # flatten errors payload = { "errors": {attr: ", ".join(err) for attr, err in errors.items()} } payload["status"] = 1 event = event_class(metadata, payload) event.post()
def post_monolith_cache_server_update_request(user_agent, ip, cache_server=None, errors=None): event_class = MonolithUpdateCacheServerRequestEvent if user_agent or ip: request = EventRequest(user_agent, ip) else: request = None metadata = EventMetadata(event_class.event_type, request=request, tags=event_class.tags) if cache_server: payload = cache_server.serialize() payload["status"] = 0 else: # flatten errors payload = {"errors": {attr: ", ".join(err) for attr, err in errors.items()}} payload["status"] = 1 event = event_class(metadata, payload) event.post()
def post_munki_events(msn, user_agent, ip, data): for report in data: events = report.pop('events') event_uuid = uuid.uuid4() for event_index, (created_at, payload) in enumerate(events): # event type try: failed = int(payload["status"]) != 0 except (KeyError, ValueError): failed = True payload_type = payload.get("type") if payload_type == "install": if failed: event_cls = MunkiInstallFailedEvent else: event_cls = MunkiInstallEvent elif payload_type == "removal": if failed: event_cls = MunkiRemovalFailedEvent else: event_cls = MunkiRemovalEvent elif payload_type == "warning": event_cls = MunkiWarningEvent elif payload_type == "error": event_cls = MunkiErrorEvent elif payload_type == "start": event_cls = MunkiStartEvent else: logger.error("Unknown munki event payload type %s", payload_type) continue # build event metadata = EventMetadata( uuid=event_uuid, index=event_index, machine_serial_number=msn, request=EventRequest(user_agent, ip), created_at=parser.parse(created_at), incident_updates=payload.pop("incident_updates", []), ) payload.update(report) event = event_cls(metadata, payload) event.post()
def post(self, request, *args, **kwargs): serializer = CleanupInventorySerializer(data=request.data) if serializer.is_valid(): event_request = EventRequest.build_from_request(request) result = cleanup_inventory.apply_async(( serializer.data["days"], event_request.serialize(), )) return Response( { "task_id": result.id, "task_result_url": reverse("base_api:task_result", args=(result.id, )) }, status=status.HTTP_201_CREATED) else: return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
def update_incident_status(incident, new_status, request): incident = Incident.objects.select_for_update().get(pk=incident.pk) if new_status not in incident.get_next_statuses(): return incident, None previous_status = { "status": incident.status, "status_time": incident.status_time } incident.status = new_status.value incident.status_time = datetime.utcnow() incident.save() # build event event_payload = incident.serialize_for_event() event_payload["previous_status"] = previous_status event = IncidentStatusUpdatedEvent( EventMetadata(request=EventRequest.build_from_request(request)), event_payload) return incident, event
def update_machine_incident_status(machine_incident, new_status, request): machine_incident = (MachineIncident.objects.select_for_update(). select_related("incident").get(pk=machine_incident.pk)) if new_status not in machine_incident.get_next_statuses(): return machine_incident, None previous_status = { "status": machine_incident.status, "status_time": machine_incident.status_time } machine_incident.status = new_status.value machine_incident.status_time = datetime.utcnow() machine_incident.save() # build event event_payload = machine_incident.serialize_for_event() event_payload["machine_incident"]["previous_status"] = previous_status event = MachineIncidentStatusUpdatedEvent( EventMetadata(request=EventRequest.build_from_request(request)), event_payload) return machine_incident, event