From e6499d176b805406d376c6f086e5fab0a12e741e Mon Sep 17 00:00:00 2001 From: vigneswararaomacharla Date: Fri, 24 May 2019 19:39:54 +0530 Subject: [PATCH 1/2] Added remediation tickets with insecure sg updates. Added remediation tickets with insecure sg updates. --- .../remediation/clean_security_groups.py | 45 ++++++++++++++++++- 1 file changed, 43 insertions(+), 2 deletions(-) diff --git a/hammer/reporting-remediation/remediation/clean_security_groups.py b/hammer/reporting-remediation/remediation/clean_security_groups.py index 91d0c7ad..695da3b1 100755 --- a/hammer/reporting-remediation/remediation/clean_security_groups.py +++ b/hammer/reporting-remediation/remediation/clean_security_groups.py @@ -5,7 +5,7 @@ import logging import argparse - +from botocore.exceptions import ClientError from library.logger import set_logging, add_cw_logging from library.config import Config from library.jiraoperations import JiraReporting @@ -23,6 +23,44 @@ class CleanSecurityGroups(object): def __init__(self, config): self.config = config + @staticmethod + def build_open_ports_table_jira(account, sg_id): + args = {'DryRun': False} + if sg_id: + args['GroupIds'] = [sg_id] + try: + secgroups = account.client("ec2").describe_security_groups(**args)["SecurityGroups"] + except ClientError as err: + if err.response['Error']['Code'] in ["AccessDenied", "UnauthorizedOperation"]: + logging.error(f"Access denied in {self.account} " + f"(ec2:{err.operation_name})") + elif err.response['Error']['Code'] == "InvalidGroup.NotFound": + logging.error(err.response['Error']['Message']) + return False + else: + logging.exception(f"Failed to describe security groups in {self.account}") + return False + + port_details = "||From Port||To Port||Protocol||CIDR||\n" + + for security_group in secgroups: + permissions_source = security_group["IpPermissions"] + for ingress in permissions_source: + protocol = ingress["IpProtocol"] + if protocol == "-1" or protocol not in ["tcp", "udp", "icmp", "icmpv6", "58"]: + from_port = None + to_port = None + else: + from_port = ingress.get("FromPort", 0) + to_port = ingress.get("ToPort", 65535) + ip_ranges = [ip_range["CidrIp"] for ip_range in ingress["IpRanges"]] + ip_ranges += [ip_range["CidrIpv6"] for ip_range in ingress.get("Ipv6Ranges", [])] + + for ip_range in ip_ranges: + port_details += f"|{from_port}|{to_port}|{protocol}|{ip_range}|" + port_details += "\n" + return port_details + def clean_security_groups(self, batch=False): """ Class function to clean security groups which are violating aws best practices """ main_account = Account(region=config.aws.region) @@ -114,7 +152,10 @@ def clean_security_groups(self, batch=False): f"[{backup_path}|https://s3.console.aws.amazon.com/s3/object/{backup_bucket}/{backup_path}]. " f"Security group '{group_name} / {group_id}' `{RestrictionStatus.OpenCompletely.value}` issue " f"in '{account_name} / {account_id}' account, '{group_region}' region " - f"was remediated by hammer") + f"was remediated by hammer.") + + comment += "\n\n After remediation, Security Group has access to following ports: \n" + comment += self.build_open_ports_table_jira(account, group_id) if comment is not None: jira.remediate_issue( From aba87a45ee8e8728811d00be836182014fb2bca1 Mon Sep 17 00:00:00 2001 From: vigneswararaomacharla Date: Mon, 27 May 2019 11:38:23 +0530 Subject: [PATCH 2/2] Updated with SG remediation updates. Updated with SG remediation updates. --- hammer/library/aws/security_groups.py | 38 +++++++++++++++++ .../remediation/clean_security_groups.py | 42 +------------------ 2 files changed, 40 insertions(+), 40 deletions(-) diff --git a/hammer/library/aws/security_groups.py b/hammer/library/aws/security_groups.py index 814d88aa..5a126522 100755 --- a/hammer/library/aws/security_groups.py +++ b/hammer/library/aws/security_groups.py @@ -342,6 +342,44 @@ def restrict(self, status=None): processed += 1 return processed + @staticmethod + def build_open_ports_table(account, sg_id): + args = {'DryRun': False} + if sg_id: + args['GroupIds'] = [sg_id] + try: + secgroups = account.client("ec2").describe_security_groups(**args)["SecurityGroups"] + except ClientError as err: + if err.response['Error']['Code'] in ["AccessDenied", "UnauthorizedOperation"]: + logging.error(f"Access denied in {account} " + f"(ec2:{err.operation_name})") + elif err.response['Error']['Code'] == "InvalidGroup.NotFound": + logging.error(err.response['Error']['Message']) + return False + else: + logging.exception(f"Failed to describe security groups in {account}") + return False + + port_details = "||From Port||To Port||Protocol||CIDR||\n" + + for security_group in secgroups: + permissions_source = security_group["IpPermissions"] + for ingress in permissions_source: + protocol = ingress["IpProtocol"] + if protocol == "-1" or protocol not in ["tcp", "udp", "icmp", "icmpv6", "58"]: + from_port = None + to_port = None + else: + from_port = ingress.get("FromPort", 0) + to_port = ingress.get("ToPort", 65535) + ip_ranges = [ip_range["CidrIp"] for ip_range in ingress["IpRanges"]] + ip_ranges += [ip_range["CidrIpv6"] for ip_range in ingress.get("Ipv6Ranges", [])] + + for ip_range in ip_ranges: + port_details += f"|{from_port}|{to_port}|{protocol}|{ip_range}|" + port_details += "\n" + return port_details + class SecurityGroup(object): """ diff --git a/hammer/reporting-remediation/remediation/clean_security_groups.py b/hammer/reporting-remediation/remediation/clean_security_groups.py index 695da3b1..f50df950 100755 --- a/hammer/reporting-remediation/remediation/clean_security_groups.py +++ b/hammer/reporting-remediation/remediation/clean_security_groups.py @@ -10,7 +10,7 @@ from library.config import Config from library.jiraoperations import JiraReporting from library.slack_utility import SlackNotification -from library.aws.security_groups import SecurityGroupsChecker, RestrictionStatus +from library.aws.security_groups import SecurityGroupsChecker, RestrictionStatus, SecurityGroupPermission from library.aws.utility import Account from library.ddb_issues import Operations as IssueOperations from library.ddb_issues import IssueStatus, SecurityGroupIssue @@ -23,44 +23,6 @@ class CleanSecurityGroups(object): def __init__(self, config): self.config = config - @staticmethod - def build_open_ports_table_jira(account, sg_id): - args = {'DryRun': False} - if sg_id: - args['GroupIds'] = [sg_id] - try: - secgroups = account.client("ec2").describe_security_groups(**args)["SecurityGroups"] - except ClientError as err: - if err.response['Error']['Code'] in ["AccessDenied", "UnauthorizedOperation"]: - logging.error(f"Access denied in {self.account} " - f"(ec2:{err.operation_name})") - elif err.response['Error']['Code'] == "InvalidGroup.NotFound": - logging.error(err.response['Error']['Message']) - return False - else: - logging.exception(f"Failed to describe security groups in {self.account}") - return False - - port_details = "||From Port||To Port||Protocol||CIDR||\n" - - for security_group in secgroups: - permissions_source = security_group["IpPermissions"] - for ingress in permissions_source: - protocol = ingress["IpProtocol"] - if protocol == "-1" or protocol not in ["tcp", "udp", "icmp", "icmpv6", "58"]: - from_port = None - to_port = None - else: - from_port = ingress.get("FromPort", 0) - to_port = ingress.get("ToPort", 65535) - ip_ranges = [ip_range["CidrIp"] for ip_range in ingress["IpRanges"]] - ip_ranges += [ip_range["CidrIpv6"] for ip_range in ingress.get("Ipv6Ranges", [])] - - for ip_range in ip_ranges: - port_details += f"|{from_port}|{to_port}|{protocol}|{ip_range}|" - port_details += "\n" - return port_details - def clean_security_groups(self, batch=False): """ Class function to clean security groups which are violating aws best practices """ main_account = Account(region=config.aws.region) @@ -155,7 +117,7 @@ def clean_security_groups(self, batch=False): f"was remediated by hammer.") comment += "\n\n After remediation, Security Group has access to following ports: \n" - comment += self.build_open_ports_table_jira(account, group_id) + comment += SecurityGroupPermission.build_open_ports_table(account, group_id) if comment is not None: jira.remediate_issue(