def setUp(self): super(CommitBlockableChangeSetTest, self).setUp() self.binary = test_utils.CreateBit9Binary(file_catalog_id='1234') self.local_rule = test_utils.CreateBit9Rule(self.binary.key, host_id='5678') self.global_rule = test_utils.CreateBit9Rule(self.binary.key)
def testUnfulfilled(self): self.Patch(change_set, 'DeferCommitBlockableChangeSet') bit9_binary = test_utils.CreateBit9Binary() now = datetime.datetime.utcnow() # Create some conflicting Bit9Rules. rule1 = test_utils.CreateBit9Rule( bit9_binary.key, is_committed=True, is_fulfilled=False, host_id='12345', updated_dt=now - datetime.timedelta(hours=3), policy=constants.RULE_POLICY.WHITELIST) rule2 = test_utils.CreateBit9Rule( bit9_binary.key, is_committed=True, is_fulfilled=False, host_id='12345', updated_dt=now - datetime.timedelta(hours=2), policy=constants.RULE_POLICY.WHITELIST) rule3 = test_utils.CreateBit9Rule( bit9_binary.key, is_committed=True, is_fulfilled=False, host_id='12345', updated_dt=now - datetime.timedelta(hours=1), policy=constants.RULE_POLICY.BLACKLIST) # Verify a RuleChangeSet doesn't yet exist. self.assertEntityCount(bit9_models.RuleChangeSet, 0) result = sync._CheckAndResolveAnomalousBlock(bit9_binary.key, '12345') self.assertTrue(result) # Verify that all Rules except the most recent have been fulfilled. self.assertTrue(rule1.key.get().is_fulfilled) self.assertTrue(rule2.key.get().is_fulfilled) self.assertFalse(rule3.key.get().is_fulfilled) # Verify that the most recent Rule is uncommitted. self.assertTrue(rule1.key.get().is_committed) self.assertTrue(rule2.key.get().is_committed) self.assertFalse(rule3.key.get().is_committed) # Verify the creation of a RuleChangeSet. self.assertEntityCount(bit9_models.RuleChangeSet, 1) # Verify the deferred commit to Bit9. self.assertTrue(change_set.DeferCommitBlockableChangeSet.called)
def testWhitelist_GlobalRule_Certificate(self): cert = test_utils.CreateBit9Certificate(id='1a2b') global_rule = test_utils.CreateBit9Rule(cert.key, host_id='') change = test_utils.CreateRuleChangeSet( cert.key, rule_keys=[global_rule.key], change_type=constants.RULE_POLICY.WHITELIST) api_cert = api.Certificate(id=9012, thumbprint='1a2b', certificate_state=1) self.PatchApiRequests([api_cert], api_cert) change_set._CommitBlockableChangeSet(cert.key) self.mock_ctx.ExecuteRequest.assert_has_calls([ mock.call('GET', api_route='certificate', query_args=['q=thumbprint:1a2b']), mock.call('POST', api_route='certificate', data={ 'id': 9012, 'thumbprint': '1a2b', 'certificateState': 2 }, query_args=None) ]) self.assertTrue(global_rule.key.get().is_committed) self.assertIsNone(change.key.get())
def testWhitelist_NoEvent(self): binary = test_utils.CreateBit9Binary(file_catalog_id='1111') user = test_utils.CreateUser() local_rule = test_utils.CreateBit9Rule( binary.key, host_id='2222', user_key=user.key, policy=constants.RULE_POLICY.WHITELIST, is_fulfilled=False) # Mock out the Bit9 API interactions. file_instance = api.FileInstance( id=3333, file_catalog_id=1111, computer_id=2222, local_state=bit9_constants.APPROVAL_STATE.UNAPPROVED) self.PatchApiRequests([file_instance], file_instance) change_set.ChangeLocalState( binary, local_rule, bit9_constants.APPROVAL_STATE.APPROVED) # Verify the Bit9 API interactions. self.mock_ctx.ExecuteRequest.assert_has_calls([ mock.call( 'GET', api_route='fileInstance', query_args=[r'q=computerId:2222', 'q=fileCatalogId:1111']), mock.call( 'POST', api_route='fileInstance', data={'id': 3333, 'localState': 2, 'fileCatalogId': 1111, 'computerId': 2222}, query_args=None)]) self.assertTrue(local_rule.key.get().is_fulfilled) self.assertBigQueryInsertion(constants.BIGQUERY_TABLE.RULE)
def testCalculateInstallerState(self): self.bit9_binary.detected_installer = False self.bit9_binary.put() test_utils.CreateBit9Rule(self.bit9_binary.key, in_effect=True, policy=constants.RULE_POLICY.FORCE_INSTALLER) self.assertTrue(self.bit9_binary.CalculateInstallerState())
def testRemove_MixedRules(self): other_local_rule = test_utils.CreateBit9Rule( self.binary.key, host_id='9012') change = test_utils.CreateRuleChangeSet( self.binary.key, rule_keys=[ self.local_rule.key, other_local_rule.key, self.global_rule.key], change_type=constants.RULE_POLICY.REMOVE) fi1 = api.FileInstance( id=9012, file_catalog_id=int(self.binary.file_catalog_id), computer_id=int(self.local_rule.host_id), local_state=bit9_constants.APPROVAL_STATE.APPROVED) fi2 = api.FileInstance( id=9012, file_catalog_id=int(self.binary.file_catalog_id), computer_id=int(other_local_rule.host_id), local_state=bit9_constants.APPROVAL_STATE.APPROVED) rule = api.FileRule( file_catalog_id=1234, file_state=bit9_constants.APPROVAL_STATE.APPROVED) self.PatchApiRequests([fi1], fi1, [fi2], fi2, rule) change_set._CommitBlockableChangeSet(self.binary.key) self.mock_ctx.ExecuteRequest.assert_has_calls([ mock.call( 'GET', api_route='fileInstance', query_args=[r'q=computerId:5678', 'q=fileCatalogId:1234']), mock.call( 'POST', api_route='fileInstance', data={'id': 9012, 'localState': 1, 'fileCatalogId': 1234, 'computerId': 5678}, query_args=None), mock.call( 'GET', api_route='fileInstance', query_args=[r'q=computerId:9012', 'q=fileCatalogId:1234']), mock.call( 'POST', api_route='fileInstance', data={'id': 9012, 'localState': 1, 'fileCatalogId': 1234, 'computerId': 9012}, query_args=None), mock.call( 'POST', api_route='fileRule', data={'fileCatalogId': 1234, 'fileState': 1}, query_args=None), ]) self.assertTrue(self.local_rule.key.get().is_fulfilled) self.assertTrue(self.local_rule.key.get().is_committed) self.assertTrue(other_local_rule.key.get().is_fulfilled) self.assertTrue(other_local_rule.key.get().is_committed) self.assertTrue(self.global_rule.key.get().is_committed) self.assertIsNone(change.key.get()) self.assertBigQueryInsertions([constants.BIGQUERY_TABLE.RULE] * 2)
def testSuccess(self): binary_count = 10 # Create a user and some corresponding Bit9Hosts. user = test_utils.CreateUser() host_1 = test_utils.CreateBit9Host(id='1111', users=[user.nickname]) host_2 = test_utils.CreateBit9Host(id='2222', users=[user.nickname]) host_3 = test_utils.CreateBit9Host(id='3333', users=[user.nickname]) # Create some Bit9Binaries, each with a Bit9Rule for host_1 and host_2. binaries = test_utils.CreateBit9Binaries(binary_count) for binary in binaries: test_utils.CreateBit9Rule( binary.key, host_id=host_1.key.id(), user_key=user.key, in_effect=True) test_utils.CreateBit9Rule( binary.key, host_id=host_2.key.id(), user_key=user.key, in_effect=True) # Verify all the rule counts. self.assertEntityCount(bit9_models.Bit9Rule, binary_count * 2) host_1_rules = bit9_models.Bit9Rule.query( bit9_models.Bit9Rule.host_id == host_1.key.id()).fetch() self.assertEqual(binary_count, len(host_1_rules)) host_2_rules = bit9_models.Bit9Rule.query( bit9_models.Bit9Rule.host_id == host_2.key.id()).fetch() self.assertEqual(binary_count, len(host_2_rules)) host_3_rules = bit9_models.Bit9Rule.query( bit9_models.Bit9Rule.host_id == host_3.key.id()).fetch() self.assertEqual(0, len(host_3_rules)) sync._CopyLocalRules(user.key, host_3.key.id()).get_result() # Verify all the rule counts again. self.assertEntityCount(bit9_models.Bit9Rule, binary_count * 3) host_1_rules = bit9_models.Bit9Rule.query( bit9_models.Bit9Rule.host_id == host_1.key.id()).fetch() self.assertEqual(binary_count, len(host_1_rules)) host_2_rules = bit9_models.Bit9Rule.query( bit9_models.Bit9Rule.host_id == host_2.key.id()).fetch() self.assertEqual(binary_count, len(host_2_rules)) host_3_rules = bit9_models.Bit9Rule.query( bit9_models.Bit9Rule.host_id == host_3.key.id()).fetch() self.assertEqual(binary_count, len(host_3_rules))
def setUp(self): super(DeferCommitBlockableChangeSetTest, self).setUp() self.binary = test_utils.CreateBit9Binary(file_catalog_id='1234') self.local_rule = test_utils.CreateBit9Rule(self.binary.key, host_id='5678') self.change = test_utils.CreateRuleChangeSet( self.binary.key, rule_keys=[self.local_rule.key], change_type=constants.RULE_POLICY.WHITELIST)
def testBlacklist_GlobalRule_Multiple(self): other_global_rule = test_utils.CreateBit9Rule(self.binary.key) test_utils.CreateRuleChangeSet( self.binary.key, rule_keys=[self.global_rule.key, other_global_rule.key], change_type=constants.RULE_POLICY.BLACKLIST) with self.assertRaises(deferred.PermanentTaskFailure): change_set._CommitBlockableChangeSet(self.binary.key)
def testGet_CaseInsensitiveID(self): test_utils.CreateBit9Rule(self.bit9_blockable.key, is_committed=False, policy=constants.RULE_POLICY.FORCE_INSTALLER) sha256 = self.bit9_blockable.key.id() with self.LoggedInUser(): self.testapp.get(self.ROUTE % sha256.lower(), status=httplib.OK) self.testapp.get(self.ROUTE % sha256.upper(), status=httplib.OK)
def testPendingGlobalRule(self): test_utils.CreateBit9Rule(self.bit9_blockable.key, host_id='', is_committed=False) with self.LoggedInUser(): response = self.testapp.get('/%s' % self.bit9_blockable.key.id()) output = response.json self.assertTrue(output)
def testPendingNonInstallerRule(self): test_utils.CreateBit9Rule(self.bit9_blockable.key, is_committed=False, policy=constants.RULE_POLICY.WHITELIST) with self.LoggedInUser(): response = self.testapp.get('/%s' % self.bit9_blockable.key.id()) output = response.json self.assertFalse(output)
def testGet_CaseInsensitiveID(self): test_utils.CreateBit9Rule(self.bit9_blockable.key, host_id='', is_committed=False) sha256 = self.bit9_blockable.key.id() with self.LoggedInUser(): self.testapp.get(self.ROUTE % sha256.lower(), status=httplib.OK) self.testapp.get(self.ROUTE % sha256.upper(), status=httplib.OK)
def testPendingGlobalRule_InstallerRule(self): test_utils.CreateBit9Rule(self.bit9_blockable.key, host_id='', policy=constants.RULE_POLICY.FORCE_INSTALLER, is_committed=False) with self.LoggedInUser(): response = self.testapp.get('/%s' % self.bit9_blockable.key.id()) output = response.json self.assertFalse(output)
def testGet_PendingInstallerRule(self): test_utils.CreateBit9Rule(self.bit9_blockable.key, is_committed=False, policy=constants.RULE_POLICY.FORCE_INSTALLER) with self.LoggedInUser(): response = self.testapp.get(self.ROUTE % self.bit9_blockable.key.id()) output = response.json self.assertTrue(output)
def testPendingLocalRule_ForUser(self): with self.LoggedInUser() as user: bit9_host = test_utils.CreateBit9Host(users=[user.nickname]) test_utils.CreateBit9Rule(self.bit9_blockable.key, host_id=bit9_host.key.id(), user_key=user.key, is_committed=False) response = self.testapp.get('/%s' % self.bit9_blockable.key.id()) output = response.json self.assertTrue(output)
def testGet_PendingDisabledRule(self): test_utils.CreateBit9Rule(self.bit9_blockable.key, host_id='', is_committed=False, in_effect=False) with self.LoggedInUser(): response = self.testapp.get(self.ROUTE % self.bit9_blockable.key.id()) output = response.json self.assertFalse(output)
def testLatencyRecorded_NonWhitelist(self, mock_change_local_state, mock_metric): binary = test_utils.CreateBit9Binary(file_catalog_id='1234') local_rule = test_utils.CreateBit9Rule( binary.key, host_id='12345', policy=constants.RULE_POLICY.FORCE_INSTALLER) change_set._ChangeLocalStates(binary, [local_rule], bit9_constants.APPROVAL_STATE.APPROVED) self.assertFalse(mock_metric.Record.called)
def testWhitelist_HasEvent(self): binary = test_utils.CreateBit9Binary(file_catalog_id='1111') user = test_utils.CreateUser() local_rule = test_utils.CreateBit9Rule( binary.key, host_id='2222', user_key=user.key, policy=constants.RULE_POLICY.WHITELIST, is_fulfilled=False) # Create a Bit9Event corresponding to the Bit9Rule. pairs = [('User', user.email), ('Host', '2222'), ('Blockable', binary.key.id()), ('Event', '1')] event_key = ndb.Key(pairs=pairs) first_blocked_dt = datetime.datetime.utcnow() - datetime.timedelta( hours=3) test_utils.CreateBit9Event(binary, key=event_key, first_blocked_dt=first_blocked_dt) # Mock out the Bit9 API interactions. file_instance = api.FileInstance( id=3333, file_catalog_id=1111, computer_id=2222, local_state=bit9_constants.APPROVAL_STATE.UNAPPROVED) self.PatchApiRequests([file_instance], file_instance) change_set.ChangeLocalState(binary, local_rule, bit9_constants.APPROVAL_STATE.APPROVED) # Verify the Bit9 API interactions. self.mock_ctx.ExecuteRequest.assert_has_calls([ mock.call( 'GET', api_route='fileInstance', query_args=[r'q=computerId:2222', 'q=fileCatalogId:1111']), mock.call('POST', api_route='fileInstance', data={ 'id': 3333, 'localState': 2, 'fileCatalogId': 1111, 'computerId': 2222 }, query_args=None) ]) self.assertTrue(local_rule.key.get().is_fulfilled) self.assertBigQueryInsertion(constants.BIGQUERY_TABLE.RULE)
def testWhitelist_LocalRule_Certificate(self): cert = test_utils.CreateBit9Certificate() local_rule = test_utils.CreateBit9Rule(cert.key, host_id='5678') change = test_utils.CreateRuleChangeSet( cert.key, rule_keys=[local_rule.key], change_type=constants.RULE_POLICY.WHITELIST) change_set._CommitBlockableChangeSet(cert.key) self.assertIsNotNone(self.local_rule.key.get().is_fulfilled) self.assertFalse(local_rule.key.get().is_fulfilled) self.assertTrue(local_rule.key.get().is_committed) self.assertIsNone(change.key.get())
def testGet_PendingLocalRule_ForSomeoneElse(self): other_user = test_utils.CreateUser() with self.LoggedInUser(): bit9_host = test_utils.CreateBit9Host(users=[other_user.nickname]) test_utils.CreateBit9Rule(self.bit9_blockable.key, host_id=bit9_host.key.id(), user_key=other_user.key, is_committed=False) response = self.testapp.get(self.ROUTE % self.bit9_blockable.key.id()) output = response.json self.assertFalse(output)
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)
def setUp(self): super(CommitBlockableChangeSetTest, self).setUp() # Set up a fake Bit9ApiAuth entity in Datastore. os.environ['GOOGLE_APPLICATION_CREDENTIALS'] = os.path.join( absltest.get_default_test_srcdir(), 'upvote/gae/modules/bit9_api', 'fake_credentials.json') self.Patch(change_set.bit9_utils.bit9.kms_ndb.EncryptedBlobProperty, '_Encrypt', return_value='blah') self.Patch(change_set.bit9_utils.bit9.kms_ndb.EncryptedBlobProperty, '_Decrypt', return_value='blah') bit9.Bit9ApiAuth.SetInstance(api_key='blah') self.mock_ctx = mock.Mock(spec=change_set.bit9_utils.api.Context) self.Patch(change_set.bit9_utils.api, 'Context', return_value=self.mock_ctx) self.binary = test_utils.CreateBit9Binary(file_catalog_id='1234') self.local_rule = test_utils.CreateBit9Rule(self.binary.key, host_id='5678') self.global_rule = test_utils.CreateBit9Rule(self.binary.key)
def testNoFileInstances(self): binary = test_utils.CreateBit9Binary(file_catalog_id='1111') user = test_utils.CreateUser() local_rule = test_utils.CreateBit9Rule( binary.key, host_id='2222', user_key=user.key, policy=constants.RULE_POLICY.WHITELIST, is_fulfilled=False) # Simulate getting no fileInstances from Bit9. self.PatchApiRequests([]) change_set.ChangeLocalState( binary, local_rule, bit9_constants.APPROVAL_STATE.APPROVED) self.assertFalse(local_rule.key.get().is_fulfilled) self.assertNoBigQueryInsertions()
def testPost_SameStateAsPreexistingRule(self): test_utils.CreateBit9Rule(self.bit9_blockable.key, policy=constants.RULE_POLICY.FORCE_INSTALLER) self.bit9_blockable.is_installer = True self.bit9_blockable.put() with self.LoggedInUser(): response = self.testapp.post( self.ROUTE % self.bit9_blockable.key.id(), {'value': True}) output = response.json self.assertTrue(output) self.assertEntityCount(rule_models.Bit9Rule, 1) self.assertEntityCount(bit9.RuleChangeSet, 0) self.assertTrue(self.bit9_blockable.key.get().is_installer) self.assertTaskCount(constants.TASK_QUEUE.BIT9_COMMIT_CHANGE, 0)
def testPost_PreexistingRule(self): test_utils.CreateBit9Rule(self.bit9_blockable.key, policy=constants.RULE_POLICY.FORCE_INSTALLER) self.bit9_blockable.is_installer = True self.bit9_blockable.put() with self.LoggedInUser(): response = self.testapp.post( self.ROUTE % self.bit9_blockable.key.id(), {'value': False}) output = response.json self.assertFalse(output) self.assertEntityCount(bit9.Bit9Rule, 2) self.assertEntityCount(bit9.RuleChangeSet, 1) self.assertBigQueryInsertions([constants.BIGQUERY_TABLE.BINARY]) self.assertFalse(self.bit9_blockable.key.get().is_installer) self.assertTaskCount(constants.TASK_QUEUE.BIT9_COMMIT_CHANGE, 1)
def testPreexistingRule(self): test_utils.CreateBit9Rule(self.bit9_blockable.key, policy=constants.RULE_POLICY.FORCE_INSTALLER) self.bit9_blockable.is_installer = True self.bit9_blockable.put() with self.LoggedInUser(): response = self.testapp.post('/%s' % self.bit9_blockable.key.id(), {'value': False}) output = response.json self.assertFalse(output) self.assertEntityCount(bit9.Bit9Rule, 2) self.assertEntityCount(bit9.RuleChangeSet, 1) self.assertEntityCount(base.AuditLog, 1, ancestor=self.bit9_blockable.key) self.assertFalse(self.bit9_blockable.key.get().is_installer) self.assertTaskCount(constants.TASK_QUEUE.BIT9_COMMIT_CHANGE, 1)
def testForcedInstaller_PreexistingRule_ConflictingPolicy(self): bit9_binary = test_utils.CreateBit9Binary( detected_installer=False, is_installer=False) test_utils.CreateBit9Rule( bit9_binary.key, is_committed=True, policy=constants.RULE_POLICY.FORCE_NOT_INSTALLER) file_catalog_kwargs = { 'id': bit9_binary.file_catalog_id, 'sha256': bit9_binary.key.id(), 'file_flags': bit9_constants.FileFlags.MARKED_INSTALLER} event, cert = _CreateEventAndCert(file_catalog_kwargs=file_catalog_kwargs) file_catalog = event.get_expand(api.Event.file_catalog_id) changed = sync._PersistBit9Binary( event, file_catalog, [cert]).get_result() self.assertTrue(changed) self.assertTrue(bit9_binary.key.get().is_installer) # Empty because Binary is not new and State is not BANNED. self.assertNoBigQueryInsertions()
def testForcedInstaller_PreexistingRule_ConflictingPolicy(self): bit9_binary = test_utils.CreateBit9Binary( detected_installer=False, is_installer=False) test_utils.CreateBit9Rule( bit9_binary.key, is_committed=True, policy=constants.RULE_POLICY.FORCE_NOT_INSTALLER) event, signing_chain = _CreateEventTuple( file_catalog=bit9_test_utils.CreateFileCatalog( id=bit9_binary.file_catalog_id, sha256=bit9_binary.key.id(), file_flags=bit9_constants.FileFlags.MARKED_INSTALLER)) file_catalog = event.get_expand(api.Event.file_catalog_id) changed = sync._PersistBit9Binary( event, file_catalog, signing_chain).get_result() self.assertTrue(changed) self.assertTrue(bit9_binary.key.get().is_installer) # Empty because Binary is not new and State is not BANNED. self.assertTaskCount(constants.TASK_QUEUE.BQ_PERSISTENCE, 0)