Beispiel #1
0
 def get_enrolled_machine_token(self, request):
     authorization_header = request.META.get("HTTP_AUTHORIZATION")
     if not authorization_header:
         raise APIAuthError("Missing or empty Authorization header")
     if "MunkiEnrolledMachine" not in authorization_header:
         raise APIAuthError("Wrong authorization token")
     return authorization_header.replace("MunkiEnrolledMachine", "").strip()
Beispiel #2
0
 def check_data_secret(self, data):
     msn = data.get('machine_serial_number')
     if not msn:
         raise APIAuthError(
             f"No reported machine serial number. Request SN {self.machine_serial_number}."
         )
     if msn != self.machine_serial_number:
         # the serial number reported by the zentral postflight is not the one in the enrollment secret.
         auth_err = "Zentral postflight reported SN {} different from enrollment SN {}".format(
             msn, self.machine_serial_number)
         post_machine_conflict_event(self.request, "zentral.contrib.munki",
                                     msn, self.machine_serial_number, {})
         raise APIAuthError(auth_err)
Beispiel #3
0
 def verify_signed_secret(self, enroll_secret):
     api_secret_data = verify_secret(enroll_secret, SOURCE_MODULE)
     self.machine_serial_number = api_secret_data.get(
         'machine_serial_number', None)
     if not self.machine_serial_number:
         raise APIAuthError("No serial number")
     self.business_unit = api_secret_data.get("business_unit", None)
Beispiel #4
0
 def get_instance_with_secret(self, secret):
     try:
         data = signing.loads(secret, key=API_SECRET)
     except signing.BadSignature:
         raise APIAuthError("Bad secret signature")
     else:
         return self.instances[data["url"]]
Beispiel #5
0
 def verify_enrolled_machine_id(self):
     """Find the corresponding enrolled machine"""
     try:
         self.enrolled_machine = (EnrolledMachine.objects
                                                 .select_related("enrollment__secret__meta_business_unit")
                                                 .get(machine_id=self.machine_id))
     except EnrolledMachine.DoesNotExist:
         raise APIAuthError("Could not authorize the request")
     else:
         self.machine_serial_number = self.enrolled_machine.serial_number
         self.business_unit = self.enrolled_machine.enrollment.secret.get_api_enrollment_business_unit()
Beispiel #6
0
 def verify_enrolled_machine_token(self, token):
     try:
         enrolled_machine = (EnrolledMachine.objects.select_related(
             "enrollment__secret__meta_business_unit").get(token=token))
     except EnrolledMachine.DoesNotExist:
         raise APIAuthError("Enrolled machine does not exist")
     else:
         self.enrollment = enrolled_machine.enrollment
         self.machine_serial_number = enrolled_machine.serial_number
         self.business_unit = self.enrollment.secret.get_api_enrollment_business_unit(
         )
Beispiel #7
0
 def get_serial_number(self, data):
     try:
         serial_number = data["host_details"]["system_info"]["hardware_serial"].strip()
     except (KeyError, AttributeError):
         serial_number = None
     if serial_number is None:
         # special configuration for linux machines. see install script.
         serial_number = data.get("host_identifier", None)
     if not serial_number:
         raise APIAuthError("No serial number")
     return serial_number
Beispiel #8
0
 def check_data_secret(self, data):
     reported_serial_number = data['serial_num']
     if reported_serial_number != self.machine_serial_number:
         # the SN reported by osquery is not the one configured in the enrollment secret
         auth_err = "santa reported SN {} different from enrollment SN {}".format(reported_serial_number,
                                                                                  self.machine_serial_number)
         machine_info = {k: v for k, v in data.items()
                         if k in ("hostname", "os_build", "os_version", "serial_num", "primary_user") and v}
         post_machine_conflict_event(self.request, "zentral.contrib.santa",
                                     reported_serial_number, self.machine_serial_number,
                                     machine_info)
         raise APIAuthError(auth_err)
Beispiel #9
0
 def check_request_secret(self, request, *args, **kwargs):
     enrolled_machine_token = self.get_enrolled_machine_token(request)
     if enrolled_machine_token:
         # new way
         self.request_secret = enrolled_machine_token
         self.verify_enrolled_machine_token(enrolled_machine_token)
     else:
         # old way
         self.request_secret = self.get_request_secret(request)
         if self.request_secret:
             self.verify_request_secret(self.request_secret)
         else:
             raise APIAuthError("Could not authenticate the request")
Beispiel #10
0
 def verify_enrollment_secret(self, enroll_secret, serial_number, uuid):
     try:
         es_request = verify_enrollment_secret("osquery_enrollment",
                                               enroll_secret,
                                               self.user_agent, self.ip,
                                               serial_number, uuid)
     except EnrollmentSecretVerificationFailed:
         raise APIAuthError("Unknown enrolled machine")
     else:
         self.enrollment = es_request.enrollment_secret.osquery_enrollment
         self.machine_serial_number = serial_number
         self.business_unit = self.enrollment.secret.get_api_enrollment_business_unit(
         )
Beispiel #11
0
 def get_machine_snapshot(self):
     if not self.machine_snapshot:
         auth_err = None
         try:
             self.machine_snapshot = MachineSnapshot.objects.current().get(source__module=SOURCE_MODULE,
                                                                           reference=self.node_key)
         except MachineSnapshot.DoesNotExist:
             auth_err = "Wrong node_key"
         except MachineSnapshot.MultipleObjectsReturned:
             auth_err = "Multiple current osquery machine snapshots for node key '{}'".format(self.node_key)
         if auth_err:
             logger.error("APIAuthError %s", auth_err)
             raise APIAuthError(auth_err)
     return self.machine_snapshot
Beispiel #12
0
 def check_data_secret(self, data):
     auth_err = None
     try:
         self.ms = MachineSnapshot.objects.current().get(source__module='zentral.contrib.osquery',
                                                         reference=data['node_key'])
     except KeyError:
         auth_err = "Missing node_key"
     except MachineSnapshot.DoesNotExist:
         auth_err = "Wrong node_key"
     if auth_err:
         logger.error("APIAuthError %s", auth_err, extra=data)
         raise APIAuthError(auth_err)
     # TODO: Better verification ?
     self.machine_serial_number = self.ms.serial_number
     self.business_unit = self.ms.business_unit
Beispiel #13
0
 def check_data_secret(self, data):
     # no node_key, use the session_id
     # TODO: better?
     auth_err = None
     try:
         self.session_id = data["session_id"]
         self.carve_session = CarveSession.objects.get(session_id=self.session_id)
         self.machine_serial_number = self.carve_session.machine_serial_number
     except KeyError:
         auth_err = "Missing session id"
     except CarveSession.DoesNotExist:
         auth_err = "Unknown session id"
     if auth_err:
         logger.error("APIAuthError %s", auth_err, extra=data)
         raise APIAuthError(auth_err)
Beispiel #14
0
 def check_data_secret(self, data):
     super().check_data_secret(data)
     self.data_data = data.pop("data")
     for r in self.data_data:
         decorations = r.pop("decorations", None)
         if decorations:
             hardware_serial = decorations.get("hardware_serial")
             if hardware_serial and hardware_serial != self.machine_serial_number:
                 # the SN reported by osquery is not the one configured in the enrollment secret
                 auth_err = "osquery reported SN {} different from enrollment SN {}".format(
                     hardware_serial, self.machine_serial_number)
                 post_machine_conflict_event(self.request,
                                             "zentral.contrib.osquery",
                                             hardware_serial,
                                             self.machine_serial_number,
                                             decorations)
                 raise APIAuthError(auth_err)
Beispiel #15
0
 def verify_enrolled_machine_token(self, token):
     cache_key = f"munki.{token}"
     try:
         self.enrollment, self.machine_serial_number, self.business_unit = cache.get(
             cache_key)
     except TypeError:
         try:
             enrolled_machine = (EnrolledMachine.objects.select_related(
                 "enrollment__secret__meta_business_unit").get(token=token))
         except EnrolledMachine.DoesNotExist:
             raise APIAuthError("Enrolled machine does not exist")
         else:
             self.enrollment = enrolled_machine.enrollment
             self.machine_serial_number = enrolled_machine.serial_number
             self.business_unit = self.enrollment.secret.get_api_enrollment_business_unit(
             )
         cache.set(cache_key, (self.enrollment, self.machine_serial_number,
                               self.business_unit),
                   timeout=600)
Beispiel #16
0
    def check_data_secret(self, data):
        # get the node_key
        try:
            self.node_key = data["node_key"]
        except KeyError:
            raise APIAuthError("Missing node_key in osquery request")

        enrolled_machine = self.get_enrolled_machine()
        if enrolled_machine:
            # new way
            self.enrollment = enrolled_machine.enrollment
            self.machine_serial_number = enrolled_machine.serial_number
            self.business_unit = self.enrollment.secret.get_api_enrollment_business_unit()
        if not enrolled_machine:
            # old way, look for a MachineSnapshot with the node_key as reference
            # TODO: deprecate and remove
            machine_snapshot = self.get_machine_snapshot()
            self.machine_serial_number = machine_snapshot.serial_number
            self.business_unit = machine_snapshot.business_unit
Beispiel #17
0
 def check_data_secret(self, data):
     # no node id => check carve session id
     auth_err = None
     try:
         self.session_id = data["session_id"]
         self.carve_session = CarveSession.objects.get(
             session_id=self.session_id)
         self.machine_serial_number = self.carve_session.machine_serial_number
         self.ms = MachineSnapshot.objects.current().get(
             source__module='zentral.contrib.osquery',
             serial_number=self.machine_serial_number)
     except KeyError:
         auth_err = "Missing session id"
     except CarveSession.DoesNotExist:
         auth_err = "Unknown session id"
     except MachineSnapshot.DoesNotExist:
         auth_err = "Unknown machine serial number"
     if auth_err:
         logger.error("APIAuthError %s", auth_err, extra=data)
         raise APIAuthError(auth_err)
     self.business_unit = self.ms.business_unit
Beispiel #18
0
 def check_data_secret(self, data):
     super().check_data_secret(data)
     self.data_data = data.pop("data")
     for r in self.data_data:
         decorations = r.pop("decorations", None)
         if decorations:
             platform = platform_with_os_name(decorations.get("os_name"))
             if platform == MACOS:
                 hardware_serial = decorations.get("hardware_serial")
                 if hardware_serial and hardware_serial != self.machine_serial_number:
                     # The SN reported by osquery is not the one configured in the enrollment secret.
                     # For other platforms than MACOS, it could happen. For example, we take the GCE instance ID as
                     # serial number in the enrollment secret for linux, if possible.
                     # Osquery builds one from the SMBIOS/DMI.
                     auth_err = "osquery reported SN {} different from enrollment SN {}".format(
                         hardware_serial, self.machine_serial_number)
                     post_machine_conflict_event(self.request,
                                                 SOURCE_MODULE,
                                                 hardware_serial,
                                                 self.machine_serial_number,
                                                 decorations)
                     raise APIAuthError(auth_err)