コード例 #1
0
ファイル: xsrf_utils_test.py プロジェクト: crudbug/upvote
 def setUp(self):
   app = webapp2.WSGIApplication(
       [webapp2.Route(r'', handler=FakeHandler)])
   super(XsrfTest, self).setUp(app, patch_generate_token=False)
   self.user_email = user_map.UsernameToEmail('test')
   self.Login(self.user_email)
   self.user_id = users.get_current_user().user_id()
コード例 #2
0
    def testAdminAddingUser(self):
        """Admin adding a user through a post request."""
        id_ = user_map.UsernameToEmail('user4')
        pre_post_user = base.User.get_by_id(id_)

        pre_post_user_existed = (pre_post_user is not None)

        params = {'roles': constants.USER_ROLE.TRUSTED_USER}

        with self.LoggedInUser(admin=True):
            response = self.testapp.post('/' + id_, params)

        expected_dict = {
            'id': id_,
            'roles': [constants.USER_ROLE.TRUSTED_USER]
        }

        datastore_user = base.User.get_by_id(id_)

        output = response.json

        self.assertIn('application/json', response.headers['Content-type'])
        self.assertIsInstance(output, dict)
        self.assertDictContainsSubset(expected_dict, output)
        self.assertDictContainsSubset(expected_dict, datastore_user.to_dict())
        self.assertFalse(pre_post_user_existed)
コード例 #3
0
ファイル: events.py プロジェクト: crudbug/upvote
    def get(self, blockable_id):  # pylint: disable=g-bad-name
        blockable = base_models.Blockable.get_by_id(blockable_id)
        if not blockable:
            self.abort(httplib.NOT_FOUND, explanation='Blockable not found')

        username = self.request.get('asUser')
        if username:
            self.RequireCapability(constants.PERMISSIONS.VIEW_OTHER_EVENTS)
            user = user_models.User.GetById(user_map.UsernameToEmail(username))
        else:
            user = self.user

        # If the blockable is a bundle, search by the 'bundle_key' property instead
        # of 'blockable_key'.
        blockable_filter = (santa_models.SantaEvent.bundle_key == blockable.key
                            if isinstance(blockable,
                                          santa_models.SantaBundle) else
                            base_models.Event.blockable_key == blockable.key)

        event_query = (base_models.Event.query(ancestor=user.key).filter(
            blockable_filter).order(-base_models.Event.last_blocked_dt))

        event = event_query.get()

        response_data = event
        if event:
            with_context = (self.request.get('withContext').lower() == 'true')
            response_data = _GetEventContext([event
                                              ])[0] if with_context else event

        self.respond_json(response_data)
コード例 #4
0
ファイル: users.py プロジェクト: rkornmeyer/upvote
    def post(self, user_id):
        """Post handler for users."""

        logging.debug('UserHandler POST method called with ID: %s', user_id)
        email_addr = user_map.UsernameToEmail(user_id)

        new_roles = self.request.get_all('roles')
        base_db.User.SetRoles(email_addr, new_roles)

        user = base_db.User.GetOrInsert(email_addr=email_addr)
        self.respond_json(user)
コード例 #5
0
  def testCopyLocalRules_NoPreviousHosts(self):
    old_user = test_utils.CreateUser(email=user_map.UsernameToEmail('foo'))
    new_user = test_utils.CreateUser(email=user_map.UsernameToEmail('bar'))

    test_utils.CreateBit9Host(
        id='12345', users=[old_user.nickname],
        policy_key=ndb.Key(bit9_db.Bit9Policy, '22222'))

    host = bit9_test_utils.CreateComputer(
        id=12345,
        policy_id=22222,
        users='{0}\\{1},{0}\\{2}'.format(
            settings.AD_DOMAIN, old_user.nickname, new_user.nickname))
    occurred_dt = datetime.datetime.utcnow()

    sync._PersistBit9Host(host, occurred_dt).wait()

    self.assertEntityCount(bit9_db.Bit9Rule, 0)
    self.assertEntityCount(bit9_db.RuleChangeSet, 0)
    self.assertTaskCount(constants.TASK_QUEUE.BQ_PERSISTENCE, 1)
    self.DrainTaskQueue(constants.TASK_QUEUE.BQ_PERSISTENCE)
    self.assertEntityCount(bigquery_db.HostRow, 1)
コード例 #6
0
  def testCopyLocalRules_Success(self):
    old_user = test_utils.CreateUser(email=user_map.UsernameToEmail('foo'))
    new_user = test_utils.CreateUser(email=user_map.UsernameToEmail('bar'))
    policy_key = ndb.Key(bit9_db.Bit9Policy, '22222')

    host1 = test_utils.CreateBit9Host(
        id='12345', users=[old_user.nickname], policy_key=policy_key)
    test_utils.CreateBit9Host(
        id='67890', users=[new_user.nickname], policy_key=policy_key)

    blockable1 = test_utils.CreateBit9Binary()
    test_utils.CreateBit9Rule(
        blockable1.key, host_id=host1.key.id(), user_key=old_user.key)
    blockable2 = test_utils.CreateBit9Binary()
    test_utils.CreateBit9Rule(
        blockable2.key, host_id=host1.key.id(), user_key=old_user.key)

    host = bit9_test_utils.CreateComputer(
        id=67890,
        policy_id=22222,
        users='{0}\\{1},{0}\\{2}'.format(
            settings.AD_DOMAIN, old_user.nickname, new_user.nickname))
    occurred_dt = datetime.datetime.utcnow()

    sync._PersistBit9Host(host, occurred_dt).wait()

    self.assertEntityCount(bit9_db.Bit9Rule, 4)  # 2 New + 2 Old
    self.assertEntityCount(bit9_db.RuleChangeSet, 2)
    rules_for_host1 = bit9_db.Bit9Rule.query(
        bit9_db.Bit9Rule.host_id == host1.key.id()).fetch()
    self.assertEqual(2, len(rules_for_host1))
    self.assertSameElements(
        [blockable1.key, blockable2.key],
        [rule.key.parent() for rule in rules_for_host1])
    self.assertTaskCount(constants.TASK_QUEUE.BQ_PERSISTENCE, 1)
    self.DrainTaskQueue(constants.TASK_QUEUE.BQ_PERSISTENCE)
    self.assertEntityCount(bigquery_db.HostRow, 1)
コード例 #7
0
ファイル: base.py プロジェクト: shaunstanislauslau/upvote
    def GetKeysToInsert(self, logged_in_users, host_owners):
        """Returns the list of keys with which this event should be inserted."""
        if settings.EVENT_CREATION == constants.EVENT_CREATION.EXECUTING_USER:
            if self.run_by_local_admin:
                usernames = logged_in_users
            else:
                usernames = [self.executing_user
                             ] if self.executing_user else []
        else:  # HOST_OWNERS
            usernames = host_owners

        emails = [user_map.UsernameToEmail(username) for username in usernames]

        keys = []
        for email in emails:
            key_pairs = [(User, email.lower()), (Host, self.host_id)]
            key_pairs += self.blockable_key.pairs()
            key_pairs += [(Event, '1')]
            keys.append(ndb.Key(pairs=key_pairs))
        return keys
コード例 #8
0
 def testUsernameToEmail(self):
     self.assertEqual('user@' + settings.USER_EMAIL_DOMAIN,
                      user_map.UsernameToEmail('user'))
コード例 #9
0
ファイル: sync.py プロジェクト: crudbug/upvote
def _PersistBit9Host(computer, occurred_dt):
    """Creates a Bit9Host from the Event protobuf if one does not already exist.

  NOTE: This function could be transactional but, at least for now, host puts in
  multiple requests don't really need to be processed in a fixed order.
  last_event_dt is the only frequently modified property and there's currently
  no need for it to be perfectly accurate.

  Args:
    computer: api.Computer object associated with the event.
    occurred_dt: datetime object corresponding to the time of the event.

  Returns:
    ndb.Future that resolves when the host is updated.
  """
    host_id = str(computer.id)
    policy = computer.policy_id
    policy_key = (ndb.Key(bit9.Bit9Policy, str(policy))
                  if policy is not None else None)
    hostname = bit9_utils.ExpandHostname(
        bit9_utils.StripDownLevelDomain(computer.name))
    policy_entity = policy_key.get()
    mode = (policy_entity.enforcement_level
            if policy_entity is not None else constants.HOST_MODE.UNKNOWN)

    # Grab the corresponding Bit9Host.
    bit9_host = yield bit9.Bit9Host.get_by_id_async(host_id)

    existing_users = set(bit9_host.users if bit9_host is not None else [])
    extracted_users = list(bit9_utils.ExtractHostUsers(computer.users))

    # Ignore any 'Desktop Window Manager' users, otherwise a user can temporarily
    # become disassociated with their machine. If they vote for something to be
    # locally whitelisted during such a period, they won't get a rule for it.
    incoming_users = set()
    for extracted_user in extracted_users:
        if r'Window Manager\DWM-' in extracted_user:
            logging.warning('Ignoring user "%s"', extracted_user)
        else:
            incoming_users.add(extracted_user)

    # If there are incoming users, either because it was only all 'Desktop Window
    # Manager' entries, or because Bit9 didn't report any users for whatever
    # reason, then just stick with the existing users, otherwise we'll
    # disassociate the machine from the user.
    if not incoming_users:
        incoming_users = existing_users

    # Perform initialization for users new to this host.
    new_users = incoming_users - existing_users
    for new_user in new_users:

        # Create User if we haven't seen this user before.
        email = user_map.UsernameToEmail(new_user)
        user = user_models.User.GetOrInsert(email_addr=email)

        # Copy the user's local rules over from a pre-existing host.
        yield _CopyLocalRules(user.key, host_id)

    # List of all row action that need to be persisted.
    row_actions = []

    # Doesn't exist? Guess we better fix that.
    if bit9_host is None:
        logging.info('Creating new Bit9Host')
        bit9_host = bit9.Bit9Host(id=host_id,
                                  hostname=hostname,
                                  last_event_dt=occurred_dt,
                                  policy_key=policy_key,
                                  users=sorted(list(incoming_users)))

        row_actions.append(constants.HOST_ACTION.FIRST_SEEN)

    else:
        changed = False

        if not bit9_host.last_event_dt or bit9_host.last_event_dt < occurred_dt:
            bit9_host.last_event_dt = occurred_dt
            changed = True

        if bit9_host.hostname != hostname:
            logging.info('Hostname for %s changed from %s to %s', host_id,
                         bit9_host.hostname, hostname)
            bit9_host.hostname = hostname
            changed = True

        if bit9_host.policy_key != policy_key:
            bit9_host.policy_key = policy_key
            changed = True
            row_actions.append(constants.HOST_ACTION.MODE_CHANGE)

        if existing_users != incoming_users:
            existing_users_list = sorted(list(existing_users))
            incoming_users_list = sorted(list(incoming_users))
            logging.info('Users for %s changed from %s to %s', host_id,
                         existing_users_list, incoming_users_list)
            bit9_host.users = incoming_users_list
            changed = True
            row_actions.append(constants.HOST_ACTION.USERS_CHANGE)

        if not changed:
            raise ndb.Return()

    logging.info('Attempting to put Bit9Host...')
    yield bit9_host.put_async()

    for action in row_actions:
        tables.HOST.InsertRow(device_id=host_id,
                              timestamp=(bit9_host.recorded_dt if action
                                         == constants.HOST_ACTION.FIRST_SEEN
                                         else bit9_host.last_event_dt),
                              action=action,
                              hostname=hostname,
                              platform=constants.PLATFORM.WINDOWS,
                              users=sorted(list(incoming_users)),
                              mode=mode)
コード例 #10
0
def RandomEmail():
    return user_map.UsernameToEmail('noreply+%s' % RandomLetters(8))
コード例 #11
0
ファイル: sync.py プロジェクト: shaunstanislauslau/upvote
  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(santa_const.PREFLIGHT.PRIMARY_USER)
    user = base_db.User.GetOrInsert(
        user_map.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:
      self.host = santa_db.SantaHost(key=self.host_key)
      self.host.client_mode = settings.SANTA_DEFAULT_CLIENT_MODE
      futures.append(self._CreateNewLocalRules(uuid, user.key))

    # Update host entity on every sync.
    self.host.serial_num = self.parsed_json.get(
        santa_const.PREFLIGHT.SERIAL_NUM)
    self.host.hostname = self.parsed_json.get(
        santa_const.PREFLIGHT.HOSTNAME)
    self.host.primary_user = primary_user
    self.host.santa_version = self.parsed_json.get(
        santa_const.PREFLIGHT.SANTA_VERSION)
    self.host.os_version = self.parsed_json.get(
        santa_const.PREFLIGHT.OS_VERSION)
    self.host.os_build = self.parsed_json.get(
        santa_const.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(santa_const.PREFLIGHT.CLIENT_MODE)
    if reported_mode != self.host.client_mode:
      msg = 'Client mode mismatch. Expected: %s. Actual: %s' % (
          self.host.client_mode, reported_mode)
      logging.info(msg)
      futures.append(base_db.AuditLog.CreateAsync(self.host, msg))

    if self.parsed_json.get(santa_const.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 = common_const.SANTA_CLIENT_MODE.MONITOR
    elif big_red_button.go_go_go:
      actual_client_mode = common_const.SANTA_CLIENT_MODE.LOCKDOWN

    # Prepare response.
    response = {
        santa_const.PREFLIGHT.BATCH_SIZE: (
            settings.SANTA_EVENT_BATCH_SIZE),
        santa_const.PREFLIGHT.CLIENT_MODE: actual_client_mode,
        santa_const.PREFLIGHT.WHITELIST_REGEX: (
            self.host.directory_whitelist_regex),
        santa_const.PREFLIGHT.BLACKLIST_REGEX: (
            self.host.directory_blacklist_regex),
        santa_const.PREFLIGHT.CLEAN_SYNC: not self.host.rule_sync_dt,
        santa_const.PREFLIGHT.BUNDLES_ENABLED: (
            settings.SANTA_BUNDLES_ENABLED),
    }

    if self.host.should_upload_logs:
      response[santa_const.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()
      bigquery.HostRow.DeferCreate(
          device_id=uuid,
          timestamp=new_host.recorded_dt,
          action=common_const.HOST_ACTION.FIRST_SEEN,
          hostname=new_host.hostname,
          platform=common_const.PLATFORM.MACOS,
          users=santa_db.SantaHost.GetAssociatedUsers(uuid),
          mode=new_host.client_mode)

    self.respond_json(response)
コード例 #12
0
ファイル: user_test.py プロジェクト: crudbug/upvote
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS-IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Unit tests for user.py."""

from upvote.gae.datastore import test_utils
from upvote.gae.datastore.models import user as user_models
from upvote.gae.lib.testing import basetest
from upvote.gae.shared.common import settings
from upvote.gae.shared.common import user_map
from upvote.shared import constants

_TEST_EMAIL = user_map.UsernameToEmail('testemail')

# Done for the sake of brevity.
USER = constants.USER_ROLE.USER
TRUSTED_USER = constants.USER_ROLE.TRUSTED_USER
ADMINISTRATOR = constants.USER_ROLE.ADMINISTRATOR


class UserTest(basetest.UpvoteTestCase):
    """Test User model."""
    def setUp(self):
        super(UserTest, self).setUp()
        self._voting_weights = settings.VOTING_WEIGHTS

        self.PatchEnv(settings.ProdEnv, ENABLE_BIGQUERY_STREAMING=True)
コード例 #13
0
 def testAdminGetUnknownUser(self):
     """Admin attempting to get information on an unknown user."""
     with self.LoggedInUser(admin=True):
         unknown_user = user_map.UsernameToEmail('blahblahblah')
         self.testapp.get('/' + unknown_user, status=httplib.NOT_FOUND)
コード例 #14
0
def _PersistBit9Host(computer, occurred_dt):
    """Creates a Bit9Host from the Event protobuf if one does not already exist.

  NOTE: This function could be transactional but, at least for now, host puts in
  multiple requests don't really need to be processed in a fixed order.
  last_event_dt is the only frequently modified property and there's currently
  no need for it to be perfectly accurate.

  Args:
    computer: api.Computer object associated with the event.
    occurred_dt: datetime object corresponding to the time of the event.

  Returns:
    ndb.Future that resolves when the host is updated.
  """
    host_id = str(computer.id)
    policy = computer.policy_id
    policy_key = (ndb.Key(bit9.Bit9Policy, str(policy))
                  if policy is not None else None)
    hostname = utils.ExpandHostname(
        rest_utils.StripDownLevelDomain(computer.name))
    policy_entity = policy_key.get()
    mode = (policy_entity.enforcement_level
            if policy_entity is not None else constants.HOST_MODE.UNKNOWN)

    # Grab the corresponding Bit9Host.
    bit9_host = yield bit9.Bit9Host.get_by_id_async(host_id)

    host_users = list(rest_utils.ExtractHostUsers(computer.users))

    # Perform initialization for users new to this host.
    existing_users = set(bit9_host.users if bit9_host is not None else [])
    new_host_users = set(host_users) - existing_users
    for username in new_host_users:
        # Create User if we haven't seen this user before.
        email = user_map.UsernameToEmail(username)
        user = base.User.GetOrInsert(email_addr=email)

        # Copy the user's local rules over from a pre-existing host.
        yield _CopyLocalRules(user.key, host_id)

    # List of all row action that need to be persisted.
    row_actions = []

    # Doesn't exist? Guess we better fix that.
    if bit9_host is None:
        logging.info('Creating new Bit9Host')
        bit9_host = bit9.Bit9Host(id=host_id,
                                  hostname=hostname,
                                  last_event_dt=occurred_dt,
                                  policy_key=policy_key,
                                  users=host_users)

        row_actions.append(constants.HOST_ACTION.FIRST_SEEN)

    else:
        changed = False
        if not bit9_host.last_event_dt or bit9_host.last_event_dt < occurred_dt:
            bit9_host.last_event_dt = occurred_dt
            changed = True
        if bit9_host.hostname != hostname:
            bit9_host.hostname = hostname
            changed = True
        if bit9_host.policy_key != policy_key:
            bit9_host.policy_key = policy_key
            changed = True
            row_actions.append(constants.HOST_ACTION.MODE_CHANGE)
        if set(bit9_host.users) != set(host_users):
            bit9_host.users = host_users
            changed = True
            row_actions.append(constants.HOST_ACTION.USERS_CHANGE)

        if not changed:
            raise ndb.Return()

    logging.info('Attempting to put Bit9Host...')
    yield bit9_host.put_async()

    for action in row_actions:
        bigquery.HostRow.DeferCreate(
            device_id=host_id,
            timestamp=(bit9_host.recorded_dt
                       if action == constants.HOST_ACTION.FIRST_SEEN else
                       bit9_host.last_event_dt),
            action=action,
            hostname=hostname,
            platform=constants.PLATFORM.WINDOWS,
            users=host_users,
            mode=mode)
コード例 #15
0
    def testGetKeysToInsert(self):
        keys = self.event_1.GetKeysToInsert(['foo', 'bar'], [])

        self.assertEqual(1, len(keys))
        expected_email = user_map.UsernameToEmail(self.event_1.executing_user)
        self.assertEqual(expected_email, keys[0].pairs()[0][1])