def test_find_changes_batch(self): """ This will test the entry point via the find_changes() method vs. the find_changes_batch() method. This will also use the IAMRole watcher, since that already has batching support. :return: """ from security_monkey.watchers.iam.iam_role import IAMRole self.setup_batch_db() watcher = IAMRole(accounts=[self.account.name]) watcher.current_account = (self.account, 0) watcher.technology = self.technology items = [] for x in range(0, 5): mod_conf = dict(ACTIVE_CONF) mod_conf["name"] = "SomeRole{}".format(x) mod_conf[ "Arn"] = "arn:aws:iam::012345678910:role/SomeRole{}".format(x) items.append(SomeTestItem().from_slurp( mod_conf, account_name=self.account.name)) assert len(watcher.find_changes(items)) == 5 # Try again -- audit_items should be 0 since nothing was changed: assert len(watcher.find_changes(items)) == 0
def test_find_changes_batch(self): """ This will test the entry point via the find_changes() method vs. the find_changes_batch() method. This will also use the IAMRole watcher, since that already has batching support. :return: """ from security_monkey.watchers.iam.iam_role import IAMRole self.setup_batch_db() watcher = IAMRole(accounts=[self.account.name]) watcher.current_account = (self.account, 0) watcher.technology = self.technology items = [] for x in range(0, 5): mod_conf = dict(ACTIVE_CONF) mod_conf["name"] = "SomeRole{}".format(x) mod_conf["Arn"] = "arn:aws:iam::012345678910:role/SomeRole{}".format(x) items.append(SomeTestItem().from_slurp(mod_conf, account_name=self.account.name)) assert len(watcher.find_changes(items)) == 5 # Try again -- audit_items should be 0 since nothing was changed: assert len(watcher.find_changes(items)) == 0
def test_ensure_item_has_latest_revision_id(self): """ Test that items always have a proper current revision set. Otherwise, the item needs to be deleted. :return: """ from security_monkey.watchers.iam.iam_role import IAMRole from security_monkey.watcher import ensure_item_has_latest_revision_id from security_monkey.datastore import Datastore # Stop the watcher registry from stepping on everyone's toes: import security_monkey.watcher old_watcher_registry = security_monkey.watcher.watcher_registry security_monkey.watcher.watcher_registry = {IAMRole.index: IAMRole} # Set everything up: self.setup_batch_db() watcher = IAMRole(accounts=[self.account.name]) watcher.current_account = (self.account, 0) watcher.technology = self.technology # Test case #1: Create an item in the DB that has no current revision ID: no_revision_item = Item(region="us-east-1", name="NOREVISION", account_id=self.account.id, tech_id=self.technology.id) db.session.add(no_revision_item) db.session.commit() assert db.session.query(Item).filter( Item.name == no_revision_item.name).one() # Should delete the item from the DB: result = ensure_item_has_latest_revision_id(no_revision_item) assert not result assert not db.session.query(Item).filter( Item.name == no_revision_item.name).first() # Test case #2: Create two item revisions for the given item, but don't attach them to the item. # After the fixer runs, it should return the item with proper hashes and a proper # link to the latest version. ds = Datastore() no_revision_item = Item(region="us-east-1", name="NOREVISION", account_id=self.account.id, tech_id=self.technology.id) db.session.add(no_revision_item) db.session.commit() ir_one = ItemRevision(config=ACTIVE_CONF, date_created=datetime.datetime.utcnow(), item_id=no_revision_item.id) ir_two = ItemRevision(config=ACTIVE_CONF, date_created=(datetime.datetime.utcnow() - timedelta(days=1)), item_id=no_revision_item.id) db.session.add(ir_one) db.session.add(ir_two) db.session.commit() assert len( db.session.query(ItemRevision).filter( ItemRevision.item_id == no_revision_item.id).all()) == 2 result = ensure_item_has_latest_revision_id(no_revision_item) assert result assert result.latest_revision_id == ir_one.id assert ds.hash_config( ACTIVE_CONF) == no_revision_item.latest_revision_complete_hash assert ds.durable_hash( ACTIVE_CONF, watcher.ephemeral_paths ) == no_revision_item.latest_revision_durable_hash # Undo the mock: security_monkey.watcher.watcher_registry = old_watcher_registry
def test_find_deleted_batch(self): """ This will use the IAMRole watcher, since that already has batching support. :return: """ from security_monkey.watchers.iam.iam_role import IAMRole self.setup_batch_db() # Set everything up: watcher = IAMRole(accounts=[self.account.name]) watcher.current_account = (self.account, 0) watcher.technology = self.technology items = [] for x in range(0, 5): mod_conf = dict(ACTIVE_CONF) mod_conf["name"] = "SomeRole{}".format(x) mod_conf[ "Arn"] = ARN_PREFIX + ":iam::012345678910:role/SomeRole{}".format( x) items.append(SomeTestItem().from_slurp( mod_conf, account_name=self.account.name)) mod_aspd = dict(ASPD) mod_aspd[ "Arn"] = ARN_PREFIX + ":iam::012345678910:role/SomeRole{}".format( x) mod_aspd["RoleName"] = "SomeRole{}".format(x) watcher.total_list.append(mod_aspd) watcher.find_changes(items) # Check for deleted items: watcher.find_deleted_batch({}) assert len(watcher.deleted_items) == 0 # Check that nothing was deleted: for x in range(0, 5): item_revision = ItemRevision.query.join( (Item, ItemRevision.id == Item.latest_revision_id)).filter( Item.arn == ARN_PREFIX + ":iam::012345678910:role/SomeRole{}".format(x), ).one() assert item_revision.active # Create some issues for testing purposes: db.session.add( ItemAudit(score=10, issue="IAM Role has full admin permissions.", notes=json.dumps(item_revision.config), item_id=item_revision.item_id)) db.session.add( ItemAudit(score=9001, issue="Some test issue", notes="{}", item_id=item_revision.item_id)) db.session.commit() assert len(ItemAudit.query.all()) == len(items) * 2 # Remove the last two items: removed_arns = [] removed_arns.append(watcher.total_list.pop()["Arn"]) removed_arns.append(watcher.total_list.pop()["Arn"]) # Check for deleted items again: watcher.find_deleted_batch({}) assert len(watcher.deleted_items) == 2 # Check that the last two items were deleted: for arn in removed_arns: item_revision = ItemRevision.query.join( (Item, ItemRevision.id == Item.latest_revision_id)).filter( Item.arn == arn, ).one() assert not item_revision.active # Check that the current ones weren't deleted: for current_item in watcher.total_list: item_revision = ItemRevision.query.join( (Item, ItemRevision.id == Item.latest_revision_id)).filter( Item.arn == current_item["Arn"], ).one() assert item_revision.active assert len( ItemAudit.query.filter( ItemAudit.item_id == item_revision.item_id).all()) == 2
def test_find_deleted_batch(self): """ This will use the IAMRole watcher, since that already has batching support. :return: """ from security_monkey.watchers.iam.iam_role import IAMRole self.setup_batch_db() # Set everything up: watcher = IAMRole(accounts=[self.account.name]) watcher.current_account = (self.account, 0) watcher.technology = self.technology items = [] for x in range(0, 5): mod_conf = dict(ACTIVE_CONF) mod_conf["name"] = "SomeRole{}".format(x) mod_conf["Arn"] = ARN_PREFIX + ":iam::012345678910:role/SomeRole{}".format(x) items.append(SomeTestItem().from_slurp(mod_conf, account_name=self.account.name)) mod_aspd = dict(ASPD) mod_aspd["Arn"] = ARN_PREFIX + ":iam::012345678910:role/SomeRole{}".format(x) mod_aspd["RoleName"] = "SomeRole{}".format(x) watcher.total_list.append(mod_aspd) watcher.find_changes(items) # Check for deleted items: watcher.find_deleted_batch({}) assert len(watcher.deleted_items) == 0 # Check that nothing was deleted: for x in range(0, 5): item_revision = ItemRevision.query.join((Item, ItemRevision.id == Item.latest_revision_id)).filter( Item.arn == ARN_PREFIX + ":iam::012345678910:role/SomeRole{}".format(x), ).one() assert item_revision.active # Create some issues for testing purposes: db.session.add(ItemAudit(score=10, issue="IAM Role has full admin permissions.", notes=json.dumps(item_revision.config), item_id=item_revision.item_id)) db.session.add(ItemAudit(score=9001, issue="Some test issue", notes="{}", item_id=item_revision.item_id)) db.session.commit() assert len(ItemAudit.query.all()) == len(items) * 2 # Remove the last two items: removed_arns = [] removed_arns.append(watcher.total_list.pop()["Arn"]) removed_arns.append(watcher.total_list.pop()["Arn"]) # Check for deleted items again: watcher.find_deleted_batch({}) assert len(watcher.deleted_items) == 2 # Check that the last two items were deleted: for arn in removed_arns: item_revision = ItemRevision.query.join((Item, ItemRevision.id == Item.latest_revision_id)).filter( Item.arn == arn, ).one() assert not item_revision.active # Check that the current ones weren't deleted: for current_item in watcher.total_list: item_revision = ItemRevision.query.join((Item, ItemRevision.id == Item.latest_revision_id)).filter( Item.arn == current_item["Arn"], ).one() assert item_revision.active assert len(ItemAudit.query.filter(ItemAudit.item_id == item_revision.item_id).all()) == 2
def test_ensure_item_has_latest_revision_id(self): """ Test that items always have a proper current revision set. Otherwise, the item needs to be deleted. :return: """ from security_monkey.watchers.iam.iam_role import IAMRole from security_monkey.watcher import ensure_item_has_latest_revision_id from security_monkey.datastore import Datastore # Stop the watcher registry from stepping on everyone's toes: import security_monkey.watcher old_watcher_registry = security_monkey.watcher.watcher_registry security_monkey.watcher.watcher_registry = {IAMRole.index: IAMRole} # Set everything up: self.setup_batch_db() watcher = IAMRole(accounts=[self.account.name]) watcher.current_account = (self.account, 0) watcher.technology = self.technology # Test case #1: Create an item in the DB that has no current revision ID: no_revision_item = Item(region="us-east-1", name="NOREVISION", account_id=self.account.id, tech_id=self.technology.id) db.session.add(no_revision_item) db.session.commit() assert db.session.query(Item).filter(Item.name == no_revision_item.name).one() # Should delete the item from the DB: result = ensure_item_has_latest_revision_id(no_revision_item) assert not result assert not db.session.query(Item).filter(Item.name == no_revision_item.name).first() # Test case #2: Create two item revisions for the given item, but don't attach them to the item. # After the fixer runs, it should return the item with proper hashes and a proper # link to the latest version. ds = Datastore() no_revision_item = Item(region="us-east-1", name="NOREVISION", account_id=self.account.id, tech_id=self.technology.id) db.session.add(no_revision_item) db.session.commit() ir_one = ItemRevision(config=ACTIVE_CONF, date_created=datetime.datetime.utcnow(), item_id=no_revision_item.id) ir_two = ItemRevision(config=ACTIVE_CONF, date_created=(datetime.datetime.utcnow() - timedelta(days=1)), item_id=no_revision_item.id) db.session.add(ir_one) db.session.add(ir_two) db.session.commit() assert len(db.session.query(ItemRevision).filter(ItemRevision.item_id == no_revision_item.id).all()) == 2 result = ensure_item_has_latest_revision_id(no_revision_item) assert result assert result.latest_revision_id == ir_one.id assert ds.hash_config(ACTIVE_CONF) == no_revision_item.latest_revision_complete_hash assert ds.durable_hash(ACTIVE_CONF, watcher.ephemeral_paths) == no_revision_item.latest_revision_durable_hash # Undo the mock: security_monkey.watcher.watcher_registry = old_watcher_registry