Exemplo n.º 1
0
    def testSuccess(self):

        host_id = test_utils.CreateSantaHost().key.id()
        other_host_id = test_utils.CreateSantaHost().key.id()
        blockable = test_utils.CreateSantaBlockable()

        # Same Blockable, but wrong Host.
        test_utils.CreateSantaEvent(blockable,
                                    host_id=other_host_id,
                                    executing_user='******')

        # Correct Host.
        test_utils.CreateSantaEvent(blockable,
                                    host_id=host_id,
                                    executing_user='******')

        # Multiple Events for one user.
        for _ in range(3):
            test_utils.CreateSantaEvent(blockable,
                                        host_id=host_id,
                                        executing_user='******')

        # Correct Host, but local admin.
        test_utils.CreateSantaEvent(blockable,
                                    host_id=host_id,
                                    executing_user=constants.LOCAL_ADMIN.MACOS)

        expected_users = ['user2', 'user3']
        actual_users = sorted(
            model_utils.GetUsersAssociatedWithSantaHost(host_id))
        self.assertEqual(expected_users, actual_users)
Exemplo n.º 2
0
    def put(self, host_id, new_value):

        # Only Santa clients are supported.
        host = self._GetHost()
        if host.GetClientName() != constants.CLIENT.SANTA:
            self.abort(
                httplib.FORBIDDEN,
                explanation='Only Santa clients support transitive whitelisting'
            )

        self._UpdateHost()

        # Note the state change in BigQuery.
        users = model_utils.GetUsersAssociatedWithSantaHost(
            self._normalized_host_id)
        comment = 'Transitive whitelisting %s by %s' % (
            'enabled' if self._bool_new_value else 'disabled',
            self.user.nickname)
        tables.HOST.InsertRow(device_id=host_id,
                              timestamp=datetime.datetime.utcnow(),
                              action=constants.HOST_ACTION.COMMENT,
                              hostname=host.hostname,
                              platform=constants.PLATFORM.MACOS,
                              users=users,
                              mode=host.client_mode,
                              comment=comment)
Exemplo n.º 3
0
    def post(self, uuid):
        self.host.last_postflight_dt = datetime.datetime.utcnow()
        self.host.rule_sync_dt = self.host.last_preflight_dt
        self.host.put()

        host_id = self.host.key.id()
        tables.HOST.InsertRow(
            device_id=host_id,
            timestamp=self.host.last_postflight_dt,
            action=constants.HOST_ACTION.FULL_SYNC,
            hostname=self.host.hostname,
            platform=constants.PLATFORM.MACOS,
            users=model_utils.GetUsersAssociatedWithSantaHost(host_id),
            mode=self.host.client_mode)
Exemplo n.º 4
0
    def post(self, uuid):
        futures = []

        # Create an User for the primary_user on any preflight if one doesn't
        # already exist.
        primary_user = self.parsed_json.get(_PREFLIGHT.PRIMARY_USER)
        user = user_models.User.GetOrInsert(
            user_utils.UsernameToEmail(primary_user))
        # Ensures the returned username is consistent with the User entity.
        primary_user = user.nickname

        # Create a SantaHost on the first preflight.
        first_preflight = not self.host
        if first_preflight:
            logging.info('Host %s is syncing for the first time', uuid)
            self.host = host_models.SantaHost(key=self.host_key)
            self.host.client_mode = settings.SANTA_DEFAULT_CLIENT_MODE
            futures.append(_CopyLocalRules(user.key, uuid))

        # Update host entity on every sync.
        self.host.serial_num = self.parsed_json.get(_PREFLIGHT.SERIAL_NUM)
        self.host.hostname = self.parsed_json.get(_PREFLIGHT.HOSTNAME)
        self.host.primary_user = primary_user
        self.host.santa_version = self.parsed_json.get(
            _PREFLIGHT.SANTA_VERSION)
        self.host.os_version = self.parsed_json.get(_PREFLIGHT.OS_VERSION)
        self.host.os_build = self.parsed_json.get(_PREFLIGHT.OS_BUILD)
        self.host.last_preflight_dt = datetime.datetime.utcnow()
        self.host.last_preflight_ip = self.request.remote_addr

        reported_mode = self.parsed_json.get(_PREFLIGHT.CLIENT_MODE)
        if reported_mode != self.host.client_mode:

            message = 'Client mode mismatch (Expected: %s, Actual: %s)' % (
                self.host.client_mode, reported_mode)
            logging.info(message)

            # If the client_mode doesn't correspond to a known value, report it as
            # UNKNOWN.
            if reported_mode not in constants.HOST_MODE.SET_ALL:
                reported_mode = constants.HOST_MODE.UNKNOWN

            tables.HOST.InsertRow(
                device_id=uuid,
                timestamp=datetime.datetime.utcnow(),
                action=constants.HOST_ACTION.COMMENT,
                hostname=self.host.hostname,
                platform=constants.PLATFORM.MACOS,
                users=model_utils.GetUsersAssociatedWithSantaHost(uuid),
                mode=reported_mode,
                comment=message)

        if self.parsed_json.get(_PREFLIGHT.REQUEST_CLEAN_SYNC):
            logging.info('Client requested clean sync')
            self.host.rule_sync_dt = None

        # Save host entity.
        futures.append(self.host.put_async())

        # If the big red button is pressed, override the self.host.client_mode
        # set in datastore with either MONITOR or LOCKDOWN for this response only.
        actual_client_mode = self.host.client_mode
        big_red_button = big_red.BigRedButton()
        if big_red_button.stop_stop_stop:
            actual_client_mode = constants.SANTA_CLIENT_MODE.MONITOR
        elif big_red_button.go_go_go:
            actual_client_mode = constants.SANTA_CLIENT_MODE.LOCKDOWN

        # Prepare response.
        response = {
            _PREFLIGHT.BATCH_SIZE: (settings.SANTA_EVENT_BATCH_SIZE),
            _PREFLIGHT.CLIENT_MODE:
            actual_client_mode,
            _PREFLIGHT.WHITELIST_REGEX:
            (self.host.directory_whitelist_regex
             if self.host.directory_whitelist_regex is not None else
             settings.SANTA_DIRECTORY_WHITELIST_REGEX),
            _PREFLIGHT.BLACKLIST_REGEX:
            (self.host.directory_blacklist_regex
             if self.host.directory_blacklist_regex is not None else
             settings.SANTA_DIRECTORY_BLACKLIST_REGEX),
            _PREFLIGHT.CLEAN_SYNC:
            not self.host.rule_sync_dt,
            _PREFLIGHT.BUNDLES_ENABLED: (settings.SANTA_BUNDLES_ENABLED),
            _PREFLIGHT.TRANSITIVE_WHITELISTING_ENABLED:
            (self.host.transitive_whitelisting_enabled),
        }

        if self.host.should_upload_logs:
            response[_PREFLIGHT.UPLOAD_LOGS_URL] = (
                blobstore.create_upload_url('/api/santa/logupload/%s' % uuid))

        # Verify all futures resolved successfully.
        for future in futures:
            future.check_success()

        # If this is the first preflight, create a FIRST_SEEN HostRow. This has to
        # occur after the new SantaHost entity is put(), since SantaHost.recorded_dt
        # is an auto_now_add.
        if first_preflight:
            new_host = ndb.Key('Host', uuid).get()
            tables.HOST.InsertRow(
                device_id=uuid,
                timestamp=new_host.recorded_dt,
                action=constants.HOST_ACTION.FIRST_SEEN,
                hostname=new_host.hostname,
                platform=constants.PLATFORM.MACOS,
                users=model_utils.GetUsersAssociatedWithSantaHost(uuid),
                mode=new_host.client_mode)

        self.respond_json(response)