コード例 #1
0
ファイル: webhook.py プロジェクト: janheise/zentral
    def _update_machine(self, client, device_type, jamf_id):
        logger.info("Update machine %s %s %s", client.source_repr, device_type,
                    jamf_id)

        try:
            machine_d, tags = client.get_machine_d_and_tags(
                device_type, jamf_id)
        except Exception:
            logger.exception("Could not get machine_d and tags. %s %s %s",
                             client.source_repr, device_type, jamf_id)
            return

        serial_number = machine_d.get("serial_number")
        if not serial_number:
            logger.warning("Machine %s %s %s without serial number",
                           client.source_repr, device_type, jamf_id)
            return

        with transaction.atomic():
            yield from commit_machine_snapshot_and_yield_events(machine_d)
            if tags:
                machine = MetaMachine(serial_number)
                for taxonomy_id, tag_names in tags.items():
                    taxonomy = self._get_taxonomy(taxonomy_id)
                    if taxonomy:
                        machine.update_taxonomy_tags(taxonomy, tag_names)
コード例 #2
0
 def test_source(self):
     tree = copy.deepcopy(self.machine_snapshot3)
     msc, ms = MachineSnapshotCommit.objects.commit_machine_snapshot_tree(
         tree)
     tree = copy.deepcopy(self.machine_snapshot3)
     tree["serial_number"] = tree["serial_number"][::-1]
     msc2, ms2 = MachineSnapshotCommit.objects.commit_machine_snapshot_tree(
         tree)
     self.assertEqual(msc2.source, msc.source)
     self.assertEqual(ms2.source, ms.source)
     self.assertEqual([],
                      list(Source.objects.current_machine_group_sources()))
     self.assertEqual([ms.source],
                      list(Source.objects.current_business_unit_sources()))
     self.assertEqual(
         [ms.source],
         list(Source.objects.current_machine_snapshot_sources()))
     self.assertEqual([ms.source],
                      list(Source.objects.current_macos_apps_sources()))
     for sn in (self.serial_number, ms2.serial_number):
         mm = MetaMachine(sn)
         mm.archive()
     self.assertEqual(
         [], list(Source.objects.current_machine_snapshot_sources()))
     self.assertEqual([], list(Source.objects.current_macos_apps_sources()))
コード例 #3
0
 def test_machine_tag(self):
     tree = copy.deepcopy(self.machine_snapshot)
     msc, ms = MachineSnapshotCommit.objects.commit_machine_snapshot_tree(tree)
     tag = Tag.objects.create(name="tag name")
     self.assertEqual(str(tag), "tag name")
     MachineTag.objects.create(tag=tag, serial_number=self.serial_number)
     self.assertEqual(list(Tag.objects.used_in_inventory()), [(tag, 1)])
     mm = MetaMachine(self.serial_number)
     mm.archive()
     self.assertEqual(list(Tag.objects.used_in_inventory()), [])
コード例 #4
0
 def test_machine_tag(self):
     tree = copy.deepcopy(self.machine_snapshot)
     msc, ms = MachineSnapshotCommit.objects.commit_machine_snapshot_tree(
         tree)
     tag = Tag.objects.create(name="tag name")
     self.assertEqual(str(tag), "tag name")
     MachineTag.objects.create(tag=tag, serial_number=self.serial_number)
     self.assertEqual(list(Tag.objects.used_in_inventory()), [(tag, 1)])
     mm = MetaMachine(self.serial_number)
     mm.archive()
     self.assertEqual(list(Tag.objects.used_in_inventory()), [])
コード例 #5
0
 def test_meta_machine(self):
     tree = copy.deepcopy(self.machine_snapshot)
     msc, ms = MachineSnapshotCommit.objects.commit_machine_snapshot_tree(
         tree)
     tree = copy.deepcopy(self.machine_snapshot2)
     msc2, ms2 = MachineSnapshotCommit.objects.commit_machine_snapshot_tree(
         tree)
     tree = copy.deepcopy(self.machine_snapshot3)
     msc3, ms3 = MachineSnapshotCommit.objects.commit_machine_snapshot_tree(
         tree)
     mm = MetaMachine(self.serial_number)
     self.assertEqual(mm.serial_number, self.serial_number)
     self.assertEqual(mm.snapshots, [ms3])
     self.assertEqual(mm.platform, MACOS)
     tag1, _ = Tag.objects.get_or_create(name="tag111")
     tag2, _ = Tag.objects.get_or_create(name="tag222")
     MachineTag.objects.create(tag=tag1, serial_number=self.serial_number)
     self.assertEqual(
         (MACOS, None, {self.meta_business_unit.id}, {tag1.id}),
         mm.get_probe_filtering_values())
     MetaBusinessUnitTag.objects.create(
         tag=tag2, meta_business_unit=self.meta_business_unit)
     self.assertEqual(
         (MACOS, None, {self.meta_business_unit.id}, {tag1.id, tag2.id}),
         mm.get_probe_filtering_values())
     mm.archive()
     mm = MetaMachine(self.serial_number)
     self.assertEqual(mm.snapshots, [])
     self.assertEqual(MachineSnapshot.objects.count(), 3)
     self.assertEqual(MachineSnapshotCommit.objects.count(), 3)
     self.assertEqual(CurrentMachineSnapshot.objects.count(), 0)
コード例 #6
0
ファイル: views.py プロジェクト: janheise/zentral
    def do_post(self, data):
        post_munki_request_event(self.machine_serial_number,
                                 self.user_agent,
                                 self.ip,
                                 request_type="job_details",
                                 enrollment={"pk": self.enrollment.pk})

        # serialize configuration
        configuration = self.enrollment.configuration
        response_d = {
            "apps_full_info_shard":
            configuration.inventory_apps_full_info_shard
        }
        if configuration.principal_user_detection_sources:
            principal_user_detection = response_d.setdefault(
                "principal_user_detection", {})
            principal_user_detection[
                "sources"] = configuration.principal_user_detection_sources
            if configuration.principal_user_detection_domains:
                principal_user_detection[
                    "domains"] = configuration.principal_user_detection_domains
        if configuration.collected_condition_keys:
            response_d[
                "collected_condition_keys"] = configuration.collected_condition_keys

        # add tags
        # TODO better cache for the machine tags
        m = MetaMachine(self.machine_serial_number)
        response_d["incidents"] = [
            mi.incident.name for mi in m.open_incidents()
        ]
        response_d["tags"] = m.tag_names()

        # last seen sha1sum
        # last managed installs sync
        try:
            munki_state = MunkiState.objects.get(
                machine_serial_number=self.machine_serial_number)
        except MunkiState.DoesNotExist:
            pass
        else:
            response_d['last_seen_sha1sum'] = munki_state.sha1sum
            response_d['managed_installs'] = (
                munki_state.last_managed_installs_sync is None or
                (datetime.utcnow() - munki_state.last_managed_installs_sync >
                 timedelta(
                     days=configuration.managed_installs_sync_interval_days)))
        return response_d
コード例 #7
0
    def dispatch(self, request, *args, **kwargs):
        try:
            token = request.META['HTTP_X_MONOLITH_TOKEN'].strip()
            api_data = verify_secret(token, 'zentral.contrib.monolith')
        except (KeyError, ValueError, APIAuthError):
            return HttpResponseForbidden("No no no!")

        # machine serial number
        h_msn = request.META.get("HTTP_X_ZENTRAL_SERIAL_NUMBER")  # new way
        t_msn = api_data.get("machine_serial_number")  # old way
        if h_msn and t_msn and h_msn != t_msn:
            logger.warning("Serial number mismatch. header: %s, token: %s",
                           h_msn, t_msn)
        self.machine_serial_number = h_msn or t_msn  # priority to h_msn because set in preflight script

        # business unit, manifest
        self.meta_business_unit = api_data['business_unit'].meta_business_unit
        self.manifest = get_object_or_404(
            Manifest, meta_business_unit=self.meta_business_unit)

        self.user_agent, self.ip = user_agent_and_ip_address_from_request(
            request)

        # machine extra infos
        self.machine = MetaMachine(self.machine_serial_number)
        self.tags = self.machine.tags

        if not self.machine_serial_number:
            logger.warning("Missing serial number. mbu: %s %s",
                           self.meta_business_unit, self.meta_business_unit.pk)

        return super().dispatch(request, *args, **kwargs)
コード例 #8
0
ファイル: views.py プロジェクト: dekoder/zentral
 def commit_machine_snapshot(self, max_age=3600):
     module = 'zentral.contrib.jamf_protect'
     if MetaMachine(self.serial_number).has_recent_source_snapshot(
             module, max_age):
         logger.debug(
             "Skip Jamf Protect machine snapshot commit for machine %s.",
             self.serial_number)
         return
     tree = {
         'source': {
             'module': module,
             'name': 'Jamf Protect'
         },
         'reference': self.serial_number,
         'serial_number': self.serial_number,
         'public_ip_address': self.ip
     }
     hostname = self.event.get("host", {}).get("hostname")
     if hostname:
         tree['system_info'] = {'computer_name': hostname}
     business_unit = self.enrolled_machine.enrollment.secret.get_api_enrollment_business_unit(
     )
     if business_unit:
         tree['business_unit'] = business_unit.serialize()
     commit_machine_snapshot_and_trigger_events(tree)
コード例 #9
0
 def get_context_data(self, **kwargs):
     ctx = super().get_context_data(**kwargs)
     ctx["mdm"] = True
     ctx["machine"] = machine = MetaMachine.from_urlsafe_serial_number(kwargs["urlsafe_serial_number"])
     ctx["serial_number"] = machine.serial_number
     # enrolled devices
     ctx["enrolled_devices"] = (EnrolledDevice.objects.filter(serial_number=machine.serial_number)
                                                      .order_by("-updated_at"))
     ctx["enrolled_devices_count"] = ctx["enrolled_devices"].count()
     # dep device?
     try:
         ctx["dep_device"] = DEPDevice.objects.get(serial_number=machine.serial_number)
     except DEPDevice.DoesNotExist:
         pass
     # dep enrollment sessions
     ctx["dep_enrollment_sessions"] = DEPEnrollmentSession.objects.filter(
         enrollment_secret__serial_numbers__contains=[machine.serial_number]
     ).order_by("-updated_at")
     ctx["dep_enrollment_sessions_count"] = ctx["dep_enrollment_sessions"].count()
     # ota enrollment sessions
     ctx["ota_enrollment_sessions"] = OTAEnrollmentSession.objects.filter(
         enrollment_secret__serial_numbers__contains=[machine.serial_number]
     ).order_by("-updated_at")
     ctx["ota_enrollment_sessions_count"] = ctx["ota_enrollment_sessions"].count()
     return ctx
コード例 #10
0
 def test_update_open_machine_incident(self):
     event_metadata = EventMetadata(event_type="test", machine_serial_number="YOLOFOMO")
     event_metadata.machine = MockMetaMachine([self.mbu1], [self.tag1],
                                              "WINDOWS", "LAPTOP",
                                              serial_number="YOLOFOMO")
     event = BaseEvent(event_metadata, {"joe": "jackson"})
     self.assertTrue(self.probe.test_event(event))
     machine_incident1, _ = update_or_create_open_machine_incident(
         self.probe_source,
         self.probe.get_matching_event_incident_severity(event),
         event.metadata.machine_serial_number,
         event.metadata.uuid
     )
     machine_incident2, event_payloads = update_or_create_open_machine_incident(
         self.probe_source,
         self.probe.get_matching_event_incident_severity(event) + 100,
         event.metadata.machine_serial_number,
         event.metadata.uuid
     )
     self.assertEqual(machine_incident1, machine_incident2)
     self.assertEqual(machine_incident2.incident, machine_incident1.incident)
     self.assertEqual(machine_incident2.incident.severity, SEVERITY_CRITICAL + 100)
     self.assertEqual(len(event_payloads), 1)
     event_payload = event_payloads[0]
     self.assertEqual(event_payload["action"], "updated")
     self.assertEqual(event_payload["diff"],
                      {"removed": {"severity": SEVERITY_CRITICAL},
                       "added": {"severity": SEVERITY_CRITICAL + 100}})
     self.assertEqual(event_payload["severity"], SEVERITY_CRITICAL + 100)
     self.assertEqual(event_payload.get("incident"), None)
     # meta machine
     self.assertEqual(MetaMachine("YOLOFOMO").max_incident_severity(), SEVERITY_CRITICAL + 100)
コード例 #11
0
 def setUpTestData(cls):
     # user
     cls.user = User.objects.create_user("godzilla", "*****@*****.**",
                                         get_random_string())
     cls.group = Group.objects.create(name=get_random_string())
     cls.user.groups.set([cls.group])
     # machine
     cls.serial_number = "0123456789"
     cls.source_name = get_random_string() + "z"
     MachineSnapshotCommit.objects.commit_machine_snapshot_tree({
         "source": {
             "module": "tests.zentral.io",
             "name": cls.source_name.upper()
         },
         "serial_number":
         cls.serial_number,
         "os_version": {
             'name': 'OS X',
             'major': 10,
             'minor': 11,
             'patch': 1
         },
         "osx_app_instances": [{
             'app': {
                 'bundle_id': 'io.zentral.baller',
                 'bundle_name': 'Baller.app',
                 'bundle_version': '123',
                 'bundle_version_str': '1.2.3'
             },
             'bundle_path': "/Applications/Baller.app"
         }]
     })
     cls.source = Source.objects.get(name=cls.source_name.upper())
     cls.machine = MetaMachine(cls.serial_number)
     cls.url_msn = cls.machine.get_urlsafe_serial_number()
コード例 #12
0
 def setUpTestData(cls):
     # user
     cls.user = User.objects.create_user("godzilla", "*****@*****.**", get_random_string())
     cls.group = Group.objects.create(name=get_random_string())
     cls.user.groups.set([cls.group])
     # probe
     cls.probe_source = ProbeSource.objects.create(
         model="BaseProbe",
         name=get_random_string(),
         status=ProbeSource.ACTIVE,
         body={"filters": {"metadata": [{"event_types": ["inventory_heartbeat"]}]}}
     )
     # machine
     cls.serial_number = "0123456789"
     MachineSnapshotCommit.objects.commit_machine_snapshot_tree({
         "source": {"module": "tests.zentral.io", "name": "Zentral Tests"},
         "serial_number": cls.serial_number,
         "os_version": {'name': 'OS X', 'major': 10, 'minor': 11, 'patch': 1},
         "osx_app_instances": [
             {'app': {'bundle_id': 'io.zentral.baller',
                      'bundle_name': 'Baller.app',
                      'bundle_version': '123',
                      'bundle_version_str': '1.2.3'},
              'bundle_path': "/Applications/Baller.app"}
         ]
     })
     cls.machine = MetaMachine(cls.serial_number)
     cls.url_msn = cls.machine.get_urlsafe_serial_number()
コード例 #13
0
 def test_source(self):
     tree = copy.deepcopy(self.machine_snapshot3)
     msc, ms = MachineSnapshotCommit.objects.commit_machine_snapshot_tree(tree)
     tree = copy.deepcopy(self.machine_snapshot3)
     tree["serial_number"] = tree["serial_number"][::-1]
     msc2, ms2 = MachineSnapshotCommit.objects.commit_machine_snapshot_tree(tree)
     self.assertEqual(msc2.source, msc.source)
     self.assertEqual(ms2.source, ms.source)
     self.assertEqual([], list(Source.objects.current_machine_group_sources()))
     self.assertEqual([], list(Source.objects.current_business_unit_sources()))
     self.assertEqual([ms.source], list(Source.objects.current_machine_snapshot_sources()))
     self.assertEqual([ms.source], list(Source.objects.current_macos_apps_sources()))
     for sn in (self.serial_number, ms2.serial_number):
         mm = MetaMachine(sn)
         mm.archive()
     self.assertEqual([], list(Source.objects.current_machine_snapshot_sources()))
     self.assertEqual([], list(Source.objects.current_macos_apps_sources()))
コード例 #14
0
 def test_meta_machine(self):
     tree = copy.deepcopy(self.machine_snapshot)
     msc, ms = MachineSnapshotCommit.objects.commit_machine_snapshot_tree(tree)
     tree = copy.deepcopy(self.machine_snapshot2)
     msc2, ms2 = MachineSnapshotCommit.objects.commit_machine_snapshot_tree(tree)
     tree = copy.deepcopy(self.machine_snapshot3)
     msc3, ms3 = MachineSnapshotCommit.objects.commit_machine_snapshot_tree(tree)
     mm = MetaMachine(self.serial_number)
     self.assertEqual(mm.serial_number, self.serial_number)
     self.assertEqual(mm.snapshots, [ms3])
     self.assertEqual(mm.platform, MACOS)
     mm.archive()
     mm = MetaMachine(self.serial_number)
     self.assertEqual(mm.snapshots, [])
     self.assertEqual(MachineSnapshot.objects.count(), 3)
     self.assertEqual(MachineSnapshotCommit.objects.count(), 3)
     self.assertEqual(CurrentMachineSnapshot.objects.count(), 0)
コード例 #15
0
 def post(self, request, *args, **kwargs):
     enrolled_device = get_object_or_404(EnrolledDevice, pk=kwargs["pk"])
     send_device_notification(enrolled_device)
     messages.info(request, "Device poked!")
     return HttpResponseRedirect(
         reverse("mdm:device",
                 args=(MetaMachine(enrolled_device.serial_number).get_urlsafe_serial_number(),))
     )
コード例 #16
0
 def get_context_data(self, **kwargs):
     context = super().get_context_data(**kwargs)
     context["mdm"] = True
     context["urlsafe_serial_number"] = MetaMachine(self.object.serial_number).get_urlsafe_serial_number()
     context["installed_device_artifacts"] = sorted(self.object.installeddeviceartifact_set.all(),
                                                    key=lambda ida: ida.created_at, reverse=True)
     context["device_artifact_commands"] = sorted(self.object.deviceartifactcommand_set.all(),
                                                  key=lambda dac: dac.id, reverse=True)
     return context
コード例 #17
0
 def do_node_post(self, data):
     queries = {}
     if self.machine_serial_number:
         machine = MetaMachine(self.machine_serial_number)
         queries = DistributedQueryProbeMachine.objects.new_queries_for_machine(
             machine)
         inventory_query = get_distributed_inventory_query(machine, self.ms)
         if inventory_query:
             queries[DEFAULT_ZENTRAL_INVENTORY_QUERY_NAME] = inventory_query
     return {'queries': queries}
コード例 #18
0
 def fetch_devices(self):
     query, args = self.build_query()
     with connection.cursor() as cursor:
         cursor.execute(query, args)
         attributes = [col.name for col in cursor.description]
         for row in cursor.fetchall():
             device = dict(zip(attributes, row))
             device["udids"] = sorted(udid for udid in device["udids"] if udid)
             device["urlsafe_serial_number"] = MetaMachine(device["serial_number"]).get_urlsafe_serial_number()
             yield device
コード例 #19
0
 def test_machine_snapshot_current(self):
     tree = copy.deepcopy(self.machine_snapshot)
     msc, ms = MachineSnapshotCommit.objects.commit_machine_snapshot_tree(tree)
     tree = copy.deepcopy(self.machine_snapshot2)
     msc2, ms2 = MachineSnapshotCommit.objects.commit_machine_snapshot_tree(tree)
     tree = copy.deepcopy(self.machine_snapshot3)
     msc3, ms3 = MachineSnapshotCommit.objects.commit_machine_snapshot_tree(tree)
     self.assertEqual(MachineSnapshot.objects.count(), 3)
     self.assertEqual(MachineSnapshot.objects.current().count(), 1)
     self.assertEqual(MachineSnapshot.objects.current().get(pk=ms3.id), ms3)
     mm = MetaMachine(self.serial_number)
     mm.archive()
     self.assertEqual(CurrentMachineSnapshot.objects.count(), 0)
     tree = copy.deepcopy(self.machine_snapshot3)
     msc4, ms4 = MachineSnapshotCommit.objects.commit_machine_snapshot_tree(tree)
     self.assertEqual(ms3, ms4)
     self.assertEqual(CurrentMachineSnapshot.objects.count(), 1)
     cms = CurrentMachineSnapshot.objects.get(serial_number=self.serial_number)
     self.assertEqual(cms.machine_snapshot, ms3)
コード例 #20
0
 def authenticate(self):
     try:
         self.enrolled_machine = EnrolledMachine.objects.select_related(
             "enrollment__configuration",
             "enrollment__secret__meta_business_unit"
         ).get(node_key=self.get_node_key())
     except EnrolledMachine.DoesNotExist:
         raise PermissionDenied("Wrong node_key")
     self.machine = MetaMachine(self.enrolled_machine.serial_number)
     self.enrollment = self.enrolled_machine.enrollment
コード例 #21
0
 def test_meta_machine_update_taxonomy_tags(self):
     # one machine
     serial_number = get_random_string(13)
     # two tags from taxonomy1
     taxonomy1 = Taxonomy.objects.create(name=get_random_string(34))
     tag11 = Tag.objects.create(taxonomy=taxonomy1,
                                name=get_random_string(17))
     MachineTag.objects.get_or_create(serial_number=serial_number,
                                      tag=tag11)
     tag12 = Tag.objects.create(taxonomy=taxonomy1,
                                name=get_random_string(18))
     MachineTag.objects.get_or_create(serial_number=serial_number,
                                      tag=tag12)
     # one tag from taxonomy2
     taxonomy2 = Taxonomy.objects.create(name=get_random_string(27))
     tag21 = Tag.objects.create(taxonomy=taxonomy2,
                                name=get_random_string(20))
     MachineTag.objects.get_or_create(serial_number=serial_number,
                                      tag=tag21)
     # one detached tag
     tag31 = Tag.objects.create(name=get_random_string(21))
     MachineTag.objects.get_or_create(serial_number=serial_number,
                                      tag=tag31)
     # update the taxonomy1  tags. keep one, add two new ones, one collision, remove one.
     new_tag_names = [get_random_string(22), get_random_string(33)]
     updated_tag_names = [
         tag11.name,  # existing,
         # tag12.name  # removed
         tag31.
         name,  # collision, because we will try to add a tag with the same name, but within the taxonomy1
     ] + new_tag_names  # new ones
     mm = MetaMachine(serial_number)
     mm.update_taxonomy_tags(taxonomy1, updated_tag_names)
     # verify
     # two new tags
     new_tags = list(Tag.objects.filter(name__in=new_tag_names))
     self.assertEqual(len(new_tags), 2)
     # in the taxonomy1
     self.assertTrue(all(t.taxonomy == taxonomy1 for t in new_tags))
     # expected tags for the machine
     expected_tags = [("machine", t)
                      for t in [tag11, tag21, tag31] + new_tags]
     self.assertEqual(set(expected_tags), set(mm.tags_with_types))
コード例 #22
0
 def do_node_post(self, data):
     queries = {}
     if self.machine_serial_number:
         machine = MetaMachine(self.machine_serial_number)
         queries = DistributedQueryProbeMachine.objects.new_queries_for_machine(machine)
         for query_name, query in get_distributed_inventory_queries(machine, self.ms):
             if query_name in queries:
                 logger.error("Conflict on the distributed query name %s", query_name)
             else:
                 queries[query_name] = query
     return {'queries': queries}
コード例 #23
0
ファイル: base.py プロジェクト: devopsotrator/zentral
 def __init__(self, event_type, **kwargs):
     self.event_type = event_type
     self.uuid = kwargs.pop('uuid', uuid.uuid4())
     if isinstance(self.uuid, str):
         self.uuid = uuid.UUID(self.uuid)
     self.index = int(kwargs.pop('index', 0))
     self.created_at = kwargs.pop('created_at', None)
     if self.created_at is None:
         self.created_at = datetime.utcnow()
     elif isinstance(self.created_at, str):
         self.created_at = parser.parse(self.created_at)
     self.machine_serial_number = kwargs.pop('machine_serial_number', None)
     if self.machine_serial_number:
         self.machine = MetaMachine(self.machine_serial_number)
     else:
         self.machine = None
     self.observer = kwargs.pop('observer', None)
     self.request = kwargs.pop('request', None)
     self.tags = kwargs.pop('tags', [])
     self.incidents = kwargs.pop('incidents', [])
コード例 #24
0
 def post(self, request, *args, **kwargs):
     dep_device = get_object_or_404(DEPDevice, pk=kwargs["pk"])
     try:
         refresh_dep_device(dep_device)
     except DEPClientError as error:
         messages.error(request, str(error))
     else:
         messages.info(request, "DEP device refreshed")
     return HttpResponseRedirect("{}#dep_device".format(
         reverse("mdm:device",
                 args=(MetaMachine(dep_device.serial_number).get_urlsafe_serial_number(),))
     ))
コード例 #25
0
ファイル: webhook.py プロジェクト: githubassets/zentral
 def _update_machine(self, client, device_type, jamf_id):
     logger.info("Update machine %s %s %s", client.source_repr, device_type,
                 jamf_id)
     try:
         machine_d, tags = client.get_machine_d_and_tags(
             device_type, jamf_id)
     except Exception:
         logger.exception("Could not get machine_d and tags. %s %s %s",
                          client.source_repr, device_type, jamf_id)
     else:
         if not machine_d.get("serial_number"):
             logger.warning("Machine %s %s %s without serial number",
                            client.source_repr, device_type, jamf_id)
             return
         try:
             with transaction.atomic():
                 msc, ms = MachineSnapshotCommit.objects.commit_machine_snapshot_tree(
                     machine_d)
         except Exception:
             logger.exception("Could not commit machine snapshot")
         else:
             if msc:
                 for idx, (event_type, created_at, payload) in enumerate(
                         inventory_events_from_machine_snapshot_commit(
                             msc)):
                     event_cls = event_cls_from_type(event_type)
                     metadata = EventMetadata(
                         event_cls.event_type,
                         machine_serial_number=ms.serial_number,
                         index=idx,
                         created_at=created_at,
                         tags=event_cls.tags)
                     event = event_cls(metadata, payload)
                     yield event
         if tags:
             machine = MetaMachine(machine_d["serial_number"])
             for taxonomy_id, tag_names in tags.items():
                 taxonomy = self._get_taxonomy(taxonomy_id)
                 if taxonomy:
                     machine.update_taxonomy_tags(taxonomy, tag_names)
コード例 #26
0
ファイル: __init__.py プロジェクト: arubdesu/zentral
 def __init__(self, event_type, **kwargs):
     self.event_type = event_type
     self.uuid = kwargs.pop('uuid', uuid.uuid4())
     if isinstance(self.uuid, str):
         self.uuid = uuid.UUID(self.uuid)
     self.index = int(kwargs.pop('index', 0))
     self.created_at = kwargs.pop('created_at', datetime.utcnow())
     if isinstance(self.created_at, str):
         self.created_at = parser.parse(self.created_at)
     self.machine_serial_number = kwargs.pop('machine_serial_number')
     self.machine = MetaMachine(self.machine_serial_number)
     self.request = kwargs.pop('request', None)
     self.tags = kwargs.pop('tags', [])
コード例 #27
0
ファイル: views.py プロジェクト: zbuc/zentral
 def dispatch(self, request, *args, **kwargs):
     try:
         token = request.META['HTTP_X_MONOLITH_TOKEN'].strip()
         api_data = verify_secret(token, 'zentral.contrib.monolith')
     except (KeyError, ValueError, APIAuthError):
         return HttpResponseForbidden("No no no!")
     self.machine_serial_number = api_data.get("machine_serial_number", None)
     self.user_agent, self.ip = user_agent_and_ip_address_from_request(request)
     self.machine = MetaMachine(self.machine_serial_number)
     self.tags = self.machine.tags
     self.meta_business_unit = api_data['business_unit'].meta_business_unit
     self.manifest = get_object_or_404(Manifest, meta_business_unit=self.meta_business_unit)
     return super().dispatch(request, *args, **kwargs)
コード例 #28
0
 def test_machine_snapshot_current(self):
     tree = copy.deepcopy(self.machine_snapshot)
     msc, ms = MachineSnapshotCommit.objects.commit_machine_snapshot_tree(
         tree)
     tree = copy.deepcopy(self.machine_snapshot2)
     msc2, ms2 = MachineSnapshotCommit.objects.commit_machine_snapshot_tree(
         tree)
     tree = copy.deepcopy(self.machine_snapshot3)
     msc3, ms3 = MachineSnapshotCommit.objects.commit_machine_snapshot_tree(
         tree)
     self.assertEqual(MachineSnapshot.objects.count(), 3)
     self.assertEqual(MachineSnapshot.objects.current().count(), 1)
     self.assertEqual(MachineSnapshot.objects.current().get(pk=ms3.id), ms3)
     mm = MetaMachine(self.serial_number)
     mm.archive()
     self.assertEqual(CurrentMachineSnapshot.objects.count(), 0)
     tree = copy.deepcopy(self.machine_snapshot3)
     msc4, ms4 = MachineSnapshotCommit.objects.commit_machine_snapshot_tree(
         tree)
     self.assertEqual(ms3, ms4)
     self.assertEqual(CurrentMachineSnapshot.objects.count(), 1)
     cms = CurrentMachineSnapshot.objects.get(
         serial_number=self.serial_number)
     self.assertEqual(cms.machine_snapshot, ms3)
コード例 #29
0
 def test_close_open_machine_incident(self):
     event_metadata = EventMetadata(event_type="test", machine_serial_number="YOLOFOMO")
     event_metadata.machine = MockMetaMachine([self.mbu1], [self.tag1],
                                              "WINDOWS", "LAPTOP",
                                              serial_number="YOLOFOMO")
     event = BaseEvent(event_metadata, {"joe": "jackson"})
     self.assertTrue(self.probe.test_event(event))
     machine_incident1, _ = update_or_create_open_machine_incident(
         self.probe_source,
         self.probe.get_matching_event_incident_severity(event),
         event.metadata.machine_serial_number,
         event.metadata.uuid
     )
     self.assertEqual(machine_incident1.status, STATUS_OPEN)
     self.assertEqual(machine_incident1.incident.status, STATUS_OPEN)
     machine_incident2, event_payloads = update_or_create_open_machine_incident(
         self.probe_source,
         0,  # severity == 0 => close
         event.metadata.machine_serial_number,
         event.metadata.uuid
     )
     self.assertEqual(machine_incident1, machine_incident2)
     self.assertEqual(machine_incident2.incident, machine_incident1.incident)
     self.assertEqual(machine_incident2.status, STATUS_CLOSED)
     incident = machine_incident2.incident
     self.assertEqual(incident.severity, SEVERITY_CRITICAL)
     self.assertEqual(incident.status, STATUS_CLOSED)
     self.assertEqual(len(event_payloads), 2)
     event_payload1, event_payload2 = event_payloads
     # machine incident event payload
     self.assertEqual(event_payload1["action"], "closed")
     self.assertEqual(event_payload1["incident"]["pk"], incident.pk)
     self.assertEqual(event_payload1["incident"]["status"], STATUS_OPEN)  # Incident still open
     self.assertEqual(event_payload1["pk"], machine_incident2.pk)
     self.assertEqual(event_payload1["status"], machine_incident2.status)
     self.assertEqual(event_payload1["event_id"], str(event.metadata.uuid))
     self.assertEqual(event_payload1["diff"], {"removed": {"status": STATUS_OPEN},
                                               "added": {"status": STATUS_CLOSED}})
     # incident event payload
     self.assertEqual(event_payload2["action"], "closed")
     self.assertEqual(event_payload2["pk"], incident.pk)
     self.assertEqual(event_payload2["status"], STATUS_CLOSED)  # Incident closed now
     self.assertEqual(event_payload2.get("incident"), None)
     self.assertEqual(event_payload2["diff"],
                      {"removed": {"status": STATUS_OPEN},
                       "added": {"status": STATUS_CLOSED}})
     # meta machine
     self.assertEqual(MetaMachine("YOLOFOMO").max_incident_severity(), None)
コード例 #30
0
ファイル: test_incidents.py プロジェクト: BNOTIONS/zentral
 def test_create_open_machine_incident(self):
     event_metadata = EventMetadata(event_type="test",
                                    machine_serial_number="YOLOFOMO")
     event_metadata.machine = MockMetaMachine([self.mbu1], [self.tag1],
                                              "WINDOWS",
                                              "LAPTOP",
                                              serial_number="YOLOFOMO")
     event = BaseEvent(event_metadata, {"joe": "jackson"})
     self.assertTrue(self.probe.test_event(event))
     machine_incident, event_payloads = update_or_create_open_machine_incident(
         self.probe_source,
         self.probe.get_matching_event_incident_severity(event),
         event.metadata.machine_serial_number, event.metadata.uuid)
     # machine incident
     self.assertEqual([machine_incident],
                      list(MachineIncident.objects.all()))
     self.assertEqual(machine_incident.status, STATUS_OPEN)
     self.assertEqual(machine_incident.event_id, event.metadata.uuid)
     # incident
     incident = machine_incident.incident
     self.assertEqual([incident], list(Incident.objects.all()))
     self.assertEqual(incident.probe_source, self.probe_source)
     self.assertEqual(incident.name, "base probe")
     self.assertEqual(incident.status, STATUS_OPEN)
     self.assertEqual(incident.severity, SEVERITY_CRITICAL)
     self.assertEqual(incident.event_id, event.metadata.uuid)
     # event payloads
     self.assertEqual(len(event_payloads), 2)
     event_payload1, event_payload2 = event_payloads
     # incident event payload
     self.assertEqual(event_payload1["action"], "created")
     self.assertEqual(event_payload1["pk"], incident.pk)
     self.assertEqual(event_payload1.get("machine_incident"), None)
     # machine incident event payload
     self.assertEqual(event_payload2["action"], "created")
     self.assertEqual(
         event_payload2["machine_incident"], {
             "pk": machine_incident.pk,
             "status": machine_incident.status,
             "event_id": str(event.metadata.uuid)
         })
     # meta machine
     self.assertEqual(
         MetaMachine("YOLOFOMO").max_incident_severity(), SEVERITY_CRITICAL)
コード例 #31
0
 def authenticate(self):
     try:
         session_id = self.data["session_id"]
     except KeyError:
         raise SuspiciousOperation("Missing session_id")
     try:
         self.session = FileCarvingSession.objects.select_for_update().get(pk=session_id)
     except FileCarvingSession.DoesNotExist:
         raise PermissionDenied("Unknown session_id")
     # TODO: better. "There can be only one"
     try:
         self.enrolled_machine = (
             EnrolledMachine.objects.select_related("enrollment__configuration")
                                    .filter(serial_number=self.session.serial_number)
                                    .order_by("-pk")[0]
         )
     except IndexError:
         raise PermissionDenied("Unknown machine")
     self.machine = MetaMachine(self.session.serial_number)
     self.enrollment = self.enrolled_machine.enrollment
コード例 #32
0
def update_osquery_enrolled_machine_platform_mask(apps, schema_editor):
    try:
        from zentral.contrib.inventory.models import MetaMachine
        from zentral.contrib.inventory.conf import LINUX, MACOS, WINDOWS
    except ImportError:
        pass
    EnrolledMachine = apps.get_model("osquery", "EnrolledMachine")
    for enrolled_machine in EnrolledMachine.objects.all():
        mm = MetaMachine(enrolled_machine.serial_number)
        if mm.platform:
            if mm.platform == LINUX:
                enrolled_machine.platform_mask = 0x01 | 0x08
            elif mm.platform == MACOS:
                enrolled_machine.platform_mask = 0x01 | 0x04 | 0x10
            elif mm.platform == WINDOWS:
                enrolled_machine.platform_mask = 0x02
            else:
                print("Unsupported osquery enrolled machine platform",
                      mm.platform)
                continue
            enrolled_machine.save()
コード例 #33
0
ファイル: api.py プロジェクト: janheise/zentral
    def post(self, request, *args, **kwargs):
        # URL kwargs
        self.enrollment_secret_secret = kwargs["enrollment_secret"]
        try:
            self.hardware_uuid = str(UUID(kwargs["machine_id"]))
        except ValueError:
            raise PermissionDenied("Invalid machine id")

        self.client_cert_dn = self._get_client_cert_dn()

        self.user_agent, self.ip = user_agent_and_ip_address_from_request(
            request)

        self.request_data = self._get_json_data(request)

        self.cache_key = f"tests/santa/fixtures/{self.enrollment_secret_secret}{self.hardware_uuid}"
        self.enrolled_machine = None
        self.tag_ids = []
        if self.use_enrolled_machine_cache:
            try:
                self.enrolled_machine, self.tag_ids = cache.get(self.cache_key)
            except TypeError:
                pass
            else:
                if self.enrolled_machine.enrollment.configuration.client_certificate_auth and not self.client_cert_dn:
                    raise PermissionDenied("Missing client certificate")
        if not self.enrolled_machine:
            self.enrolled_machine = self.get_enrolled_machine()
            if not self.enrolled_machine:
                raise PermissionDenied("Machine not enrolled")
            meta_machine = MetaMachine(self.enrolled_machine.serial_number)
            self.tag_ids = [t.id for t in meta_machine.tags]
            cache.set(self.cache_key, (self.enrolled_machine, self.tag_ids),
                      600)  # TODO cache timeout hardcoded

        return JsonResponse(self.do_post())
コード例 #34
0
ファイル: test_machine_snapshot.py プロジェクト: zbuc/zentral
 def test_meta_machine(self):
     tree = copy.deepcopy(self.machine_snapshot)
     msc, ms = MachineSnapshotCommit.objects.commit_machine_snapshot_tree(
         tree)
     tree = copy.deepcopy(self.machine_snapshot2)
     msc2, ms2 = MachineSnapshotCommit.objects.commit_machine_snapshot_tree(
         tree)
     tree = copy.deepcopy(self.machine_snapshot3)
     msc3, ms3 = MachineSnapshotCommit.objects.commit_machine_snapshot_tree(
         tree)
     mm = MetaMachine(self.serial_number)
     self.assertEqual(mm.serial_number, self.serial_number)
     self.assertEqual(mm.snapshots, [ms3])
     self.assertEqual(mm.platform, MACOS)
     mm.archive()
     mm = MetaMachine(self.serial_number)
     self.assertEqual(mm.snapshots, [])
     self.assertEqual(MachineSnapshot.objects.count(), 3)
     self.assertEqual(MachineSnapshotCommit.objects.count(), 3)
     self.assertEqual(CurrentMachineSnapshot.objects.count(), 0)
コード例 #35
0
 def do_node_post(self, data):
     # TODO: The machine serial number is included in the string used to authenticate the requests
     # This is done in the osx pkg builder. The machine serial number should always be present here.
     # Maybe we could code a fallback to the available mbu probes if the serial number is not present.
     return build_osquery_conf(MetaMachine(self.machine_serial_number))
コード例 #36
0
ファイル: __init__.py プロジェクト: arubdesu/zentral
class EventMetadata(object):
    def __init__(self, event_type, **kwargs):
        self.event_type = event_type
        self.uuid = kwargs.pop('uuid', uuid.uuid4())
        if isinstance(self.uuid, str):
            self.uuid = uuid.UUID(self.uuid)
        self.index = int(kwargs.pop('index', 0))
        self.created_at = kwargs.pop('created_at', datetime.utcnow())
        if isinstance(self.created_at, str):
            self.created_at = parser.parse(self.created_at)
        self.machine_serial_number = kwargs.pop('machine_serial_number')
        self.machine = MetaMachine(self.machine_serial_number)
        self.request = kwargs.pop('request', None)
        self.tags = kwargs.pop('tags', [])

    @classmethod
    def deserialize(cls, event_d_metadata):
        kwargs = event_d_metadata.copy()
        kwargs['event_type'] = kwargs.pop('type')
        kwargs['uuid'] = kwargs.pop('id')
        request_d = kwargs.pop('request', None)
        if request_d:
            kwargs['request'] = EventRequest(**request_d)
        return cls(**kwargs)

    def serialize(self, machine_metadata=True):
        d = {'created_at': self.created_at.isoformat(),
             'id': str(self.uuid),
             'index': self.index,
             'type': self.event_type,
             'machine_serial_number': self.machine_serial_number,
             }
        if self.request:
            d['request'] = self.request.serialize()
        if self.tags:
            d['tags'] = self.tags
        if not machine_metadata:
            return d
        machine_d = {}
        for ms in self.machine.get_snapshots():
            source = ms.source
            ms_d = {'name': ms.get_machine_str()}
            if ms.business_unit:
                if not ms.business_unit.is_api_enrollment_business_unit():
                    ms_d['business_unit'] = {'reference': ms.business_unit.reference,
                                             'key': ms.business_unit.get_short_key(),
                                             'name': ms.business_unit.name}
            if ms.os_version:
                ms_d['os_version'] = str(ms.os_version)
            for group in ms.groups.all():
                ms_d.setdefault('groups', []).append({'reference': group.reference,
                                                      'key': group.get_short_key(),
                                                      'name': group.name})
            key = slugify(source.name)
            if key in ms_d:
                # TODO: earlier warning in conf check ?
                logger.warning('Inventory source slug %s exists already', key)
            machine_d[key] = ms_d
        for tag in self.machine.tags():
            machine_d.setdefault('tags', []).append({'id': tag.id,
                                                     'name': tag.name})
        for meta_business_unit in self.machine.meta_business_units():
            machine_d.setdefault('meta_business_units', []).append({
                'name': meta_business_unit.name,
                'id': meta_business_unit.id
            })
        if machine_d:
            d['machine'] = machine_d
        return d