Exemplo n.º 1
0
def _PersistBit9Events(event, file_catalog, computer, signing_chain):
    """Creates a Bit9Event from the given Event protobuf.

  Args:
    event: The api.Event instance to be synced to Upvote.
    file_catalog: The api.FileCatalog instance associated with this event.
    computer: The api.Computer instance associated with this event.
    signing_chain: List of api.Certificate instances associated with this event.

  Returns:
    An ndb.Future that resolves when all events are created.
  """
    logging.info('Creating new Bit9Event')

    host_id = str(computer.id)
    blockable_key = ndb.Key(bit9.Bit9Binary, file_catalog.sha256)
    host_users = list(rest_utils.ExtractHostUsers(computer.users))
    occurred_dt = event.timestamp

    is_anomalous = _CheckAndResolveAnomalousBlock(blockable_key, host_id)

    new_event = bit9.Bit9Event(blockable_key=blockable_key,
                               cert_key=_GetCertKey(signing_chain),
                               event_type=constants.EVENT_TYPE.BLOCK_BINARY,
                               last_blocked_dt=occurred_dt,
                               first_blocked_dt=occurred_dt,
                               host_id=host_id,
                               file_name=event.file_name,
                               file_path=event.path_name,
                               publisher=file_catalog.publisher,
                               version=file_catalog.product_version,
                               description=event.description,
                               executing_user=rest_utils.ExtractHostUser(
                                   event.user_name),
                               is_anomalous=is_anomalous,
                               bit9_id=event.id)

    bigquery.ExecutionRow.DeferCreate(sha256=new_event.blockable_key.id(),
                                      device_id=host_id,
                                      timestamp=occurred_dt,
                                      platform=new_event.GetPlatformName(),
                                      client=new_event.GetClientName(),
                                      file_path=new_event.file_path,
                                      file_name=new_event.file_name,
                                      executing_user=new_event.executing_user,
                                      associated_users=host_users,
                                      decision=new_event.event_type)

    keys_to_insert = new_event.GetKeysToInsert(host_users, host_users)

    futures = [_PersistBit9Event(new_event, key) for key in keys_to_insert]
    return model_utils.GetMultiFuture(futures)
Exemplo n.º 2
0
def _GetAssociatedHosts(username):
    """Gets all hosts associated with the provided user."""
    queries = (
        r'*{0}\\{lower}',  # Normal user at list end.
        r'*{0}\\{lower},*',
    )  # Normal user in list middle.
    host_user_query = '|'.join(queries).format(
        settings.AD_DOMAIN,
        lower=username.lower(),
    )
    hosts = (api.Computer.query().filter(
        api.Computer.users == host_user_query).execute(utils.CONTEXT))

    return [
        host for host in hosts
        if username in rest_utils.ExtractHostUsers(host.users)
    ]
Exemplo n.º 3
0
    def get(self, user_id):
        user = base_db.User.GetById(user_id)
        if user is None:
            logging.warning('Unknown user ID: %s', user_id)
            self.abort(httplib.NOT_FOUND)

        bit9_hosts = _GetAssociatedHosts(user.nickname)
        ids = [str(host.id) for host in bit9_hosts]

        # Get Host datastore entities corresponding to the IDs retrieved.
        gae_hosts = ndb.get_multi(
            ndb.Key(bit9_db.Bit9Host, id_) for id_ in ids)
        hosts_to_put = []
        for gae_host, bit9_host in zip(gae_hosts, bit9_hosts):
            policy_key = (ndb.Key(bit9_db.Bit9Policy, str(bit9_host.policy_id))
                          if bit9_host.policy_id is not None else None)
            changed = False
            if gae_host is None:
                # If the host doesn't exist, create it.
                hostname = utils.ExpandHostname(
                    rest_utils.StripDownLevelDomain(bit9_host.name))
                gae_host = bit9_db.Bit9Host(id=str(bit9_host.id),
                                            hostname=hostname,
                                            last_event_dt=None,
                                            policy_key=policy_key,
                                            users=rest_utils.ExtractHostUsers(
                                                bit9_host.users))
                changed = True
            else:
                # If the host does exist, update any changed fields.
                if gae_host.policy_key != policy_key:
                    gae_host.policy_key = policy_key
                    changed = True
                if set(gae_host.users) != set(bit9_host.users):
                    gae_host.users = bit9_host.users
                    changed = True

            if changed:
                hosts_to_put.append(gae_host)

        if hosts_to_put:
            logging.info('Updating %s Bit9Hosts...', len(hosts_to_put))
            ndb.put_multi(hosts_to_put)

        self.respond_json(ids)
Exemplo n.º 4
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)
Exemplo n.º 5
0
 def testExtractHostUsers_MixedCase(self):
   user_str = r'HOST\user,{0}\USer'.format(settings.AD_DOMAIN)
   expected = [r'HOST\user', r'user']
   actual = rest_utils.ExtractHostUsers(user_str)
   self.assertEqual(expected, actual)
Exemplo n.º 6
0
 def testExtractHostUsers_Skip(self):
   user_str = r'HOST\user,{0}\user,HOST\skipuser$,{0}\skipuser$'.format(
       settings.AD_DOMAIN)
   expected = [r'HOST\user', r'user']
   actual = rest_utils.ExtractHostUsers(user_str)
   self.assertEqual(expected, actual)
Exemplo n.º 7
0
 def testExtractHostUsers_None(self):
   self.assertEqual([], rest_utils.ExtractHostUsers(None))
Exemplo n.º 8
0
 def testExtractHostUsers_Empty(self):
   self.assertEqual([], rest_utils.ExtractHostUsers(''))