def run(self, *args, **kwargs): """Entry point for the scheduler Args: *args: Optional arguments **kwargs: Optional keyword arguments Returns: None """ accounts = list(AWSAccount.get_all(include_disabled=False).values()) # S3 Bucket config s3_acl = get_template('cloudtrail_s3_bucket_policy.json') s3_bucket_name = self.dbconfig.get('bucket_name', self.ns) s3_bucket_region = self.dbconfig.get('bucket_region', self.ns, 'us-west-2') s3_bucket_account = AWSAccount.get( self.dbconfig.get('bucket_account', self.ns)) CloudTrail.create_s3_bucket(s3_bucket_name, s3_bucket_region, s3_bucket_account, s3_acl) self.validate_sqs_policy(accounts) for account in accounts: ct = CloudTrail(account, s3_bucket_name, s3_bucket_region, self.log) ct.run()
def create_sns_topic(self, region): """Creates an SNS topic if needed. Returns the ARN if the created SNS topic Args: region (str): Region name Returns: `str` """ sns = self.session.client('sns', region_name=region) self.log.info('Creating SNS topic for {}/{}'.format( self.account, region)) # Create the topic res = sns.create_topic(Name=self.topic_name) arn = res['TopicArn'] # Allow CloudTrail to publish messages with a policy update tmpl = get_template('cloudtrail_sns_policy.json') policy = tmpl.render(region=region, account_id=self.account.account_number, topic_name=self.topic_name) sns.set_topic_attributes(TopicArn=arn, AttributeName='Policy', AttributeValue=policy) auditlog(event='cloudtrail.create_sns_topic', actor=self.ns, data={ 'account': self.account.account_name, 'region': region }) return arn
def notify(self, notices): """Send notifications to the recipients provided Args: notices (:obj:`dict` of `str`: `list`): A dictionary mapping notification messages to the recipient. Returns: `None` """ tmpl_html = get_template('required_tags_notice.html') tmpl_text = get_template('required_tags_notice.txt') for recipient, data in list(notices.items()): body_html = tmpl_html.render(data=data) body_text = tmpl_text.render(data=data) send_notification(subsystem=self.ns, recipients=[recipient], subject=self.email_subject, body_html=body_html, body_text=body_text)
def create_iam_role(self, account): """Create a new IAM role. Returns the ARN of the newly created role Args: account (:obj:`Account`): Account where to create the IAM role Returns: `str` """ try: iam = self.session.client('iam') trust = get_template('vpc_flow_logs_iam_role_trust.json').render() policy = get_template('vpc_flow_logs_role_policy.json').render() newrole = iam.create_role( Path='/', RoleName=self.role_name, AssumeRolePolicyDocument=trust)['Role']['Arn'] # Attach an inline policy to the role to avoid conflicts or hitting the Managed Policy Limit iam.put_role_policy(RoleName=self.role_name, PolicyName='VpcFlowPolicy', PolicyDocument=policy) self.log.debug('Created VPC Flow Logs role & policy for {}'.format( account.account_name)) auditlog(event='vpc_flow_logs.create_iam_role', actor=self.ns, data={ 'account': account.account_name, 'roleName': self.role_name, 'trustRelationship': trust, 'inlinePolicy': policy }) return newrole except Exception: self.log.exception( 'Failed creating the VPC Flow Logs role for {}.'.format( account))
def notify(self, notices): """Send notifications to the users via. the provided methods Args: notices (:obj:`dict` of `str`: `dict`): List of the notifications to send Returns: `None` """ issues_html = get_template('unattached_ebs_volume.html') issues_text = get_template('unattached_ebs_volume.txt') for recipient, issues in list(notices.items()): if issues: message_html = issues_html.render(issues=issues) message_text = issues_text.render(issues=issues) send_notification(subsystem=self.name, recipients=[recipient], subject=self.subject, body_html=message_html, body_text=message_text)
def notify(self, new_issues, existing_issues, fixed_issues): """Send notifications (email, slack, etc.) for any issues that are currently open or has just been closed Args: new_issues (`list` of :obj:`DomainHijackIssue`): List of newly discovered issues existing_issues (`list` of :obj:`DomainHijackIssue`): List of existing open issues fixed_issues (`list` of `dict`): List of fixed issues Returns: None """ if len(new_issues + existing_issues + fixed_issues) > 0: maxlen = max(len(x['properties']['source']) for x in (new_issues + existing_issues + fixed_issues)) + 2 text_tmpl = get_template('domain_hijacking.txt') html_tmpl = get_template('domain_hijacking.html') issues_text = text_tmpl.render( new_issues=new_issues, existing_issues=existing_issues, fixed_issues=fixed_issues, maxlen=maxlen ) issues_html = html_tmpl.render( new_issues=new_issues, existing_issues=existing_issues, fixed_issues=fixed_issues, maxlen=maxlen ) try: send_notification( subsystem=self.name, recipients=[NotificationContact('email', addr) for addr in self.recipients], subject=self.subject, body_html=issues_html, body_text=issues_text ) except Exception as ex: self.log.exception('Failed sending notification email: {}'.format(ex))
def _init_saml_request(self): tmpl = get_template('saml_settings.json') config = tmpl.render( strict=str(self.dbconfig.get('strict', self.ns, True)).lower(), debug=str(self.dbconfig.get('debug', self.ns, False)).lower(), sp_entity_id=self.dbconfig.get('sp_entity_id', self.ns), sp_acs=self.dbconfig.get('sp_acs', self.ns), sp_sls=self.dbconfig.get('sp_sls', self.ns), idp_entity_id=self.dbconfig.get('idp_entity_id', self.ns), idp_ssos=self.dbconfig.get('idp_ssos', self.ns), idp_sls=self.dbconfig.get('idp_sls', self.ns), idp_x509cert=self.dbconfig.get('idp_x509cert', self.ns) ) auth = OneLogin_Saml2_Auth(self.req, json.loads(config)) auth.set_strict(False) return auth
def _get_syslog_format(event_type): """Take an event type argument and return a python logging format In order to properly format the syslog messages to current standard, load the template and perform necessary replacements and return the string. Args: event_type (str): Event type name Returns: `str` """ syslog_format_template = get_template('syslog_format.json') fmt = syslog_format_template.render(event_type=event_type, host=dbconfig.get('instance_name', default='local')) # Load and redump string, to get rid of any extraneous whitespaces return json.dumps(json.loads(fmt))