<s> """<STR_LIT>""" <EOL> import datastore <EOL> from security_monkey import app , db <EOL> from security_monkey . watcher import ChangeItem <EOL> from security_monkey . common . jinja import get_jinja_env <EOL> from security_monkey . datastore import User , AuditorSettings , Item , ItemAudit , Technology , Account <EOL> from security_monkey . common . utils import send_email <EOL> from sqlalchemy import and_ <EOL> class Auditor ( object ) : <EOL> """<STR_LIT>""" <EOL> index = None <EOL> i_am_singular = None <EOL> i_am_plural = None <EOL> def __init__ ( self , accounts = None , debug = False ) : <EOL> self . datastore = datastore . Datastore ( ) <EOL> self . accounts = accounts <EOL> self . debug = debug <EOL> self . items = [ ] <EOL> self . team_emails = app . config . get ( '<STR_LIT>' , [ ] ) <EOL> self . emails = [ ] <EOL> if type ( self . team_emails ) in ( str , unicode ) : <EOL> self . emails . append ( self . team_emails ) <EOL> elif type ( self . team_emails ) in ( list , tuple ) : <EOL> self . emails . extend ( self . team_emails ) <EOL> else : <EOL> app . logger . info ( "<STR_LIT>" ) <EOL> for account in self . accounts : <EOL> users = User . query . filter ( User . daily_audit_email == True ) . filter ( User . accounts . any ( name = account ) ) . all ( ) <EOL> self . emails . extend ( [ user . email for user in users ] ) <EOL> def add_issue ( self , score , issue , item , notes = None ) : <EOL> """<STR_LIT>""" <EOL> if notes and len ( notes ) > <NUM_LIT> : <EOL> notes = notes [ <NUM_LIT:0> : <NUM_LIT> ] <EOL> for existing_issue in item . audit_issues : <EOL> if existing_issue . issue == issue : <EOL> if existing_issue . notes == notes : <EOL> if existing_issue . score == score : <EOL> app . logger . debug ( <EOL> "<STR_LIT>" <EOL> . format ( item . index , item . region , item . account , item . name , issue , notes ) ) <EOL> return existing_issue <EOL> app . logger . debug ( "<STR_LIT>" <EOL> . format ( item . index , item . region , item . account , item . name , issue , notes ) ) <EOL> new_issue = datastore . ItemAudit ( score = score , <EOL> issue = issue , <EOL> notes = notes , <EOL> justified = False , <EOL> justified_user_id = None , <EOL> justified_date = None , <EOL> justification = None ) <EOL> item . audit_issues . append ( new_issue ) <EOL> return new_issue <EOL> def prep_for_audit ( self ) : <EOL> """<STR_LIT>""" <EOL> pass <EOL> def audit_these_objects ( self , items ) : <EOL> """<STR_LIT>""" <EOL> app . logger . debug ( "<STR_LIT>" . format ( len ( items ) ) ) <EOL> self . prep_for_audit ( ) <EOL> methods = [ getattr ( self , method_name ) for method_name in dir ( self ) if method_name . find ( "<STR_LIT>" ) == <NUM_LIT:0> ] <EOL> app . logger . debug ( "<STR_LIT>" . format ( methods ) ) <EOL> for item in items : <EOL> for method in methods : <EOL> method ( item ) <EOL> self . items = items <EOL> def audit_all_objects ( self ) : <EOL> """<STR_LIT>""" <EOL> self . items = self . read_previous_items ( ) <EOL> self . audit_these_objects ( self . items ) <EOL> def read_previous_items ( self ) : <EOL> """<STR_LIT>""" <EOL> prev_list = [ ] <EOL> for account in self . accounts : <EOL> prev = self . datastore . get_all_ctype_filtered ( tech = self . index , account = account , include_inactive = False ) <EOL> for item in prev : <EOL> item_revision = prev [ item ] <EOL> new_item = ChangeItem ( index = self . index , <EOL> region = item . region , <EOL> account = item . account . name , <EOL> name = item . name , <EOL> new_config = item_revision . config ) <EOL> new_item . audit_issues = [ ] <EOL> new_item . db_item = item <EOL> prev_list . append ( new_item ) <EOL> return prev_list <EOL> def save_issues ( self ) : <EOL> """<STR_LIT>""" <EOL> app . logger . debug ( "<STR_LIT>" ) <EOL> for item in self . items : <EOL> if not hasattr ( item , '<STR_LIT>' ) : <EOL> item . db_item = self . datastore . _get_item ( item . index , item . region , item . account , item . name ) <EOL> existing_issues = item . db_item . issues <EOL> new_issues = item . audit_issues <EOL> old_scored = [ ( "<STR_LIT>" . format ( old_issue . issue , old_issue . notes ) , old_issue . score ) for old_issue in existing_issues ] <EOL> for new_issue in new_issues : <EOL> nk = "<STR_LIT>" . format ( new_issue . issue , new_issue . notes ) <EOL> if ( nk , new_issue . score ) not in old_scored : <EOL> app . logger . debug ( "<STR_LIT>" . format ( nk ) ) <EOL> item . found_new_issue = True <EOL> item . confirmed_new_issues . append ( new_issue ) <EOL> item . db_item . issues . append ( new_issue ) <EOL> db . session . add ( item . db_item ) <EOL> db . session . add ( new_issue ) <EOL> else : <EOL> for issue in existing_issues : <EOL> if issue . issue == new_issue . issue and issue . notes == new_issue . notes and issue . score == new_issue . score : <EOL> item . confirmed_existing_issues . append ( issue ) <EOL> break <EOL> key = "<STR_LIT>" . format ( item . index , item . region , item . account , item . name ) <EOL> app . logger . debug ( "<STR_LIT>" . format ( key , nk ) ) <EOL> new_scored = [ ( "<STR_LIT>" . format ( new_issue . issue , new_issue . notes ) , new_issue . score ) for new_issue in new_issues ] <EOL> for old_issue in existing_issues : <EOL> ok = "<STR_LIT>" . format ( old_issue . issue , old_issue . notes ) <EOL> if ( ok , old_issue . score ) not in new_scored : <EOL> app . logger . debug ( "<STR_LIT>" . format ( ok ) ) <EOL> item . confirmed_fixed_issues . append ( old_issue ) <EOL> db . session . delete ( old_issue ) <EOL> db . session . commit ( ) <EOL> self . _create_auditor_settings ( ) <EOL> def email_report ( self , report ) : <EOL> """<STR_LIT>""" <EOL> if not report : <EOL> app . logger . info ( "<STR_LIT>" ) <EOL> return <EOL> subject = "<STR_LIT>" . format ( self . i_am_singular ) <EOL> send_email ( subject = subject , recipients = self . emails , html = report ) <EOL> def create_report ( self ) : <EOL> """<STR_LIT>""" <EOL> jenv = get_jinja_env ( ) <EOL> template = jenv . get_template ( '<STR_LIT>' ) <EOL> for item in self . items : <EOL> item . totalscore = <NUM_LIT:0> <EOL> for issue in item . db_item . issues : <EOL> item . totalscore = item . totalscore + issue . score <EOL> sorted_list = sorted ( self . items , key = lambda item : item . totalscore ) <EOL> sorted_list . reverse ( ) <EOL> report_list = [ ] <EOL> for item in sorted_list : <EOL> if item . totalscore > <NUM_LIT:0> : <EOL> report_list . append ( item ) <EOL> else : <EOL> break <EOL> if len ( report_list ) > <NUM_LIT:0> : <EOL> return template . render ( { '<STR_LIT>' : report_list } ) <EOL> else : <EOL> return False <EOL> def _create_auditor_settings ( self ) : <EOL> """<STR_LIT>""" <EOL> app . logger . debug ( "<STR_LIT>" . format ( self . accounts , self . index ) ) <EOL> query = ItemAudit . query <EOL> query = query . join ( ( Item , Item . id == ItemAudit . item_id ) ) <EOL> query = query . join ( ( Technology , Technology . id == Item . tech_id ) ) <EOL> query = query . filter ( Technology . name == self . index ) <EOL> issues = query . filter ( ItemAudit . auditor_setting_id == None ) . all ( ) <EOL> for issue in issues : <EOL> self . _set_auditor_setting_for_issue ( issue ) <EOL> db . session . commit ( ) <EOL> app . logger . debug ( "<STR_LIT>" . format ( self . accounts , self . index ) ) <EOL> def _set_auditor_setting_for_issue ( self , issue ) : <EOL> auditor_setting = AuditorSettings . query . filter ( <EOL> and_ ( <EOL> AuditorSettings . tech_id == issue . item . tech_id , <EOL> AuditorSettings . account_id == issue . item . account_id , <EOL> AuditorSettings . issue_text == issue . issue <EOL> ) <EOL> ) . first ( ) <EOL> if auditor_setting : <EOL> auditor_setting . issues . append ( issue ) <EOL> db . session . add ( auditor_setting ) <EOL> return auditor_setting <EOL> auditor_setting = AuditorSettings ( <EOL> tech_id = issue . item . tech_id , <EOL> account_id = issue . item . account_id , <EOL> disabled = False , <EOL> issue_text = issue . issue <EOL> ) <EOL> auditor_setting . issues . append ( issue ) <EOL> db . session . add ( auditor_setting ) <EOL> db . session . commit ( ) <EOL> db . session . refresh ( auditor_setting ) <EOL> app . logger . debug ( "<STR_LIT>" . format ( <EOL> issue . issue , <EOL> self . index , <EOL> issue . item . account . name ) ) <EOL> return auditor_setting <EOL> def _check_cross_account ( self , src_account_number , dest_item , location ) : <EOL> account = Account . query . filter ( Account . number == src_account_number ) . first ( ) <EOL> account_name = None <EOL> if account is not None : <EOL> account_name = account . name <EOL> src = account_name or src_account_number <EOL> dst = dest_item . account <EOL> if src == dst : <EOL> return None <EOL> notes = "<STR_LIT>" . format ( src , dst , location ) <EOL> if not account_name : <EOL> tag = "<STR_LIT>" <EOL> self . add_issue ( <NUM_LIT:10> , tag , dest_item , notes = notes ) <EOL> elif account_name != dest_item . account and not account . third_party : <EOL> tag = "<STR_LIT>" <EOL> self . add_issue ( <NUM_LIT:0> , tag , dest_item , notes = notes ) <EOL> elif account_name != dest_item . account and account . third_party : <EOL> tag = "<STR_LIT>" <EOL> self . add_issue ( <NUM_LIT:0> , tag , dest_item , notes = notes ) <EOL> def _check_cross_account_root ( self , source_item , dest_arn , actions ) : <EOL> if not actions : <EOL> return None <EOL> account = Account . query . filter ( Account . name == source_item . account ) . first ( ) <EOL> source_item_account_number = account . number <EOL> if source_item_account_number == dest_arn . account_number : <EOL> return None <EOL> tag = "<STR_LIT>" <EOL> notes = "<STR_LIT>" . format ( dest_arn . account_number ) <EOL> notes += "<STR_LIT:{}>" . format ( actions ) <EOL> self . add_issue ( <NUM_LIT:6> , tag , source_item , notes = notes ) </s>
