def _setup_one_two_revisions(self): account_type_result = AccountType.query.filter(AccountType.name == 'AWS').first() if not account_type_result: account_type_result = AccountType(name='AWS') db.session.add(account_type_result) db.session.commit() account = Account(number="012345678910", name="testing", s3_name="testing", role_name="SecurityMonkey", account_type_id=account_type_result.id) technology = Technology(name="iamrole") item = Item(region="us-west-2", name="testrole", arn="arn:aws:iam::012345678910:role/testrole", technology=technology, account=account) self.now = datetime(2016, 11, 3) self.yesterday = self.now - timedelta(days=1) item.revisions.append(ItemRevision(active=True, config={}, date_created=self.now)) item.revisions.append(ItemRevision(active=True, config={}, date_created=self.yesterday)) db.session.add(account) db.session.add(technology) db.session.add(item) db.session.commit() items = Item.query.all() for item in items: latest_revision = item.revisions.first() item.latest_revision_id = latest_revision.id db.session.add(item) db.session.commit()
def fix_orphaned_deletions(account_name, technology_name): """ Possible issue with orphaned items. This will check if there are any, and will assume that the item was deleted. This will create a deletion change record to it. :param account_name: :param technology_name: :return: """ # If technology doesn't exist, then create it: technology = Technology.query.filter( Technology.name == technology_name).first() if not technology: technology = Technology(name=technology_name) db.session.add(technology) db.session.commit() app.logger.info("Technology: {} did not exist... created it...".format( technology_name)) account = Account.query.filter(Account.name == account_name).one() # Query for orphaned items of the given technology/account pair: orphaned_items = Item.query.filter( Item.account_id == account.id, Item.tech_id == technology.id, Item.latest_revision_id == None).all() # noqa if not orphaned_items: app.logger.info( "[@] No orphaned items have been found. (This is good)") return # Fix the orphaned items: for oi in orphaned_items: app.logger.error( "[?] Found an orphaned item: {}. Creating a deletion record for it" .format(oi.name)) revision = ItemRevision(active=False, config={}) oi.revisions.append(revision) db.session.add(revision) db.session.add(oi) db.session.commit() # Update the latest revision id: db.session.refresh(revision) oi.latest_revision_id = revision.id db.session.add(oi) db.session.commit() app.logger.info("[-] Created deletion record for item: {}.".format( oi.name))
def test_save_issues(self): item = Item(region="us-west-2", name="testitem", technology=self.technology, account=self.test_account) revision = ItemRevision(item=item, config={}, active=True) item_audit = ItemAudit(item=item, issue="test issue") db.session.add(item) db.session.add(revision) db.session.add(item_audit) db.session.commit() auditor = Auditor(accounts=[self.test_account.name]) auditor.index = self.technology.name auditor.i_am_singular = self.technology.name auditor.items = auditor.read_previous_items() auditor.audit_objects() try: auditor.save_issues() except AttributeError as e: self.fail( "Auditor.save_issues() raised AttributeError unexpectedly: {}". format(e.message))
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 create_revision(config, db_item): return ItemRevision( active=is_active(config), config=config, item_id=db_item.id, )