Exemple #1
0
  def testGetSelf_Sorted(self):
    """Hosts are sorted by their rule_sync_dts."""
    early, middle, recent, recenter = common_test_utils.GetSequentialTimes(4)

    user = test_utils.CreateUser()

    santa_host_1 = test_utils.CreateSantaHost(
        primary_user=user.nickname, rule_sync_dt=early)
    santa_host_2 = test_utils.CreateSantaHost(
        primary_user=user.nickname, rule_sync_dt=middle)
    test_utils.CreateSantaHost(rule_sync_dt=recent)
    bit9_host_1 = test_utils.CreateBit9Host(
        users=[user.nickname], last_event_dt=recenter)

    self.assertTrue(model_utils.IsHostAssociatedWithUser(santa_host_1, user))
    self.assertTrue(model_utils.IsHostAssociatedWithUser(santa_host_2, user))
    self.assertTrue(model_utils.IsHostAssociatedWithUser(bit9_host_1, user))

    with self.LoggedInUser(user=user):
      response = self.testapp.get(self.SELF_ROUTE)
    output = response.json

    self.assertIn('application/json', response.headers['Content-type'])

    self.assertLen(output, 3)
    expected_host_ids = [
        bit9_host_1.key.id(), santa_host_2.key.id(), santa_host_1.key.id()]
    actual_host_ids = [entry['id'] for entry in output]
    self.assertListEqual(sorted(expected_host_ids), sorted(actual_host_ids))
 def testUnknownUserGet(self):
     """Normal user not associated with a host attempts to get it by ID."""
     with self.LoggedInUser() as user:
         self.assertFalse(
             model_utils.IsHostAssociatedWithUser(self.santa_host_1, user))
         self.testapp.get(self.ROUTE % self.santa_host_1.key.id(),
                          status=httplib.FORBIDDEN)
Exemple #3
0
    def testUnsupported(self):

        user = test_utils.CreateUser()
        host = MysteryHost()

        with self.assertRaises(ValueError):
            model_utils.IsHostAssociatedWithUser(host, user)
Exemple #4
0
    def dispatch(self):

        # Make sure a host_id is provided.
        host_id = self.request.route_kwargs.get('host_id')
        if not host_id:
            self.abort(httplib.BAD_REQUEST, explanation='No host_id provided')

        # Make sure the Host actually exists.
        self._normalized_host_id = host_models.Host.NormalizeId(host_id)
        host = self._GetHost()
        if not host:
            self.abort(httplib.NOT_FOUND,
                       explanation='Host %s not found' % host_id)

        # Make sure the Host is associated with the current user.
        if not model_utils.IsHostAssociatedWithUser(host, self.user):
            explanation = 'Host %s not associated with user %s' % (
                host.hostname, self.user.nickname)
            self.abort(httplib.FORBIDDEN, explanation=explanation)

        # Make sure a new_value is provided.
        new_value = self.request.route_kwargs.get('new_value')
        if not new_value:
            self.abort(httplib.BAD_REQUEST,
                       explanation='No new_value provided')

        # Make sure the new_value is an explicit boolean string.
        if re.match('^(true|false)$', new_value, flags=re.IGNORECASE) is None:
            self.abort(httplib.BAD_REQUEST,
                       explanation='Invalid new_value: %s' % new_value)

        super(BooleanPropertyHandler, self).dispatch()
Exemple #5
0
  def testAssociations(self):

    bit9_user = test_utils.CreateUser()
    bit9_host = test_utils.CreateBit9Host(users=[bit9_user.nickname])

    santa_user = test_utils.CreateUser()
    santa_host = test_utils.CreateSantaHost(primary_user=santa_user.nickname)

    self.assertTrue(
        model_utils.IsHostAssociatedWithUser(bit9_host, bit9_user))
    self.assertTrue(
        model_utils.IsHostAssociatedWithUser(santa_host, santa_user))
    self.assertFalse(
        model_utils.IsHostAssociatedWithUser(bit9_host, santa_user))
    self.assertFalse(
        model_utils.IsHostAssociatedWithUser(santa_host, bit9_user))
Exemple #6
0
  def testGet_UnknownUser(self):

    user = test_utils.CreateUser()
    host = test_utils.CreateSantaHost(primary_user=user.nickname)

    with self.LoggedInUser() as other_user:
      self.assertFalse(model_utils.IsHostAssociatedWithUser(host, other_user))
      self.testapp.get(self.ROUTE % host.key.id(), status=httplib.FORBIDDEN)
 def get(self, host_id):
     host_id = host_models.Host.NormalizeId(host_id)
     logging.info('Host handler get method called with ID=%s.', host_id)
     host = host_models.Host.get_by_id(host_id)
     if host is None:
         self.abort(httplib.NOT_FOUND, explanation='Host not found')
     elif not model_utils.IsHostAssociatedWithUser(host, self.user):
         self.RequireCapability(constants.PERMISSIONS.VIEW_OTHER_HOSTS)
     self.respond_json(host)
Exemple #8
0
    def post(self, host_id):

        # This request should only be available to admins or users who have (at
        # least at one time) had control of the host.
        if not (self.user.is_admin
                or model_utils.IsHostAssociatedWithUser(self.host, self.user)):
            logging.warning(
                'User %s is not authorized to request an Exemption for host %s',
                self.user.nickname, host_id)
            self.abort(httplib.FORBIDDEN,
                       explanation='Host not associated with user %s' %
                       self.user.nickname)

        # Extract and validate the exemption reason.
        reason = self.request.get('reason')
        other_text = self.request.get('otherText') or None
        if not reason:
            self.abort(httplib.BAD_REQUEST, explanation='No reason provided')
        elif reason == constants.EXEMPTION_REASON.OTHER and not other_text:
            self.abort(
                httplib.BAD_REQUEST,
                explanation='No explanation for "Other" reason provided')

        # Extract and validate the exemption duration.
        duration = self.request.get('duration')
        if not duration:
            self.abort(httplib.BAD_REQUEST,
                       explanation='Exemption term not provided')

        # Request a new Exemption, and bail if something goes wrong.
        try:
            exemption_api.Request(host_id, reason, other_text, duration)
        except exemption_api.InvalidRenewalError:
            self.abort(httplib.BAD_REQUEST,
                       'Request cannot be renewed at this time')
        except exemption_api.InvalidReasonError:
            self.abort(httplib.BAD_REQUEST, 'Invalid reason provided')
        except exemption_api.InvalidDurationError:
            self.abort(httplib.BAD_REQUEST, 'Invalid duration provided')
        except Exception:  # pylint: disable=broad-except
            logging.exception(
                'Error encountered while escalating Exemption for host %s',
                host_id)
            self.abort(httplib.INTERNAL_SERVER_ERROR,
                       explanation='Error while escalating exemption')

        # Start processing the Exemption right away, rather than waiting for the
        # 15 minute cron to catch it. On the off chance the cron fires between the
        # above Request() call and here, catch and ignore InvalidStateChangeErrors.
        try:
            exm_key = exemption_models.Exemption.CreateKey(host_id)
            exemption_api.Process(exm_key)
        except exemption_models.InvalidStateChangeError:
            logging.warning('Error encountered while processing Exemption')

        self._RespondWithExemptionAndTransitiveState(exm_key)
    def testAssociatedUserGet_PrimaryUser(self):
        """Normal user associated with a host gets it by ID."""
        with self.LoggedInUser() as user:
            self.santa_host_3.primary_user = user.nickname
            self.santa_host_3.put()
            self.assertTrue(
                model_utils.IsHostAssociatedWithUser(self.santa_host_3, user))
            response = self.testapp.get(self.ROUTE %
                                        self.santa_host_3.key.id())

        output = response.json

        self.assertIn('application/json', response.headers['Content-type'])
        self.assertIsInstance(output, dict)
Exemple #10
0
  def testGet_PrimaryUser_NoPriorExemption(self):

    user = test_utils.CreateUser()
    host = test_utils.CreateSantaHost(primary_user=user.nickname)
    self.assertTrue(model_utils.IsHostAssociatedWithUser(host, user))

    with self.LoggedInUser(user=user):
      response = self.testapp.get(self.ROUTE % host.key.id())

    output = response.json

    self.assertIn('application/json', response.headers['Content-type'])
    self.assertIsInstance(output, dict)
    self.assertNotIn('exemption', output)
Exemple #11
0
    def get(self, host_id):

        host_id = host_models.Host.NormalizeId(host_id)
        logging.info('Host handler get method called with ID=%s.', host_id)
        host = host_models.Host.get_by_id(host_id)

        if host is None:
            self.abort(httplib.NOT_FOUND, explanation='Host not found')
        elif not model_utils.IsHostAssociatedWithUser(host, self.user):
            self.RequirePermission(constants.PERMISSIONS.VIEW_OTHER_HOSTS)

        # Include Exemption data with the Host (if one exists).
        exm = exemption_models.Exemption.Get(host.key.id())
        host_dict = host.to_dict()
        if exm:
            host_dict['exemption'] = exm.to_dict()

        self.respond_json(host_dict)
    def testAssociatedUserGet(self):
        """Normal user associated with a host gets it by ID."""
        blockable = test_utils.CreateBlockable()
        with self.LoggedInUser() as user:
            test_utils.CreateSantaEvent(blockable,
                                        host_id=self.santa_host_1.key.id(),
                                        executing_user=user.nickname,
                                        parent=datastore_utils.ConcatenateKeys(
                                            user.key, self.santa_host_1.key,
                                            blockable.key))
            self.assertTrue(
                model_utils.IsHostAssociatedWithUser(self.santa_host_1, user))
            response = self.testapp.get(self.ROUTE %
                                        self.santa_host_1.key.id())

        output = response.json

        self.assertIn('application/json', response.headers['Content-type'])
        self.assertIsInstance(output, dict)
Exemple #13
0
    def get(self, host_id):

        logging.info('Retrieving Exemption for host %s', host_id)

        # This request should only be available to admins or users who have (at
        # least at one time) had control of the host.
        if not (self.user.is_admin
                or model_utils.IsHostAssociatedWithUser(self.host, self.user)):
            logging.warning(
                'User %s is not authorized to access Exemption for host %s',
                self.user.nickname, host_id)
            self.abort(httplib.FORBIDDEN,
                       explanation='Host not associated with user %s' %
                       self.user.nickname)

        if self.exm is None:
            self.abort(httplib.NOT_FOUND, explanation='Exemption not found')

        self.respond_json(self.exm)
Exemple #14
0
  def testGet_AssociatedUser(self):

    user = test_utils.CreateUser()
    host = test_utils.CreateSantaHost(primary_user=user.nickname)
    test_utils.CreateExemption(host.key.id())
    blockable = test_utils.CreateBlockable()
    test_utils.CreateSantaEvent(
        blockable, host_id=host.key.id(), executing_user=user.nickname,
        parent=datastore_utils.ConcatenateKeys(
            user.key, host.key, blockable.key))
    self.assertTrue(model_utils.IsHostAssociatedWithUser(host, user))

    with self.LoggedInUser(user=user):
      response = self.testapp.get(self.ROUTE % host.key.id())

    output = response.json

    self.assertIn('application/json', response.headers['Content-type'])
    self.assertIsInstance(output, dict)
    self.assertIn('exemption', output)
Exemple #15
0
    def post(self, host_id):

        if not self.exm:
            self.abort(httplib.NOT_FOUND, explanation='Exemption not found')

        # Verify that the current user is associated with the Host.
        # NOTE: Admins don't get a pass here, they can (and should) use the
        # above 'revoke' handler instead.
        if not model_utils.IsHostAssociatedWithUser(self.host, self.user):
            logging.error('Host %s not associated with user %s', host_id,
                          self.user.nickname)
            self.abort(httplib.FORBIDDEN,
                       explanation='Host not associated with requesting user')

        try:
            exemption_api.Cancel(self.exm.key)
        except Exception:  # pylint: disable=broad-except
            logging.exception(
                'Error encountered while cancelling Exemption for host %s',
                host_id)
            self.abort(httplib.INTERNAL_SERVER_ERROR,
                       explanation='Failed to cancel exemption')