Example #1
0
 def test_update_machine_statuses_status_default_time_update(self):
     cc1 = self._force_compliance_check()
     serial_number = get_random_string()
     first_status_time = datetime(2014, 10, 26)
     ms = MachineStatus.objects.create(compliance_check=cc1,
                                       compliance_check_version=cc1.version,
                                       serial_number=serial_number,
                                       status=Status.OK.value,
                                       status_time=first_status_time)
     update_machine_statuses(serial_number, [(cc1, Status.OK, None)])
     ms.refresh_from_db()
     self.assertTrue(ms.status_time > first_status_time)
Example #2
0
 def test_update_machine_statuses_update_two_no_changes(self):
     cc1 = self._force_compliance_check()
     cc2 = self._force_compliance_check()
     serial_number = get_random_string()
     update_machine_statuses(serial_number,
                             [(cc1, Status.OK, None),
                              (cc2, Status.FAILED, datetime.utcnow())])
     result = update_machine_statuses(serial_number,
                                      [(cc1, Status.OK, None),
                                       (cc2, Status.FAILED, None)])
     self.assertEqual(len(result), 2)
     self.assertEqual(result[0], (cc1.pk, Status.OK.value, Status.OK.value))
     self.assertEqual(result[1],
                      (cc2.pk, Status.FAILED.value, Status.FAILED.value))
     self.assertEqual(
         MachineStatus.objects.filter(serial_number=serial_number).count(),
         2)
Example #3
0
 def test_update_machine_statuses_create_one_then_another_one(self):
     cc1 = self._force_compliance_check()
     serial_number = get_random_string()
     result = update_machine_statuses(serial_number,
                                      [(cc1, Status.OK, datetime.utcnow())])
     self.assertEqual(len(result), 1)
     self.assertEqual(result[0], (cc1.pk, Status.OK.value, None))
     self.assertEqual(
         MachineStatus.objects.filter(serial_number=serial_number).count(),
         1)
     serial_number = get_random_string()
     result = update_machine_statuses(serial_number,
                                      [(cc1, Status.OK, datetime.utcnow())])
     self.assertEqual(len(result), 1)
     self.assertEqual(result[0], (cc1.pk, Status.OK.value, None))
     self.assertEqual(
         MachineStatus.objects.filter(serial_number=serial_number).count(),
         1)
Example #4
0
 def test_update_machine_statuses_version_update(self):
     cc1 = self._force_compliance_check()
     self.assertEqual(cc1.version, 1)
     serial_number = get_random_string()
     result = update_machine_statuses(serial_number,
                                      [(cc1, Status.OK, datetime.utcnow())])
     self.assertEqual(len(result), 1)
     self.assertEqual(result[0], (cc1.pk, Status.OK.value, None))
     ms_qs = MachineStatus.objects.filter(serial_number=serial_number)
     self.assertEqual(ms_qs.count(), 1)
     ms = ms_qs.first()
     self.assertEqual(ms.compliance_check_version, cc1.version)
     cc1.version = 2
     cc1.save()
     result = update_machine_statuses(serial_number,
                                      [(cc1, Status.OK, datetime.utcnow())])
     self.assertEqual(len(result), 1)
     self.assertEqual(result[0], (cc1.pk, Status.OK.value, Status.OK.value))
     ms.refresh_from_db()
     self.assertEqual(ms.compliance_check_version, cc1.version)
Example #5
0
 def process_tree(self, tree, last_seen):
     machine_tag_set = None
     compliance_check_statuses = []
     serial_number = tree["serial_number"]
     source_name = tree["source"]["name"]
     platform = tree.get("platform")
     if not platform:
         logger.warning("Cannot process %s %s tree: missing platform",
                        source_name, serial_number)
         return
     for check_tag_set, jmespath_parsed_expr, jmespath_check in self._get_source_platform_checks(
             source_name, platform):
         if check_tag_set:
             if machine_tag_set is None:
                 # TODO cache?
                 machine_tag_set = set(
                     MachineTag.objects.filter(
                         serial_number=serial_number).values_list(
                             "tag_id", flat=True))
             if not check_tag_set.intersection(machine_tag_set):
                 # tags mismatch
                 continue
         # default to unknown status
         status = Status.UNKNOWN
         try:
             result = jmespath_parsed_expr.search(tree)
         except Exception:
             logger.exception("Could not evaluate JMESPath check %s",
                              jmespath_check.pk)
         else:
             if result is True:
                 status = Status.OK
             elif result is False:
                 status = Status.FAILED
             else:
                 logger.warning("JMESPath check %s result is not a boolean",
                                jmespath_check.pk)
         compliance_check_statuses.append(
             (jmespath_check.compliance_check, status, last_seen))
     if not compliance_check_statuses:
         # nothing to update, no events
         return
     status_updates = update_machine_statuses(serial_number,
                                              compliance_check_statuses)
     for compliance_check_pk, status_value, previous_status_value in status_updates:
         if status_value == previous_status_value:
             # status not updated, no event
             continue
         yield JMESPathCheckStatusUpdated.build_from_object_serial_number_and_statuses(
             self._checks[compliance_check_pk], serial_number,
             Status(status_value),
             Status(previous_status_value)
             if previous_status_value is not None else None)
Example #6
0
 def test_update_machine_statuses_to_old_noop(self):
     cc1 = self._force_compliance_check()
     serial_number = get_random_string()
     status_time = datetime.utcnow()
     ms = MachineStatus.objects.create(compliance_check=cc1,
                                       compliance_check_version=cc1.version,
                                       serial_number=serial_number,
                                       status=Status.OK.value,
                                       status_time=status_time)
     result = update_machine_statuses(
         serial_number, [(cc1, Status.FAILED, datetime(1871, 3, 18))])
     # noop
     self.assertEqual(len(result), 0)
     ms_qs = MachineStatus.objects.filter(serial_number=serial_number)
     self.assertEqual(ms_qs.count(), 1)
     self.assertEqual(ms_qs.first(), ms)
     ms.refresh_from_db()
     self.assertEqual(ms.status, Status.OK.value)
     self.assertEqual(ms.status_time, status_time)
Example #7
0
 def commit(self):
     if not self.cc_statuses:
         return
     compliance_check_statuses = []
     checks = {}
     for query in (Query.objects.select_related(
             "compliance_check").prefetch_related("packquery__pack").filter(
                 pk__in=self.cc_statuses.keys(),
                 compliance_check__isnull=False)):
         query_version, status, status_time, distributed_query_pk = self.cc_statuses[
             query.pk]
         if query.version != query_version:
             # outdated status
             continue
         compliance_check_statuses.append(
             (query.compliance_check, status, status_time))
         checks[query.compliance_check.pk] = (query, status_time,
                                              distributed_query_pk)
     status_updates = update_machine_statuses(self.serial_number,
                                              compliance_check_statuses)
     event_cls = event_cls_from_type(
         "osquery_check_status_updated")  # import cycle with osquery.events
     for compliance_check_pk, status_value, previous_status_value in status_updates:
         if status_value == previous_status_value:
             # status not updated, no event
             continue
         query, status_time, distributed_query_pk = checks[
             compliance_check_pk]
         yield event_cls.build_from_query_serial_number_and_statuses(
             query,
             distributed_query_pk,
             self.serial_number,
             Status(status_value),
             status_time,
             Status(previous_status_value)
             if previous_status_value is not None else None,
         )