Exemplo n.º 1
0
    def clean_iam_access_keys(self, batch=False):
        """ Class method to remediate IAM User access keys which are not used """
        main_account = Account(region=config.aws.region)
        ddb_table = main_account.resource("dynamodb").Table(
            self.config.iamUserInactiveKeys.ddb_table_name)

        retention_period = self.config.iamUserInactiveKeys.remediation_retention_period

        jira = JiraReporting(self.config)
        slack = SlackNotification(self.config)

        for account_id, account_name in self.config.aws.accounts.items():
            logging.debug("* Account Name:" + account_name +
                          " :::Account ID:::" + account_id)
            issues = IssueOperations.get_account_open_issues(
                ddb_table, account_id, IAMKeyInactiveIssue)
            for issue in issues:
                key_id = issue.issue_id
                username = issue.issue_details.username

                user_in_whitelist = self.config.iamUserInactiveKeys.in_whitelist(
                    account_id, username)
                key_in_whitelist = self.config.iamUserInactiveKeys.in_whitelist(
                    account_id, key_id)

                if user_in_whitelist or key_in_whitelist:
                    logging.debug(
                        f"Skipping '{key_id} / {username}' (in whitelist)")
                    continue

                if issue.timestamps.reported is None:
                    logging.debug(
                        f"Skipping '{key_id} / {username}' (was not reported)")
                    continue

                if issue.timestamps.remediated is not None:
                    logging.debug(
                        f"Skipping '{key_id} / {username}' (has been already remediated)"
                    )
                    continue

                updated_date = issue.timestamp_as_datetime
                no_of_days_issue_created = (self.config.now -
                                            updated_date).days

                if no_of_days_issue_created >= retention_period:
                    try:
                        if not batch and \
                           not confirm(f"Do you want to remediate inactive access key '{key_id} / {username}'", False):
                            continue

                        account = Account(
                            id=account_id,
                            name=account_name,
                            role_name=self.config.aws.role_name_reporting)
                        if account.session is None:
                            continue

                        logging.debug(
                            f"Remediating inactive access key '{key_id} / {username}'"
                        )
                        remediation_succeed = True
                        try:
                            IAMOperations.disable_access_key(
                                account.client("iam"), username, key_id)
                            comment = (
                                f"Inactive access key '{key_id} / {username}' issue "
                                f"in '{account_name} / {account_id}' account "
                                f"was remediated by hammer")
                        except Exception:
                            remediation_succeed = False
                            logging.exception(
                                "Failed to disable '{key_id} / {username}' inactive access key"
                            )
                            comment = (
                                f"Failed to remediate inactive access key '{key_id} / {username}' issue "
                                f"in '{account_name} / {account_id}' account "
                                f"due to some limitations. Please, check manually"
                            )

                        jira.remediate_issue(
                            ticket_id=issue.jira_details.ticket,
                            comment=comment,
                            reassign=remediation_succeed,
                        )
                        slack.report_issue(
                            msg=f"{comment}"
                            f"{' (' + jira.ticket_url(issue.jira_details.ticket) + ')' if issue.jira_details.ticket else ''}",
                            account_id=account_id,
                        )
                        IssueOperations.set_status_remediated(ddb_table, issue)
                    except Exception:
                        logging.exception(
                            f"Error occurred while disabling '{username} / {key_id}' "
                            f"in '{account_name} / {account_id}'")
                else:
                    logging.debug(
                        f"Skipping '{key_id} / {username}' "
                        f"({retention_period - no_of_days_issue_created} days before remediation)"
                    )
Exemplo n.º 2
0
    def build_instances_table(self, iam_client, instances):
        instance_details = ""
        instance_profile_details = []
        # security group has associated instances
        in_use = False
        # security group has associated instances with public ip in public subnet
        public = False
        # security group has associated instances with public ip in private subnet
        blind_public = False
        owners = []
        bus = []
        products = []
        separator = "\n"

        table_limit_reached = False
        if len(instances) > 0:
            in_use = True
            instance_details += (
                f"||Instance ID||State"
                f"||Private Ip Address||Public Ip Address"
                f"||Owner||Business unit||Product||Component"
                f"||Subnet||\n")

            for ec2_instance in instances:
                if len(ec2_instance.public_ips) > 0:
                    if ec2_instance.public_subnet:
                        public = True
                    else:
                        blind_public = True
                owner = ec2_instance.tags.get('owner')
                bu = ec2_instance.tags.get('bu')
                product = ec2_instance.tags.get('product')
                component = ec2_instance.tags.get('component')
                if self.config.jira.text_field_character_limit == 0 or \
                   len(instance_details) < (self.config.jira.text_field_character_limit * 0.5):
                    instance_details += (
                        f"|{ec2_instance.id}|{ec2_instance.state}"
                        f"|{list_converter(ec2_instance.private_ips)}"
                        f"|{list_converter(ec2_instance.public_ips)}"
                        f"|{empty_converter(owner)}"
                        f"|{empty_converter(bu)}"
                        f"|{empty_converter(product)}"
                        f"|{empty_converter(component)}"
                        f"|{'public' if ec2_instance.public_subnet else 'private'}|\n"
                    )

                    instance_profile_id = ec2_instance.iam_profile_id
                    if instance_profile_id is not None:
                        try:
                            public_role_policies = IAMOperations.get_instance_profile_policy_details(iam_client, instance_profile_id)
                        except Exception:
                            logging.exception("Failed to get instance profile policy details")
                            public_role_policies = []
                        if len(public_role_policies) > 0:
                            for public_role in public_role_policies:
                                instance_profile_details.append(
                                    f"|{ec2_instance.id}|{public_role.role_name}"
                                    f"|{public_role.policy_name}"
                                    f"|{list_converter(public_role.actions, separator)}|\n"
                                )
                elif not table_limit_reached:
                    table_limit_reached = True
                owners.append(owner)
                bus.append(bu)
                products.append(product)

            instance_details = f"*Ec2 Instances{' (limited subset)' if table_limit_reached else ''}*:\n{instance_details}"

        # remove empty and count number of occurrences for each owner/bu/product
        owners = Counter([x for x in owners if x])
        bus = Counter([x for x in bus if x])
        products = Counter([x for x in products if x])
        # find owner/bu/product with max occurrences
        owner = max(owners, key=lambda owner: owners[owner]) if owners else None
        bu = max(bus, key=lambda bu: bus[bu]) if bus else None
        product = max(products, key=lambda product: products[product]) if products else None
        # logging.debug(f"bu={bu}")
        # logging.debug(f"product={product}")

        if len(instance_profile_details) > 0:
            instance_profile_details = (
                f"\n*Instance Role Unsafe Policies:*\n"
                f"||Instance Id||Role Name||Policy Name||Unsafe actions||\n"
            ) + "".join(instance_profile_details) + "\n"

        return instance_details, instance_profile_details, in_use, public, blind_public, owner, bu, product