Esempio n. 1
0
 def testParseClientIdWithoutRequiredFields(self):
   """Tests ParseClientId() without required fields."""
   client_id_dict = {}
   for key in common.CLIENT_ID_FIELDS.keys():
     client_id_dict[key] = None
   client_id_dict['track'] = common.common.DEFAULT_TRACK
   # empty cid
   self.assertEqual(client_id_dict, common.ParseClientId(''))
   # empty cid with delimiters
   self.assertEqual(client_id_dict, common.ParseClientId('|||'))
   # cid with unknown key name
   client_id_dict['ASDFMOOCOW'] = '1'
   self.assertEqual(client_id_dict, common.ParseClientId('ASDFMOOCOW=1'))
   del client_id_dict['ASDFMOOCOW']
Esempio n. 2
0
 def testParseClientIdWithValidClientIdAllValidTracks(self):
   """Tests ParseClientId() with a valid client id; tests all valid tracks."""
   client_id_str, client_id_dict = self._GetClientIdTestData()
   for track in common.common.TRACKS:
     cid = client_id_str % track
     client_id_dict['track'] = track
     self.assertEqual(client_id_dict, common.ParseClientId(cid))
Esempio n. 3
0
 def testParseClientIdOnCorp(self):
   """Tests ParseClientId with on_corp=1."""
   client_id_str, client_id_dict = self._GetClientIdTestData()
   client_id_str = client_id_str.replace('on_corp=0', 'on_corp=1')
   client_id_dict['on_corp'] = True
   cid = client_id_str % 'stable'
   client_id_dict['track'] = 'stable'
   self.assertEqual(client_id_dict, common.ParseClientId(cid))
Esempio n. 4
0
 def testParseClientIdWithAppleSusTrue(self):
   """Tests ParseClientId with applesus=true."""
   client_id_str, client_id_dict = self._GetClientIdTestData()
   client_id_str = client_id_str.replace('applesus=false', 'applesus=true')
   client_id_dict['applesus'] = True
   cid = client_id_str % 'stable'
   client_id_dict['track'] = 'stable'
   self.assertEqual(client_id_dict, common.ParseClientId(cid))
Esempio n. 5
0
 def testParseClientIdNoneBool(self):
   """Tests ParseClientId with on_corp=<missing>."""
   client_id_str, client_id_dict = self._GetClientIdTestData()
   client_id_str = client_id_str.replace('on_corp=0', 'on_corp=')
   client_id_dict['on_corp'] = None
   cid = client_id_str % 'stable'
   client_id_dict['track'] = 'stable'
   self.assertEqual(client_id_dict, common.ParseClientId(cid))
Esempio n. 6
0
 def testParseClientIdWithInvalidType(self):
   """Tests ParseClientId() with an invalid type; checks for None."""
   client_id_str, client_id_dict = self._GetClientIdTestData()
   client_id_str = client_id_str.replace('uptime=123.0', 'uptime=hello')
   client_id_dict['uptime'] = None
   for track in common.common.TRACKS:
     cid = client_id_str % track
     client_id_dict['track'] = track
     self.assertEqual(client_id_dict, common.ParseClientId(cid))
Esempio n. 7
0
 def testParseClientIdNewline(self):
   """Tests ParseClientId when newline in the string."""
   client_id_str, client_id_dict = self._GetClientIdTestData()
   client_id_str = client_id_str.replace(
       'hostname=foohost', 'hostname=foo\nhost')
   client_id_dict['hostname'] = 'foo_host'
   cid = client_id_str % 'stable'
   client_id_dict['track'] = 'stable'
   self.assertEqual(client_id_dict, common.ParseClientId(cid))
Esempio n. 8
0
 def testParseClientIdWithVeryLongStrValues(self):
   """Tests ParseClientId() with str values that are over 500 characters."""
   long_owner = ''.join(str(i) for i in range(999))
   client_id_str, client_id_dict = self._GetClientIdTestData()
   client_id_str = client_id_str.replace(
       'owner=foouser', 'owner=%s' % long_owner)
   client_id_dict['owner'] = long_owner[:500]
   client_id_dict['track'] = common.common.DEFAULT_TRACK
   output = common.ParseClientId(client_id_str)
   for k in client_id_dict:
     self.assertEqual(client_id_dict[k], output.get(k))
Esempio n. 9
0
 def testParseClientIdWithUuidOverride(self):
   """Tests ParseClientId() with uuid override."""
   uuid_override = 'foouuidbar'
   uuid_override_full = 'CN=%s' % uuid_override
   client_id_str, client_id_dict = self._GetClientIdTestData()
   client_id_dict['uuid'] = uuid_override
   for track in common.common.TRACKS:
     cid = client_id_str % track
     client_id_dict['track'] = track
     self.assertEqual(
         client_id_dict, common.ParseClientId(cid, uuid=uuid_override_full))
Esempio n. 10
0
 def testParseClientIdWithUnicode(self):
   """Tests ParseClientId with some unicode characters."""
   client_id_str, client_id_dict = self._GetClientIdTestData()
   # Convert the client_id_str to unicode.
   client_id_unicode = client_id_str.decode('utf-8')
   # Replace foohost with a unicode O with umlaut, surrounded by zz.
   client_id_unicode = client_id_str.replace('foohost', u'zz\u00D6zz')
   cid = client_id_unicode % u'stable'
   client_id_dict[u'track'] = u'stable'
   client_id_dict[u'hostname'] = u'zz\xd6zz'
   self.assertEqual(client_id_dict, common.ParseClientId(cid))
Esempio n. 11
0
def GetClientIdForRequest(request, session=None, client_id_str=None):
    """Returns a client_id dict for the given request.

  Args:
    request: webapp Request object.
    session: response from auth.DoAnyAuth().
    client_id_str: str client id.
  Returns:
    a dict client_id.
  """
    if hasattr(session, 'uuid'):  # DoMunkiAuth returned session, override uuid
        # webapp's request.headers.get() returns None if the key doesn't exist
        # which breaks urllib.unquote(), so return empty string default instead.
        client_id = request.headers.get('X-munki-client-id', '')
        if not client_id:
            logging.warning('Client ID header missing: %s', session.uuid)
        client_id = urllib.unquote(client_id)
        client_id = common.ParseClientId(client_id, uuid=session.uuid)
    else:  # DoUserAuth was called; setup client id
        client_id_str = urllib.unquote(client_id_str)
        client_id = common.ParseClientId(client_id_str)

    return client_id
Esempio n. 12
0
 def _SanitazeMunkiHeader(self, munki_header):
     """Leave required fields only."""
     client_id = common.ParseClientId(munki_header)
     return 'os_version=%s|track=%s' % (client_id.get(
         'os_version', ''), client_id.get('track', 'stable'))
Esempio n. 13
0
    def post(self):
        """Reports get handler.

    Returns:
      A webapp.Response() response.
    """
        session = gaeserver.DoMunkiAuth()
        uuid = main_common.SanitizeUUID(session.uuid)
        report_type = self.request.get('_report_type')
        feedback_requested = self.request.get('_feedback')
        message = None
        details = None
        client_id = None
        computer = None

        if report_type == 'preflight' or report_type == 'postflight':
            client_id_str = urllib.unquote(self.request.get('client_id'))
            client_id = common.ParseClientId(client_id_str, uuid=uuid)
            user_settings_str = self.request.get('user_settings')
            user_settings = None
            try:
                if user_settings_str:
                    user_settings = util.Deserialize(
                        urllib.unquote(str(user_settings_str)))
            except util.DeserializeError:
                logging.warning('Client %s sent broken user_settings: %s',
                                client_id_str, user_settings_str)

            pkgs_to_install = self.request.get_all('pkgs_to_install')
            apple_updates_to_install = self.request.get_all(
                'apple_updates_to_install')

            computer = models.Computer.get_by_key_name(uuid)
            ip_address = os.environ.get('REMOTE_ADDR', '')
            report_feedback = None
            if report_type == 'preflight':
                # if the UUID is known to be lost/stolen, log this connection.
                if models.ComputerLostStolen.IsLostStolen(uuid):
                    logging.warning('Connection from lost/stolen machine: %s',
                                    uuid)
                    models.ComputerLostStolen.LogLostStolenConnection(
                        computer=computer, ip_address=ip_address)

                # we want to get feedback now, before preflight_datetime changes.
                if feedback_requested:
                    client_exit = self.request.get('client_exit', None)
                    report_feedback = self.GetReportFeedback(
                        uuid,
                        report_type,
                        computer=computer,
                        ip_address=ip_address,
                        client_exit=client_exit)
                    self.response.out.write(report_feedback)

                    # if report feedback calls for a client exit, log it.
                    if report_feedback == common.ReportFeedback.EXIT:
                        if not client_exit:
                            # client didn't ask for an exit, which means server decided.
                            client_exit = 'Connection from defined exit IP address'
                        common.WriteClientLog(models.PreflightExitLog,
                                              uuid,
                                              computer=computer,
                                              exit_reason=client_exit)

            common.LogClientConnection(report_type,
                                       client_id,
                                       user_settings,
                                       pkgs_to_install,
                                       apple_updates_to_install,
                                       computer=computer,
                                       ip_address=ip_address,
                                       report_feedback=report_feedback)

        elif report_type == 'install_report':
            computer = models.Computer.get_by_key_name(uuid)

            self._LogInstalls(self.request.get_all('installs'), computer)

            for removal in self.request.get_all('removals'):
                common.WriteClientLog(models.ClientLog,
                                      uuid,
                                      computer=computer,
                                      action='removal',
                                      details=removal)

            for problem in self.request.get_all('problem_installs'):
                common.WriteClientLog(models.ClientLog,
                                      uuid,
                                      computer=computer,
                                      action='install_problem',
                                      details=problem)
        elif report_type == 'preflight_exit':
            # NOTE(user): only remains for older clients.
            message = self.request.get('message')
            computer = common.WriteClientLog(models.PreflightExitLog,
                                             uuid,
                                             exit_reason=message)
        elif report_type == 'broken_client':
            # Default reason of "objc" to support legacy clients, existing when objc
            # was the only broken state ever reported.
            reason = self.request.get('reason', 'objc')
            details = self.request.get('details')
            logging.warning('Broken Munki client (%s): %s', reason, details)
            common.WriteBrokenClient(uuid, reason, details)
        elif report_type == 'msu_log':
            details = {}
            for k in ['time', 'user', 'source', 'event', 'desc']:
                details[k] = self.request.get(k, None)
            common.WriteComputerMSULog(uuid, details)
        else:
            # unknown report type; log all post params.
            params = []
            for param in self.request.arguments():
                params.append('%s=%s' % (param, self.request.get_all(param)))
            common.WriteClientLog(models.ClientLog,
                                  uuid,
                                  action='unknown',
                                  details=str(params))

        # If the client asked for feedback, get feedback and respond.
        # Skip this if the report_type is preflight, as report feedback was
        # retrieved before LogComputerConnection changed preflight_datetime.
        if feedback_requested and report_type != 'preflight':
            self.response.out.write(
                self.GetReportFeedback(
                    uuid,
                    report_type,
                    message=message,
                    details=details,
                    computer=computer,
                ))
Esempio n. 14
0
    def post(self):
        """Reports get handler.

    Returns:
      A webapp.Response() response.
    """
        session = gaeserver.DoMunkiAuth()
        uuid = main_common.SanitizeUUID(session.uuid)
        report_type = self.request.get('_report_type')
        report_feedback = {}
        message = None
        details = None
        client_id = None
        computer = None

        if report_type == 'preflight' or report_type == 'postflight':
            client_id_str = urllib.unquote(self.request.get('client_id'))
            client_id = common.ParseClientId(client_id_str, uuid=uuid)
            user_settings_str = self.request.get('user_settings')
            user_settings = None
            try:
                if user_settings_str:
                    user_settings = util.Deserialize(
                        urllib.unquote(str(user_settings_str)))
            except util.DeserializeError:
                logging.warning('Client %s sent broken user_settings: %s',
                                client_id_str, user_settings_str)

            pkgs_to_install = self.request.get_all('pkgs_to_install')
            apple_updates_to_install = self.request.get_all(
                'apple_updates_to_install')

            computer = models.Computer.get_by_key_name(uuid)
            ip_address = os.environ.get('REMOTE_ADDR', '')
            if report_type == 'preflight':
                # we want to get feedback now, before preflight_datetime changes.
                client_exit = self.request.get('client_exit', None)
                report_feedback = self.GetReportFeedback(
                    uuid,
                    report_type,
                    computer=computer,
                    ip_address=ip_address,
                    client_exit=client_exit)

                if self.request.get('json') == '1':
                    self.response.out.write(JSON_PREFIX +
                                            json.dumps(report_feedback))
                else:
                    # For legacy clients that accept a single string, not JSON.
                    feedback_to_send = 'OK'
                    for feedback in LEGACY_FEEDBACK_LIST:
                        if report_feedback.get(feedback.lower()):
                            feedback_to_send = feedback
                    self.response.out.write(feedback_to_send)

                # if report feedback calls for a client exit, log it.
                if report_feedback.get('exit'):
                    if not client_exit:
                        # client didn't ask for an exit, which means server decided.
                        client_exit = 'Connection from defined exit IP address'
                    common.WriteClientLog(models.PreflightExitLog,
                                          uuid,
                                          computer=computer,
                                          exit_reason=client_exit)

            common.LogClientConnection(report_type,
                                       client_id,
                                       user_settings,
                                       pkgs_to_install,
                                       apple_updates_to_install,
                                       computer=computer,
                                       ip_address=ip_address,
                                       report_feedback=report_feedback)

        elif report_type == 'install_report':
            computer = models.Computer.get_by_key_name(uuid)

            self._LogInstalls(self.request.get_all('installs'), computer)

            for removal in self.request.get_all('removals'):
                common.WriteClientLog(models.ClientLog,
                                      uuid,
                                      computer=computer,
                                      action='removal',
                                      details=removal)

            for problem in self.request.get_all('problem_installs'):
                common.WriteClientLog(models.ClientLog,
                                      uuid,
                                      computer=computer,
                                      action='install_problem',
                                      details=problem)
        elif report_type == 'broken_client':
            # Default reason of "objc" to support legacy clients, existing when objc
            # was the only broken state ever reported.
            reason = self.request.get('reason', 'objc')
            details = self.request.get('details')
            logging.warning('Broken Munki client (%s): %s', reason, details)
            common.WriteBrokenClient(uuid, reason, details)
        elif report_type == 'msu_log':
            details = {}
            for k in ['time', 'user', 'source', 'event', 'desc']:
                details[k] = self.request.get(k, None)
            common.WriteComputerMSULog(uuid, details)
        else:
            # unknown report type; log all post params.
            params = []
            for param in self.request.arguments():
                params.append('%s=%s' % (param, self.request.get_all(param)))
            common.WriteClientLog(models.ClientLog,
                                  uuid,
                                  action='unknown',
                                  details=str(params))