Ejemplo n.º 1
0
Archivo: base.py Proyecto: smusa/simian
 def GetSerializedItem(cls, key):
     """Returns the deserialized value of a serialized cache."""
     entity = cls.MemcacheWrappedGet(key)
     if entity and entity.blob_value:
         return util.Deserialize(entity.blob_value), entity.mtime
     else:
         return {}, None
Ejemplo n.º 2
0
 def testDeserializeJson(self):
     """Test Deserialize()."""
     with mock.patch.object(util.json, 'loads', return_value='object1'):
         self.assertEqual('object1', util.Deserialize('serial1'))
     with mock.patch.object(util.json, 'loads', side_effect=ValueError):
         self.assertRaises(util.DeserializeError, util.Deserialize,
                           'serial2')
Ejemplo n.º 3
0
    def _DisplayMsuLogSummary(self):
        """Displays a summary of MSU logs."""
        summaries = []
        for since_days in None, 7, 1:
            key = 'msu_user_summary'
            if since_days:
                key = '%s_since_%sD_' % (key, since_days)
                human_since = '%s day(s)' % since_days
            else:
                human_since = 'forever'

            m = models.ReportsCache.get_by_key_name(key)
            if not m or not m.blob_value:
                continue
            summary = util.Deserialize(m.blob_value)
            summary_list = []
            keys = summary.keys()
            keys.sort(cmp=lambda x, y: cmp(summary[x], summary[y]),
                      reverse=True)
            for x in keys:
                summary_list.append({'var': x, 'val': summary[x]})

            summaries.append({
                'values': summary_list,
                'since': human_since,
                'mtime': m.mtime
            })

        # TODO(user): Since the above is a list now, memcache here.

        self.Render('msu_log_summary.html', {
            'summaries': summaries,
            'report_type': 'msu_gui_logs'
        })
Ejemplo n.º 4
0
  def testDeserializeUnicode(self):
    """Test Deserialize()."""
    ustr = u'Hello there\u2014'
    ustr_js = '"Hello there\\u2014"'

    self.assertEqual(
        ustr,
        util.Deserialize(ustr_js, _use_json=True, _use_pickle=False))
Ejemplo n.º 5
0
 def testSet(self, *_):
   self.testapp.post(
       '/admin/ip_blacklist', {'item_0': '192.168.1.1', 'item_1': 'zerocool'},
       status=httplib.FOUND)
   self.assertEqual(
       {'192.168.1.1': 'zerocool'},
       util.Deserialize(models.KeyValueCache.MemcacheWrappedGet(
           'client_exit_ip_blocks', 'text_value')))
Ejemplo n.º 6
0
  def testDeserializeFloat(self):
    """Test Deserialize()."""
    input = '{"foo": 103.2261}'
    output = {'foo': 103.2261}

    self.assertEqual(
        output,
        util.Deserialize(input))
Ejemplo n.º 7
0
 def __set__(self, model_instance, value):
     """Deserializes db.Text values and simply sets other types to self._obj."""
     if value is None or value == '':
         super(SerializedProperty, self).__set__(model_instance, None)
     elif type(value) is db.Text:
         # If the value is is db.Text, deserialize it to init _obj.
         self._obj = util.Deserialize(value)
     else:
         # If the incoming value is a not db.Text, it's an obj so just store it.
         self._obj = value
Ejemplo n.º 8
0
 def GetMembers(self, group_name):
   """Get a list of members belonging to the group."""
   members = models.KeyValueCache.MemcacheWrappedGet(group_name, 'text_value')
   member_list = []
   if members:
     try:
       member_list = util.Deserialize(members)
     except util.DeserializeError:
       pass
   return member_list
Ejemplo n.º 9
0
    def IpInList(cls, key_name, ip):
        """Check whether IP is in serialized IP/mask list in key_name.

    The KeyValueCache entity at key_name is expected to have a text_value
    which is in util.Serialize() form. The deserialized structure looks like

    [ "200.0.0.0/24",
      "10.0.0.0/8",
      etc ...
    ]

    Note that this function is not IPv6 safe and will always return False
    if the input ip is IPv6 format.

    Args:
      key_name: str, like 'auth_bad_ip_blocks'
      ip: str, like '127.0.0.1'
    Returns:
      True if the ip is inside a mask in the list, False if not
    """
        if not ip:
            return False  # lenient response

        # TODO(user): Once the underlying util.Ip* methods support ipv6
        # this method can go away. Until then, this stops all of the churn
        # and exits early.
        if ip.find(':') > -1:  # ipv6
            return False

        try:
            ip_blocks_str = cls.MemcacheWrappedGet(key_name, 'text_value')
            if not ip_blocks_str:
                return False
            ip_blocks = util.Deserialize(ip_blocks_str)
        except (util.DeserializeError, db.Error):
            logging.exception('IpInList(%s)', ip)
            return False  # lenient response

        # Note: The method below, parsing a serialized list of networks
        # expressed as strings, might seem silly. But the total time to
        # deserialize and translate the strings back into IP network/mask
        # integers is actually faster than storing them already split, e.g. a
        # list of 2 item lists (network,mask). Apparently JSON isn't as
        # efficient at parsing ints or nested lists.
        #
        # (pickle is 2X+ faster but not secure & deprecated inside util module)

        ip_int = ipcalc.IpToInt(ip)

        for ip_mask_str in ip_blocks:
            ip_mask = ipcalc.IpMaskToInts(ip_mask_str)
            if (ip_int & ip_mask[1]) == ip_mask[0]:
                return True

        return False
Ejemplo n.º 10
0
    def testDeserializeJson(self):
        """Test Deserialize()."""
        self.mox.StubOutWithMock(util.json, 'loads')

        util.json.loads('serial1', parse_float=float).AndReturn('object1')
        util.json.loads('serial2', parse_float=float).AndRaise(ValueError)

        self.mox.ReplayAll()
        self.assertEqual('object1', util.Deserialize('serial1'))
        self.assertRaises(util.DeserializeError, util.Deserialize, 'serial2')
        self.mox.VerifyAll()
Ejemplo n.º 11
0
 def GetSerializedItem(cls, key):
     """Returns the deserialized value of a serialized cache."""
     entity = cls.MemcacheWrappedGet(key)
     if entity and entity.blob_value:
         data = entity.blob_value
         mtime = entity.mtime
         i = 1
         while entity and len(
                 entity.blob_value) >= _MEMCACHE_ENTITY_SIZE_LIMIT:
             entity = cls.MemcacheWrappedGet('%s_shard_%s' % (key, i))
             if entity and entity.blob_value:
                 data += entity.blob_value
             i += 1
         return util.Deserialize(data), mtime
     else:
         return {}, None
Ejemplo n.º 12
0
 def get(self):
   """GET handler."""
   if not self.IsAdminUser():
     self.error(httplib.FORBIDDEN)
     return
   ips = {}
   try:
     ips = util.Deserialize(
         models.KeyValueCache.MemcacheWrappedGet('client_exit_ip_blocks',
                                                 'text_value'))
   except util.DeserializeError:
     pass
   d = {'report_type': 'ip_blacklist', 'title': 'IP Blacklist', 'columns': 2,
        'list': sorted(ips.items()), 'labels': ['IP', 'Comment'],
        'regex': ['/%s/' % IP_REGEX, '/^.{0,60}$/'],
        'infopanel': 'Subnet format required (e.g. 192.168.1.0/24)'}
   self.Render('list_edit.html', d)
Ejemplo n.º 13
0
def _GetGroupMembers(group_name):
    """Returns a set of email addresses that are members of a given group.

  Args:
    group_name: str group name to return the members of.
  Returns:
    List of email addresses of members, or an empty list for unknown groups.
  """
    members = getattr(settings, group_name.upper(), [])
    try:
        json_members = models.KeyValueCache.MemcacheWrappedGet(
            group_name, 'text_value')
        if json_members:
            members.extend(util.Deserialize(json_members))
    except (db.Error, util.DeserializeError):
        pass
    return members
Ejemplo n.º 14
0
    def testDeserializePickle(self):
        """Test Deserialize()."""
        self.mox.StubOutWithMock(util.pickle, 'loads')

        util.pickle.loads('serial1').AndReturn('object1')
        util.pickle.loads('serial2').AndRaise(util.pickle.UnpicklingError)

        self.mox.ReplayAll()
        self.assertEqual(
            'object1',
            util.Deserialize('serial1',
                             _use_json=False,
                             _use_pickle=True,
                             _pickle_re=util.re.compile('.')))
        self.assertRaises(util.DeserializeError,
                          util.Deserialize,
                          'serial2',
                          _use_json=False,
                          _use_pickle=True,
                          _pickle_re=util.re.compile('.'))
        self.mox.VerifyAll()
Ejemplo n.º 15
0
    def _DisplayMsuLogSummary(self, since_days=None):
        """Displays a summary of MSU logs."""
        key = 'msu_user_summary'
        if since_days:
            key = '%s_since_%sD_' % (key, since_days)
            human_since = '%s day(s)' % since_days
        else:
            human_since = 'forever'

        m = models.ReportsCache.get_by_key_name(key)
        summary = util.Deserialize(m.blob_value)
        summary_list = []
        keys = summary.keys()
        keys.sort(cmp=lambda x, y: cmp(summary[x], summary[y]))
        map(lambda x: summary_list.append({'var': x, 'val': summary[x]}), keys)

        self.response.out.write(
            RenderTemplate('templates/stats_msulogsummary.html', {
                'summary': summary_list,
                'since': human_since,
                'mtime': m.mtime,
            }))
Ejemplo n.º 16
0
 def _GetUserSettings(self):
     """Returns the user setting dictionary, or None."""
     if self._user_settings:
         return util.Deserialize(self._user_settings)
     else:
         return None
Ejemplo n.º 17
0
  def testDeserializeUnicode(self):
    """Test Deserialize()."""
    ustr = u'Hello there\u2014'
    ustr_js = '"Hello there\\u2014"'

    self.assertEqual(ustr, util.Deserialize(ustr_js))
Ejemplo n.º 18
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))
Ejemplo n.º 19
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,
                ))