def create_tickets_s3buckets(self): """ Class method to create jira tickets """ table_name = self.config.s3policy.ddb_table_name main_account = Account(region=self.config.aws.region) ddb_table = main_account.resource("dynamodb").Table(table_name) jira = JiraReporting(self.config) slack = SlackNotification(self.config) for account_id, account_name in self.config.s3policy.accounts.items(): logging.debug(f"Checking '{account_name} / {account_id}'") issues = IssueOperations.get_account_not_closed_issues( ddb_table, account_id, S3PolicyIssue) for issue in issues: bucket_name = issue.issue_id tags = issue.issue_details.tags policy = issue.issue_details.policy # issue has been already reported if issue.timestamps.reported is not None: owner = issue.issue_details.owner bu = issue.jira_details.business_unit product = issue.jira_details.product if issue.status in [ IssueStatus.Resolved, IssueStatus.Whitelisted ]: logging.debug( f"Closing {issue.status.value} S3 bucket '{bucket_name}' public policy issue" ) comment = ( f"Closing {issue.status.value} S3 bucket '{bucket_name}' public policy " f"in '{account_name} / {account_id}' account ") jira.close_issue(ticket_id=issue.jira_details.ticket, comment=comment) slack.report_issue( msg=f"{comment}" f"{' (' + jira.ticket_url(issue.jira_details.ticket) + ')' if issue.jira_details.ticket else ''}", owner=owner, account_id=account_id, bu=bu, product=product, ) IssueOperations.set_status_closed(ddb_table, issue) # issue.status != IssueStatus.Closed (should be IssueStatus.Open) elif issue.timestamps.updated > issue.timestamps.reported: logging.debug( f"Updating S3 bucket '{bucket_name}' public policy issue" ) comment = "Issue details are changed, please check again.\n" # Adding new bucket policy json as attachment to Jira ticket. attachment = jira.add_attachment( ticket_id=issue.jira_details.ticket, filename=self.attachment_name( account_id, bucket_name), text=policy) if attachment is not None: comment += f"New policy - [^{attachment.filename}].\n" comment += JiraOperations.build_tags_table(tags) jira.update_issue(ticket_id=issue.jira_details.ticket, comment=comment) slack.report_issue( msg= f"S3 bucket '{bucket_name}' pubic policy issue is changed " f"in '{account_name} / {account_id}' account" f"{' (' + jira.ticket_url(issue.jira_details.ticket) + ')' if issue.jira_details.ticket else ''}", owner=owner, account_id=account_id, bu=bu, product=product, ) IssueOperations.set_status_updated(ddb_table, issue) else: logging.debug(f"No changes for '{bucket_name}'") # issue has not been reported yet else: logging.debug( f"Reporting S3 bucket '{bucket_name}' public policy issue" ) owner = tags.get("owner", None) bu = tags.get("bu", None) product = tags.get("product", None) if bu is None: bu = self.config.get_bu_by_name(bucket_name) issue_summary = ( f"S3 bucket '{bucket_name}' with public policy " f"in '{account_name} / {account_id}' account{' [' + bu + ']' if bu else ''}" ) issue_description = ( f"Bucket policy allows unrestricted public access.\n\n" f"*Threat*: " f"This creates potential security vulnerabilities by allowing anyone to add, modify, or remove items in a bucket.\n\n" f"*Risk*: High\n\n" f"*Account Name*: {account_name}\n" f"*Account ID*: {account_id}\n" f"*S3 Bucket name*: {bucket_name}\n" f"*Bucket Owner*: {owner}\n" f"\n") auto_remediation_date = ( self.config.now + self.config.s3policy.issue_retention_date).date() issue_description += f"\n{{color:red}}*Auto-Remediation Date*: {auto_remediation_date}{{color}}\n\n" issue_description += JiraOperations.build_tags_table(tags) issue_description += f"\n" issue_description += ( f"*Recommendation*: " f"Grant CloudFront OAI applicable permissions on bucket " f"or update bucket permissions with VPC CIDRs ranges or ip addresses/ranges from " f"[RFC1918|https://tools.ietf.org/html/rfc1918]. ") if self.config.whitelisting_procedure_url: issue_description += ( f"For any other exceptions, please follow the [whitelisting procedure|{self.config.whitelisting_procedure_url}] " f"and provide a strong business reasoning. ") try: response = jira.add_issue( issue_summary=issue_summary, issue_description=issue_description, priority="Major", labels=["publics3"], owner=owner, account_id=account_id, bu=bu, product=product, ) except Exception: logging.exception("Failed to create jira ticket") continue if response is not None: issue.jira_details.ticket = response.ticket_id issue.jira_details.ticket_assignee_id = response.ticket_assignee_id # Adding bucket policy json as attachment to Jira ticket. jira.add_attachment( ticket_id=issue.jira_details.ticket, filename=self.attachment_name( account_id, bucket_name), text=policy) issue.jira_details.owner = owner issue.jira_details.business_unit = bu issue.jira_details.product = product slack.report_issue( msg=f"Discovered {issue_summary}" f"{' (' + jira.ticket_url(issue.jira_details.ticket) + ')' if issue.jira_details.ticket else ''}", owner=owner, account_id=account_id, bu=bu, product=product, ) IssueOperations.set_status_reported(ddb_table, issue)
def create_tickets_sqs_policy(self): """ Class method to create jira tickets """ table_name = self.config.sqspolicy.ddb_table_name main_account = Account(region=self.config.aws.region) ddb_table = main_account.resource("dynamodb").Table(table_name) jira = JiraReporting(self.config) slack = SlackNotification(self.config) for account_id, account_name in self.config.aws.accounts.items(): logging.debug(f"Checking '{account_name} / {account_id}'") issues = IssueOperations.get_account_not_closed_issues( ddb_table, account_id, SQSPolicyIssue) for issue in issues: queue_url = issue.issue_id queue_name = issue.issue_details.name queue_region = issue.issue_details.region tags = issue.issue_details.tags policy = issue.issue_details.policy # issue has been already reported if issue.timestamps.reported is not None: owner = issue.issue_details.owner bu = issue.jira_details.business_unit product = issue.jira_details.product if issue.status in [ IssueStatus.Resolved, IssueStatus.Whitelisted ]: logging.debug( f"Closing {issue.status.value} SQS queue '{queue_name}' public policy issue" ) comment = ( f"Closing {issue.status.value} SQS queue '{queue_name}' public policy " f"in '{account_name} / {account_id}' account, '{queue_region}' region" ) if issue.status == IssueStatus.Whitelisted: # Adding label with "whitelisted" to jira ticket. jira.add_label(ticket_id=issue.jira_details.ticket, label=IssueStatus.Whitelisted.value) jira.close_issue(ticket_id=issue.jira_details.ticket, comment=comment) slack.report_issue( msg=f"{comment}" f"{' (' + jira.ticket_url(issue.jira_details.ticket) + ')' if issue.jira_details.ticket else ''}", owner=owner, account_id=account_id, bu=bu, product=product, ) IssueOperations.set_status_closed(ddb_table, issue) # issue.status != IssueStatus.Closed (should be IssueStatus.Open) elif issue.timestamps.updated > issue.timestamps.reported: logging.debug( f"Updating SQS queue '{queue_name}' public policy issue" ) comment = "Issue details are changed, please check again.\n" # Adding new SQS queue policy json as attachment to Jira ticket. attachment = jira.add_attachment( ticket_id=issue.jira_details.ticket, filename=self.attachment_name( account_id, queue_region, queue_name), text=policy) if attachment is not None: comment += f"New policy - [^{attachment.filename}].\n" comment += JiraOperations.build_tags_table(tags) jira.update_issue(ticket_id=issue.jira_details.ticket, comment=comment) slack.report_issue( msg= f"SQS queue '{queue_name}' pubic policy issue is changed " f"in '{account_name} / {account_id}' account, '{queue_region}' region" f"{' (' + jira.ticket_url(issue.jira_details.ticket) + ')' if issue.jira_details.ticket else ''}", owner=owner, account_id=account_id, bu=bu, product=product, ) IssueOperations.set_status_updated(ddb_table, issue) else: logging.debug(f"No changes for '{queue_name}'") # issue has not been reported yet else: logging.debug( f"Reporting SQS queue '{queue_name}' public policy issue" ) owner = tags.get("owner", None) bu = tags.get("bu", None) product = tags.get("product", None) if bu is None: bu = self.config.get_bu_by_name(queue_name) issue_summary = ( f"SQS queue '{queue_name}' with public policy " f"in '{account_name} / {account_id}' account, '{queue_region}' region" f"{' [' + bu + ']' if bu else ''}") issue_description = ( f"Queue policy allows unrestricted public access.\n\n" f"*Threat*: " f"This creates potential security vulnerabilities by allowing anyone to add, modify, or remove items in a SQS.\n\n" f"*Risk*: High\n\n" f"*Account Name*: {account_name}\n" f"*Account ID*: {account_id}\n" f"*SQS queue url*: {queue_url}\n" f"*SQS queue name*: {queue_name}\n" f"*SQS queue region*: {queue_region}\n" f"\n") auto_remediation_date = ( self.config.now + self.config.sqspolicy.issue_retention_date).date() issue_description += f"\n{{color:red}}*Auto-Remediation Date*: {auto_remediation_date}{{color}}\n\n" issue_description += JiraOperations.build_tags_table(tags) issue_description += f"\n" issue_description += ( f"*Recommendation*: " f"Check if global access is truly needed and " f"if not - update SQS queue policy with " f"an [*IpAddress* condition|https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-customer-managed-policy-examples.html#grant-all-permissions-to-all-users-in-cidr-range] " f"in order to restrict access to specific private IP ranges from [RFC1918|https://tools.ietf.org/html/rfc1918]." ) if self.config.whitelisting_procedure_url: issue_description += ( f"For any other exceptions, please follow the [whitelisting procedure|{self.config.whitelisting_procedure_url}] " f"and provide a strong business reasoning. ") try: response = jira.add_issue( issue_summary=issue_summary, issue_description=issue_description, priority="Major", labels=["publicsqs"], owner=owner, account_id=account_id, bu=bu, product=product, ) except Exception: logging.exception("Failed to create jira ticket") continue if response is not None: issue.jira_details.ticket = response.ticket_id issue.jira_details.ticket_assignee_id = response.ticket_assignee_id # Adding SQS queue json as attachment to Jira ticket. jira.add_attachment( ticket_id=issue.jira_details.ticket, filename=self.attachment_name( account_id, queue_region, queue_name), text=policy) issue.jira_details.owner = owner issue.jira_details.business_unit = bu issue.jira_details.product = product slack.report_issue( msg=f"Discovered {issue_summary}" f"{' (' + jira.ticket_url(issue.jira_details.ticket) + ')' if issue.jira_details.ticket else ''}", owner=owner, account_id=account_id, bu=bu, product=product, ) IssueOperations.set_status_reported(ddb_table, issue)