Exemplo n.º 1
0
def generate_example_report():
    output_directory = os.getcwd()
    account_name = "fake"
    account_id = "987654321987"
    # rendered_report = scan_account_authorization_details(
    #     results_file, DEFAULT_EXCLUSIONS, account_name="example", output_directory=os.getcwd()
    # )
    minimize = False
    html_report = HTMLReport(account_id=account_id,
                             account_name=account_name,
                             results=results,
                             minimize=minimize)
    rendered_report = html_report.get_html_report()

    # html_output_file = os.path.join(output_directory, f"index.html")
    html_output_file = os.path.join(output_directory,
                                    f"iam-report-{account_name}.html")

    with open(html_output_file, "w") as f:
        f.write(rendered_report)

    print(f"Wrote HTML results to: {html_output_file}")
    index_output_file = os.path.join(output_directory, "index.html")
    shutil.copyfile(os.path.join(output_directory, "iam-report-fake.html"),
                    index_output_file)
    url = "file://%s" % os.path.abspath(index_output_file)
    webbrowser.open(url, new=2)
Exemplo n.º 2
0
def scan_account_authorization_details(
    account_authorization_details_cfg,
    exclusions,
    account_name="default",
    output_directory=os.getcwd(),
    write_data_files=False,
    minimize=False,
):  # pragma: no cover
    """
    Given the path to account authorization details files and the exclusions config file, scan all inline and
    managed policies in the account to identify actions that do not leverage resource constraints.
    """

    logger.debug("Identifying modify-only actions that are not leveraging "
                 "resource constraints...")
    check_authorization_details_schema(account_authorization_details_cfg)
    authorization_details = AuthorizationDetails(
        account_authorization_details_cfg, exclusions)
    results = authorization_details.results

    # Lazy method to get an account ID
    account_id = None
    for role in results.get("roles"):
        if "arn:aws:iam::aws:" not in results["roles"][role]["arn"]:
            account_id = get_account_from_arn(results["roles"][role]["arn"])
            break

    html_report = HTMLReport(
        account_id=account_id,
        account_name=account_name,
        results=results,
        minimize=minimize,
    )
    rendered_report = html_report.get_html_report()

    # Raw data file
    if write_data_files:
        if output_directory is None:
            output_directory = os.getcwd()

        results_data_file = os.path.join(output_directory,
                                         f"iam-results-{account_name}.json")
        results_data_filepath = write_results_data_file(
            authorization_details.results, results_data_file)
        print(f"Results data saved: {str(results_data_filepath)}")

        findings_data_file = os.path.join(output_directory,
                                          f"iam-findings-{account_name}.json")
        findings_data_filepath = write_results_data_file(
            results, findings_data_file)
        print(f"Findings data file saved: {str(findings_data_filepath)}")

    return rendered_report
Exemplo n.º 3
0
def scan_accounts(
    multi_account_config: MultiAccountConfig,
    exclusions: Exclusions,
    role_name: str,
    write_data_file: bool,
    profile: Optional[str] = None,
    output_directory: Optional[str] = None,
    output_bucket: Optional[str] = None,
) -> None:
    """Use this method as a library to scan multiple accounts"""
    # TODO: Speed improvements? Multithreading? This currently runs sequentially.
    for target_account_name, target_account_id in multi_account_config.accounts.items(
    ):
        print(
            f"{OK_GREEN}Scanning account: {target_account_name} (ID: {target_account_id}){END}"
        )
        results = scan_account(
            target_account_id=target_account_id,
            target_role_name=role_name,
            exclusions=exclusions,
            profile=profile,
        )
        html_report = HTMLReport(
            account_id=target_account_id,
            account_name=target_account_name,
            results=results,
            minimize=True,
        )
        rendered_report = html_report.get_html_report()
        if not output_directory and not output_bucket:
            raise Exception(
                "Please supply --output-bucket and/or --output-directory as arguments."
            )
        if output_bucket:
            s3 = aws_login.get_boto3_resource(service="s3", profile=profile)
            # Write the HTML file
            output_file = f"{target_account_name}.html"
            s3.Object(output_bucket,
                      output_file).put(ACL="bucket-owner-full-control",
                                       Body=rendered_report)
            utils.print_green(
                f"Saved the HTML report to: s3://{output_bucket}/{output_file}"
            )
            # Write the JSON data file
            if write_data_file:
                output_file = f"{target_account_name}.json"
                body = json.dumps(results,
                                  sort_keys=True,
                                  default=str,
                                  indent=4)
                s3.Object(output_bucket,
                          output_file).put(ACL="bucket-owner-full-control",
                                           Body=body)
                utils.print_green(
                    f"Saved the JSON data to: s3://{output_bucket}/{output_file}"
                )
        if output_directory:
            # Write the HTML file
            html_output_file = Path(
                output_directory) / f"{target_account_name}.html"
            html_output_file.write_text(rendered_report)
            utils.print_green(
                f"Saved the HTML report to: {os.path.relpath(html_output_file)}"
            )
            # Write the JSON data file
            if write_data_file:
                results_data_file = os.path.join(
                    output_directory, f"{target_account_name}.json")
                results_data_filepath = utils.write_results_data_file(
                    results, results_data_file)
                utils.print_green(
                    f"Saved the JSON data to: {os.path.relpath(results_data_filepath)}"
                )
Exemplo n.º 4
0
def scan_account_authorization_details(
        account_authorization_details_cfg,
        exclusions,
        account_name="default",
        output_directory=os.getcwd(),
        write_data_files=False):  # pragma: no cover
    """
    Given the path to account authorization details files and the exclusions config file, scan all inline and
    managed policies in the account to identify actions that do not leverage resource constraints.
    """

    logger.debug("Identifying modify-only actions that are not leveraging "
                 "resource constraints...")
    check_authorization_details_schema(account_authorization_details_cfg)
    authorization_details = AuthorizationDetails(
        account_authorization_details_cfg)
    results = authorization_details.missing_resource_constraints(
        exclusions, modify_only=True)

    principal_policy_mapping = authorization_details.principal_policy_mapping
    # For the IAM Principals tab, add on risk stats per principal
    for principal_policy_entry in principal_policy_mapping:
        for finding in results:
            if principal_policy_entry.get("PolicyName").lower() == finding.get(
                    "PolicyName").lower():
                principal_policy_entry["Actions"] = len(finding["Actions"])
                principal_policy_entry["PrivilegeEscalation"] = len(
                    finding["PrivilegeEscalation"])
                principal_policy_entry["DataExfiltrationActions"] = len(
                    finding["DataExfiltrationActions"])
                principal_policy_entry["PermissionsManagementActions"] = len(
                    finding["PermissionsManagementActions"])
                principal_name = principal_policy_entry["Principal"]
                # Customer Managed Policies
                if finding.get("Type") == "Policy" and finding.get(
                        "ManagedBy"
                ) == "Customer" and principal_policy_entry.get(
                        "Type") != "Policy":
                    if "Principals" not in finding:
                        finding["Principals"] = [principal_name]
                    else:
                        if principal_name not in finding["Principals"]:
                            finding["Principals"].append(principal_name)

                # AWS Managed Policies
                if finding.get("Type") == "Policy" and finding.get(
                        "ManagedBy") == "AWS":
                    if "Principals" not in finding:
                        finding["Principals"] = [principal_name]
                    else:
                        if principal_name not in finding["Principals"]:
                            finding["Principals"].append(principal_name)

    # Lazy method to get an account ID
    account_id = None
    for item in results:
        if item["ManagedBy"] == "Customer":
            account_id = item["AccountID"]
            break

    html_report = HTMLReport(account_id=account_id,
                             account_name=account_name,
                             results=results,
                             exclusions_cfg=exclusions,
                             principal_policy_mapping=principal_policy_mapping)
    rendered_report = html_report.get_html_report()

    # Raw data file
    if write_data_files:
        if output_directory is None:
            output_directory = os.getcwd()

        # new_data = authorization_details.new_principal_policy_mapping
        # new_raw_data_file = os.path.join(output_directory, f"iam-new-principal-policy-mapping-{account_name}.json")
        # new_raw_data_filepath = write_results_data_file(new_data, new_raw_data_file)
        # print(f"Raw data file saved: {str(new_raw_data_filepath)}")

        raw_data_file = os.path.join(output_directory,
                                     f"iam-results-{account_name}.json")
        raw_data_filepath = write_results_data_file(results, raw_data_file)
        print(f"Raw data file saved: {str(raw_data_filepath)}")

        # Principal policy mapping
        principal_policy_mapping_file = os.path.join(
            output_directory, f"iam-principals-{account_name}.json")
        principal_policy_mapping_filepath = write_results_data_file(
            principal_policy_mapping, principal_policy_mapping_file)
        print(
            f"Principals data file saved: {str(principal_policy_mapping_filepath)}"
        )

        # Create the CSV triage sheet
        create_triage_worksheet(account_name, results, output_directory)

    return rendered_report
Exemplo n.º 5
0
    def test_output_html_output_as_string(self):
        example_authz_details_file = os.path.abspath(
            os.path.join(
                os.path.dirname(__file__),
                os.path.pardir,
                "files",
                "example-authz-details.json",
            ))
        with open(example_authz_details_file, "r") as json_file:
            cfg = json.load(json_file)
            decision = check_authorization_details_schema(cfg)
        self.assertTrue(decision)
        # TODO: These values are just for testing
        account_authorization_details_cfg = cfg
        exclusions = DEFAULT_EXCLUSIONS

        authorization_details = AuthorizationDetails(
            account_authorization_details_cfg)
        results = authorization_details.missing_resource_constraints(
            exclusions, modify_only=True)

        principal_policy_mapping = authorization_details.principal_policy_mapping
        # For the IAM Principals tab, add on risk stats per principal
        for principal_policy_entry in principal_policy_mapping:
            for finding in results:
                if principal_policy_entry.get("PolicyName").lower(
                ) == finding.get("PolicyName").lower():
                    principal_policy_entry["Actions"] = len(finding["Actions"])
                    principal_policy_entry["PrivilegeEscalation"] = len(
                        finding["PrivilegeEscalation"])
                    principal_policy_entry["DataExfiltrationActions"] = len(
                        finding["DataExfiltrationActions"])
                    principal_policy_entry[
                        "PermissionsManagementActions"] = len(
                            finding["PermissionsManagementActions"])
                    principal_name = principal_policy_entry["Principal"]
                    # Customer Managed Policies
                    if finding.get("Type") == "Policy" and finding.get(
                            "ManagedBy"
                    ) == "Customer" and principal_policy_entry.get(
                            "Type") != "Policy":
                        if "Principals" not in finding:
                            finding["Principals"] = [principal_name]
                        else:
                            if principal_name not in finding["Principals"]:
                                finding["Principals"].append(principal_name)

                    # AWS Managed Policies
                    if finding.get("Type") == "Policy" and finding.get(
                            "ManagedBy") == "AWS":
                        if "Principals" not in finding:
                            finding["Principals"] = [principal_name]
                        else:
                            if principal_name not in finding["Principals"]:
                                finding["Principals"].append(principal_name)

        # Lazy method to get an account ID
        account_id = None
        for item in results:
            if item["ManagedBy"] == "Customer":
                account_id = item["AccountID"]
                break

        html_report = HTMLReport(
            account_id=account_id,
            account_name="CHANGEME",
            results=results,
            exclusions_cfg=exclusions,
            principal_policy_mapping=principal_policy_mapping)
        rendered_report = html_report.get_html_report()