예제 #1
0
 def test_user_principal_attached_managed_policies(self):
     # User with attached managed policies
     authz_cfg = {
         "UserDetailList": [
             {
                 "Path":
                 "/",
                 "UserName":
                 "******",
                 "UserId":
                 "BlakeBortles",
                 "Arn":
                 "arn:aws:iam::012345678901:user/BlakeBortles",
                 "CreateDate":
                 "2019-12-18 19:10:08+00:00",
                 "GroupList": ["GOAT"],
                 "AttachedManagedPolicies": [{
                     "PolicyArn":
                     "arn:aws:iam::aws:policy/AdministratorAccess",
                     "PolicyName":
                     "AdministratorAccess"
                 }],
                 "Tags": []
             },
         ],
         "GroupDetailList": [],
         "RoleDetailList": [],
         "Policies": []
     }
     authorization_details = AuthorizationDetails(authz_cfg)
     expected_result = ["AdministratorAccess"]
     results = authorization_details.aws_managed_policies_in_use
     # print(json.dumps(results, indent=4))
     self.assertListEqual(results, expected_result)
 def test_authorization_details_with_resource_constraints(self):
     """Case: Authorization details with resource constraints, WITHOUT --flag-all-risky-actions"""
     authz_details = AuthorizationDetails(auth_json=self.authz_json)
     self.assertListEqual(authz_details.policies.policy_details[0].policy_document.credentials_exposure, [])
     self.assertListEqual(authz_details.policies.policy_details[0].policy_document.allows_privilege_escalation, [])
     self.assertListEqual(authz_details.policies.policy_details[0].policy_document.allows_data_exfiltration_actions, [])
     self.assertListEqual(authz_details.policies.policy_details[0].policy_document.permissions_management_without_constraints, [])
     self.assertListEqual(authz_details.policies.policy_details[0].policy_document.infrastructure_modification, [])
 def test_authorization_details_flag_all_risky_actions(self):
     """Case: Authorization details with resource constraints, WITH --flag-all-risky-actions"""
     authz_details = AuthorizationDetails(auth_json=self.authz_json, flag_resource_arn_statements=True, flag_conditional_statements=True)
     self.assertListEqual(authz_details.policies.policy_details[0].policy_document.credentials_exposure, ['iam:UpdateAccessKey', 'sts:AssumeRole'])
     self.assertListEqual(authz_details.policies.policy_details[0].policy_document.allows_privilege_escalation, [{'type': 'UpdateRolePolicyToAssumeIt', 'actions': ['iam:updateassumerolepolicy', 'sts:assumerole']}])
     self.assertListEqual(authz_details.policies.policy_details[0].policy_document.allows_data_exfiltration_actions, ['s3:GetObject'])
     self.assertListEqual(authz_details.policies.policy_details[0].policy_document.permissions_management_without_constraints, ['iam:UpdateAssumeRolePolicy', 's3:PutBucketAcl', 'iam:UpdateAccessKey'])
     self.assertListEqual(authz_details.policies.policy_details[0].policy_document.infrastructure_modification, ['ec2:AuthorizeSecurityGroupIngress', 'iam:UpdateAccessKey', 'iam:UpdateAssumeRolePolicy', 's3:GetObject', 's3:PutBucketAcl', 'sts:AssumeRole'])
예제 #4
0
 def test_authorization_details_attributes(self):
     authorization_details = AuthorizationDetails(
         example_authz_details_for_overrides_complete)
     self.assertListEqual(authorization_details.aws_managed_policies_in_use,
                          ['AdministratorAccess'])
     self.assertListEqual(authorization_details.users, ['BlakeBortles'])
     self.assertListEqual(authorization_details.groups, ['GOAT'])
     self.assertListEqual(authorization_details.roles,
                          ['GOAT', 'MyOtherRole'])
예제 #5
0
    def test_authorization_file_details_missing_constraints_v2(self):
        authorization_details = AuthorizationDetails(example_authz_details_for_overrides_complete)
        result = authorization_details.missing_resource_constraints(modify_only=False)
        expected_results_file = os.path.abspath(
            os.path.join(
                os.path.dirname(__file__),
                os.path.pardir,
                "files",
                "scanning",
                "test_authorization_file_details_missing_constraints_v2.json",
            )
        )

        # print(expected_results_file)
        with open(expected_results_file) as json_file:
            expected_result = json.load(json_file)
        # print(json.dumps(result, indent=4))
        self.maxDiff = None
        self.assertListEqual(result, expected_result)
예제 #6
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
예제 #7
0
def scan_account(target_account_id: str,
                 target_role_name: str,
                 exclusions: Exclusions,
                 profile: str = None):
    """Scan a target account in one shot"""
    authorization_details = download_account_authorization_details(
        target_account_id=target_account_id,
        target_role_name=target_role_name,
        profile=profile)
    check_authorization_details_schema(authorization_details)
    authorization_details = AuthorizationDetails(authorization_details,
                                                 exclusions)
    results = authorization_details.results
    return results
 def test_authorization_files_action_links(self):
     authorization_details = AuthorizationDetails(auth_details_json)
     results = authorization_details.links
     """
     # It will look like this, but :
     {
         "a4b:AssociateContactWithAddressBook": "https://docs.aws.amazon.com/a4b/latest/APIReference/API_AssociateContactWithAddressBook.html",
         "a4b:AssociateDeviceWithRoom": "https://docs.aws.amazon.com/a4b/latest/APIReference/API_AssociateDeviceWithRoom.html",
         ...
     }
     """
     print(len(results.keys()))
     self.assertTrue(len(results.keys()) > 3500)
     print(json.dumps(results, indent=4))
def generate_example_iam_data():
    check_authorization_details_schema(account_authorization_details_cfg)
    authorization_details = AuthorizationDetails(
        account_authorization_details_cfg)
    results = authorization_details.results
    print(f"Top-level keys of results dictionary: {results.keys()}")
    # Write the results
    if os.path.exists(results_file):
        os.remove(results_file)
    with open(results_file, "w") as file:
        json.dump(results, file, indent=4)
    print(f"Wrote new example IAM data file to: {results_file}")
    # print(json.dumps(results, indent=4))
    return results
예제 #10
0
 def test_principal_policy_mapping(self):
     authorization_details = AuthorizationDetails(
         example_authz_details_for_overrides_complete)
     expected_results = [{
         "Principal": "GOAT",
         "Type": "Group",
         "PolicyType": "Managed",
         "ManagedBy": "AWS",
         "PolicyName": "AdministratorAccess",
         "Comment": None
     }, {
         "Principal": "GOAT",
         "Type": "Role",
         "PolicyType": "Inline",
         "ManagedBy": "Customer",
         "PolicyName": "SsmOnboardingInlinePolicy",
         "Comment": None
     }, {
         "Principal": "MyOtherRole",
         "Type": "Role",
         "PolicyType": "Inline",
         "ManagedBy": "Customer",
         "PolicyName": "InlinePolicyForTestingOverrides",
         "Comment": None
     }, {
         "Principal": "BlakeBortles",
         "Type": "User",
         "PolicyType": "Managed",
         "ManagedBy": "AWS",
         "PolicyName": "AdministratorAccess",
         "Comment": "Group Membership"
     }]
     print(
         json.dumps(authorization_details.principal_policy_mapping,
                    indent=4))
     self.assertListEqual(authorization_details.principal_policy_mapping,
                          expected_results)
예제 #11
0
 def test_new_principal_policy_mapping(self):
     authorization_details = AuthorizationDetails(cfg, exclusions)
     results = authorization_details.results
     # print(json.dumps(results))
     self.assertDictEqual(expected_data_file, results)
예제 #12
0
def scan_account_authorization_file(input_file, exclusions_cfg, output,
                                    all_access_levels, skip_open_report):
    """
    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.
    """
    with open(input_file) as f:
        contents = f.read()
        account_authorization_details_cfg = json.loads(contents)
        check_authorization_details_schema(account_authorization_details_cfg)

    # Scan authorization details. Defaults to modify-only permissions
    if all_access_levels:
        logger.debug(
            "--all-access-levels selected. Identifying all actions that are not leveraging resource "
            "constraints...")
        authorization_details = AuthorizationDetails(
            account_authorization_details_cfg)
        results = authorization_details.missing_resource_constraints(
            exclusions_cfg, modify_only=False)
    else:
        logger.debug(
            "--all-access-levels NOT selected. Identifying modify-only actions that are not leveraging "
            "resource constraints...")
        authorization_details = AuthorizationDetails(
            account_authorization_details_cfg)
        results = authorization_details.missing_resource_constraints(
            exclusions_cfg, modify_only=True)

    principal_policy_mapping = authorization_details.principal_policy_mapping

    account_name = Path(input_file).stem

    # 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
    output_directory = output

    # Account metadata
    account_metadata = {
        "account_name":
        account_name,
        "account_id":
        account_id,
        "customer_managed_policies":
        len(authorization_details.customer_managed_policies_in_use),
        "aws_managed_policies":
        len(authorization_details.aws_managed_policies_in_use),
    }

    # Raw data file
    raw_data_file = os.path.join(output, 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, 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)}"
    )

    print("Creating the HTML Report")
    generate_html_report(
        account_metadata,
        results,
        principal_policy_mapping,
        output_directory,
        exclusions_cfg,
        skip_open_report=skip_open_report,
    )
예제 #13
0
    def test_authorization_file_details_missing_constraints(self):
        authz_file = {
            "UserDetailList": [],
            "GroupDetailList": [],
            "RoleDetailList": [],
            "Policies": [{
                "PolicyName":
                "NotYourPolicy",
                "PolicyId":
                "YAAAAASSQUEEEN",
                "Arn":
                "arn:aws:iam::012345678901:policy/NotYourPolicy",
                "Path":
                "/",
                "DefaultVersionId":
                "v9",
                "AttachmentCount":
                1,
                "PermissionsBoundaryUsageCount":
                0,
                "IsAttachable":
                True,
                "CreateDate":
                "2020-01-29 21:24:20+00:00",
                "UpdateDate":
                "2020-01-29 23:23:12+00:00",
                "PolicyVersionList": [{
                    "Document": {
                        "Version":
                        "2012-10-17",
                        "Statement": [{
                            "Sid":
                            "VisualEditor0",
                            "Effect":
                            "Allow",
                            "Action": [
                                "ecr:GetAuthorizationToken",
                                "ecr:UploadLayerPart",
                                "ecr:CompleteLayerUpload", "ecr:PutImage"
                            ],
                            "Resource": ["*"]
                        }]
                    },
                    "VersionId": "v9",
                    "IsDefaultVersion": True,
                    "CreateDate": "2020-01-29 23:23:12+00:00"
                }]
            }, {
                "PolicyName":
                "PolicyForTestingOverrides",
                "PolicyId":
                "PolicyForTestingOverrides",
                "Arn":
                "arn:aws:iam::012345678901:policy/PolicyForTestingOverrides",
                "Path":
                "/",
                "DefaultVersionId":
                "v9",
                "AttachmentCount":
                1,
                "PermissionsBoundaryUsageCount":
                0,
                "IsAttachable":
                True,
                "CreateDate":
                "2020-01-29 21:24:20+00:00",
                "UpdateDate":
                "2020-01-29 23:23:12+00:00",
                "PolicyVersionList": [{
                    "Document": {
                        "Version":
                        "2012-10-17",
                        "Statement": [{
                            "Sid": "VisualEditor0",
                            "Effect": "Allow",
                            "Action": ["s3:CreateBucket"],
                            "Resource": ["arn:aws:s3:::mybucket"]
                        }, {
                            "Sid":
                            "VisualEditor1",
                            "Effect":
                            "Allow",
                            "Action": ["s3:PutObject", "s3:GetObject"],
                            "Resource": ["*"]
                        }]
                    },
                    "VersionId": "v9",
                    "IsDefaultVersion": True,
                    "CreateDate": "2020-01-29 23:23:12+00:00"
                }]
            }]
        }
        authorization_details = AuthorizationDetails(authz_file)
        results = authorization_details.missing_resource_constraints(
            modify_only=False)
        expected_results = [{
            "AccountID":
            "012345678901",
            "ManagedBy":
            "Customer",
            "PolicyName":
            "NotYourPolicy",
            "Type":
            "Policy",
            "Arn":
            "arn:aws:iam::012345678901:policy/NotYourPolicy",
            "ActionsCount":
            3,
            "ServicesCount":
            1,
            "Services": ["ecr"],
            "Actions":
            ["ecr:CompleteLayerUpload", "ecr:PutImage", "ecr:UploadLayerPart"],
            "PolicyDocument": {
                "Version":
                "2012-10-17",
                "Statement": [{
                    "Sid":
                    "VisualEditor0",
                    "Effect":
                    "Allow",
                    "Action": [
                        "ecr:GetAuthorizationToken", "ecr:UploadLayerPart",
                        "ecr:CompleteLayerUpload", "ecr:PutImage"
                    ],
                    "Resource": ["*"]
                }]
            },
            "AssumeRolePolicyDocument":
            None,
            "AssumableByComputeService": [],
            "PrivilegeEscalation": [],
            "DataExfiltrationActions": [],
            "PermissionsManagementActions": []
        }, {
            "AccountID": "012345678901",
            "ManagedBy": "Customer",
            "PolicyName": "PolicyForTestingOverrides",
            "Type": "Policy",
            "Arn":
            "arn:aws:iam::012345678901:policy/PolicyForTestingOverrides",
            "ActionsCount": 2,
            "ServicesCount": 1,
            "Services": ["s3"],
            "Actions": ["s3:GetObject", "s3:PutObject"],
            "PolicyDocument": {
                "Version":
                "2012-10-17",
                "Statement": [{
                    "Sid": "VisualEditor0",
                    "Effect": "Allow",
                    "Action": ["s3:CreateBucket"],
                    "Resource": ["arn:aws:s3:::mybucket"]
                }, {
                    "Sid": "VisualEditor1",
                    "Effect": "Allow",
                    "Action": ["s3:PutObject", "s3:GetObject"],
                    "Resource": ["*"]
                }]
            },
            "AssumeRolePolicyDocument": None,
            "AssumableByComputeService": [],
            "PrivilegeEscalation": [],
            "DataExfiltrationActions": ["s3:GetObject"],
            "PermissionsManagementActions": []
        }]

        # print(json.dumps(results, indent=4))
        self.maxDiff = None
        self.assertListEqual(results, expected_results)
예제 #14
0
 def test_user_principal_attached_managed_policies(self):
     # User with attached managed policies
     authz_cfg = {
         "UserDetailList": [
             {
               "Path": "/",
               "UserName": "******",
               "UserId": "BlakeBortles",
               "Arn": "arn:aws:iam::012345678901:user/BlakeBortles",
               "CreateDate": "2019-12-18 19:10:08+00:00",
               "GroupList": [
                 "GOAT"
               ],
               "AttachedManagedPolicies": [
                 {
                     "PolicyArn": "arn:aws:iam::aws:policy/AdministratorAccess",
                     "PolicyName": "AdministratorAccess"
                 }
                 ],
               "Tags": []
             },
         ],
         "GroupDetailList": [],
         "RoleDetailList": [],
         "Policies": [
             {
                 "PolicyName": "AdministratorAccess",
                 "PolicyId": "ANPAIWMBCKSKIEE64ZLYK",
                 "Arn": "arn:aws:iam::aws:policy/AdministratorAccess",
                 "Path": "/",
                 "DefaultVersionId": "v1",
                 "AttachmentCount": 1,
                 "PermissionsBoundaryUsageCount": None,
                 "IsAttachable": True,
                 "CreateDate": "2015-02-06 18:39:46+00:00",
                 "UpdateDate": "2015-02-06 18:39:46+00:00",
                 "PolicyVersionList": [
                     {
                         "Document": {
                             "Version": "2012-10-17",
                             "Statement": [
                                 {
                                     "Effect": "Allow",
                                     "Action": "*",
                                     "Resource": "*"
                                 }
                             ]
                         },
                         "VersionId": "v1",
                         "IsDefaultVersion": True,
                         "CreateDate": "2015-02-06 18:39:46+00:00"
                     }
                 ]
             },
         ]
     }
     authorization_details = AuthorizationDetails(authz_cfg)
     expected_result = ["AdministratorAccess"]
     results = authorization_details.aws_managed_policies_in_use
     # print(json.dumps(results, indent=4))
     self.assertListEqual(results, expected_result)
예제 #15
0
    def test_exclusions_for_service_roles(self):
        """test_exclusions_for_service_roles: Ensuring that exclusions config of service roles are specifically
        skipped, as designed"""
        authz_file = {
            "UserDetailList": [],
            "GroupDetailList": [],
            "RoleDetailList": [
                {
                    "Path":
                    "/aws-service-role/cloudwatch-crossaccount.amazonaws.com/",
                    "RoleName":
                    "AWSServiceRoleForCloudWatchCrossAccount",
                    "RoleId":
                    "LALALALALAALALA",
                    "Arn":
                    "arn:aws:iam::115657980943:role/aws-service-role/cloudwatch-crossaccount.amazonaws.com/AWSServiceRoleForCloudWatchCrossAccount",
                    "CreateDate":
                    "2019-11-07 20:21:23+00:00",
                    "AssumeRolePolicyDocument": {
                        "Version":
                        "2012-10-17",
                        "Statement": [{
                            "Effect": "Allow",
                            "Principal": {
                                "Service":
                                "cloudwatch-crossaccount.amazonaws.com"
                            },
                            "Action": "sts:AssumeRole"
                        }]
                    },
                    "InstanceProfileList": [],
                    "RolePolicyList": [],
                    "AttachedManagedPolicies": [{
                        "PolicyName":
                        "CloudWatch-CrossAccountAccess",
                        "PolicyArn":
                        "arn:aws:iam::aws:policy/aws-service-role/CloudWatch-CrossAccountAccess"
                    }]
                },
            ],
            "Policies": [{
                "PolicyName":
                "CloudWatch-CrossAccountAccess",
                "PolicyId":
                "LALALALALAALALA",
                "Arn":
                "arn:aws:iam::aws:policy/aws-service-role/CloudWatch-CrossAccountAccess",
                # "Arn": "arn:aws:iam::aws:policy/Sup",
                "Path":
                "/aws-service-role/",
                "DefaultVersionId":
                "v1",
                "AttachmentCount":
                1,
                "PermissionsBoundaryUsageCount":
                None,
                "IsAttachable":
                True,
                "CreateDate":
                "2019-07-23 09:59:27+00:00",
                "UpdateDate":
                "2019-07-23 09:59:27+00:00",
                "PolicyVersionList": [{
                    "Document": {
                        "Version":
                        "2012-10-17",
                        # This is fake, I'm just trying to trigger a response
                        "Statement": [{
                            "Action": ["iam:*"],
                            "Resource": ["*"],
                            "Effect": "Allow"
                        }]
                    },
                    "VersionId": "v1",
                    "IsDefaultVersion": True,
                    "CreateDate": "2019-07-23 09:59:27+00:00"
                }]
            }]
        }
        exclusions_cfg = {"policies": ["aws-service-role*"]}
        exclusions = Exclusions(exclusions_cfg)
        authorization_details = AuthorizationDetails(authz_file, exclusions)
        results = authorization_details.results

        expected_results = {
            "groups": {},
            "users": {},
            "roles": {},
            "aws_managed_policies": {},
            "customer_managed_policies": {},
            "inline_policies": {},
            "exclusions": {
                "policies": ["aws-service-role*"]
            },
            "links": {}
        }
        self.assertDictEqual(results, expected_results)
예제 #16
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()
예제 #17
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
예제 #18
0
    def test_authorization_file_details_missing_constraints(self):
        authz_file = {
            "UserDetailList": [
                {
                  "Path": "/",
                  "UserName": "******",
                  "UserId": "BlakeBortles",
                  "Arn": "arn:aws:iam::012345678901:user/BlakeBortles",
                  "CreateDate": "2019-12-18 19:10:08+00:00",
                  "GroupList": [
                    "GOAT"
                  ],
                  "AttachedManagedPolicies": [
                        {
                            "PolicyArn": "arn:aws:iam::012345678901:policy/PolicyForTestingOverrides",
                            "PolicyName": "PolicyForTestingOverrides"
                        },{
                            "PolicyArn": "arn:aws:iam::012345678901:policy/NotYourPolicy",
                            "PolicyName": "NotYourPolicy"
                        }
                  ],
                  "Tags": []
                }
            ],
            "GroupDetailList": [],
            "RoleDetailList": [],
            "Policies": [
                {
                    "PolicyName": "NotYourPolicy",
                    "PolicyId": "YAAAAASSQUEEEN",
                    "Arn": "arn:aws:iam::012345678901:policy/NotYourPolicy",
                    "Path": "/",
                    "DefaultVersionId": "v9",
                    "AttachmentCount": 1,
                    "PermissionsBoundaryUsageCount": 0,
                    "IsAttachable": True,
                    "CreateDate": "2020-01-29 21:24:20+00:00",
                    "UpdateDate": "2020-01-29 23:23:12+00:00",
                    "PolicyVersionList": [
                        {
                            "Document": {
                                "Version": "2012-10-17",
                                "Statement": [
                                    {
                                        "Sid": "VisualEditor0",
                                        "Effect": "Allow",
                                        "Action": [
                                            "ecr:GetAuthorizationToken",
                                            "ecr:UploadLayerPart",
                                            "ecr:CompleteLayerUpload",
                                            "ecr:PutImage"
                                        ],
                                        "Resource": [
                                            "*"
                                        ]
                                    }
                                ]
                            },
                            "VersionId": "v9",
                            "IsDefaultVersion": True,
                            "CreateDate": "2020-01-29 23:23:12+00:00"
                        }
                    ]
                },
                {
                    "PolicyName": "PolicyForTestingOverrides",
                    "PolicyId": "PolicyForTestingOverrides",
                    "Arn": "arn:aws:iam::012345678901:policy/PolicyForTestingOverrides",
                    "Path": "/",
                    "DefaultVersionId": "v9",
                    "AttachmentCount": 1,
                    "PermissionsBoundaryUsageCount": 0,
                    "IsAttachable": True,
                    "CreateDate": "2020-01-29 21:24:20+00:00",
                    "UpdateDate": "2020-01-29 23:23:12+00:00",
                    "PolicyVersionList": [
                        {
                            "Document": {
                                "Version": "2012-10-17",
                                "Statement": [
                                    {
                                        "Sid": "VisualEditor0",
                                        "Effect": "Allow",
                                        "Action": [
                                            "s3:CreateBucket"
                                        ],
                                        "Resource": [
                                            "arn:aws:s3:::mybucket"
                                        ]
                                    },
                                    {
                                        "Sid": "VisualEditor1",
                                        "Effect": "Allow",
                                        "Action": [
                                            "s3:PutObject",
                                            "s3:GetObject"
                                        ],
                                        "Resource": [
                                            "*"
                                        ]
                                    }
                                ]
                            },
                            "VersionId": "v9",
                            "IsDefaultVersion": True,
                            "CreateDate": "2020-01-29 23:23:12+00:00"
                        }
                    ]
                }
            ]
        }
        authorization_details = AuthorizationDetails(authz_file)
        results = authorization_details.results
        expected_results = {
            "groups": {},
            "users": {
                "BlakeBortles": {
                    "arn": "arn:aws:iam::012345678901:user/BlakeBortles",
                    "create_date": "2019-12-18 19:10:08+00:00",
                    "id": "BlakeBortles",
                    "name": "BlakeBortles",
                    "inline_policies": {},
                    "groups": {},
                    "path": "/",
                    "customer_managed_policies": {
                        "PolicyForTestingOverrides": "PolicyForTestingOverrides",
                        "YAAAAASSQUEEEN": "NotYourPolicy"
                    },
                    "aws_managed_policies": {},
                    "is_excluded": False
                }
            },
            "roles": {},
            "aws_managed_policies": {},
            "customer_managed_policies": {
                "YAAAAASSQUEEEN": {
                    "PolicyName": "NotYourPolicy",
                    "PolicyId": "YAAAAASSQUEEEN",
                    "Arn": "arn:aws:iam::012345678901:policy/NotYourPolicy",
                    "Path": "/",
                    "DefaultVersionId": "v9",
                    "AttachmentCount": 1,
                    "IsAttachable": True,
                    "CreateDate": "2020-01-29 21:24:20+00:00",
                    "UpdateDate": "2020-01-29 23:23:12+00:00",
                    "PolicyVersionList": [
                        {
                            "Document": {
                                "Version": "2012-10-17",
                                "Statement": [
                                    {
                                        "Sid": "VisualEditor0",
                                        "Effect": "Allow",
                                        "Action": [
                                            "ecr:GetAuthorizationToken",
                                            "ecr:UploadLayerPart",
                                            "ecr:CompleteLayerUpload",
                                            "ecr:PutImage"
                                        ],
                                        "Resource": [
                                            "*"
                                        ]
                                    }
                                ]
                            },
                            "VersionId": "v9",
                            "IsDefaultVersion": True,
                            "CreateDate": "2020-01-29 23:23:12+00:00"
                        }
                    ],
                    "PrivilegeEscalation": [],
                    "DataExfiltration": [],
                    "ResourceExposure": [],
                    "ServiceWildcard": [],
                    "CredentialsExposure": [
                        "ecr:GetAuthorizationToken"
                    ],
                    "InfrastructureModification": [
                        "ecr:CompleteLayerUpload",
                        "ecr:PutImage",
                        "ecr:UploadLayerPart"
                    ],
                    "is_excluded": False
                },
                "PolicyForTestingOverrides": {
                    "PolicyName": "PolicyForTestingOverrides",
                    "PolicyId": "PolicyForTestingOverrides",
                    "Arn": "arn:aws:iam::012345678901:policy/PolicyForTestingOverrides",
                    "Path": "/",
                    "DefaultVersionId": "v9",
                    "AttachmentCount": 1,
                    "IsAttachable": True,
                    "CreateDate": "2020-01-29 21:24:20+00:00",
                    "UpdateDate": "2020-01-29 23:23:12+00:00",
                    "PolicyVersionList": [
                        {
                            "Document": {
                                "Version": "2012-10-17",
                                "Statement": [
                                    {
                                        "Sid": "VisualEditor0",
                                        "Effect": "Allow",
                                        "Action": [
                                            "s3:CreateBucket"
                                        ],
                                        "Resource": [
                                            "arn:aws:s3:::mybucket"
                                        ]
                                    },
                                    {
                                        "Sid": "VisualEditor1",
                                        "Effect": "Allow",
                                        "Action": [
                                            "s3:PutObject",
                                            "s3:GetObject"
                                        ],
                                        "Resource": [
                                            "*"
                                        ]
                                    }
                                ]
                            },
                            "VersionId": "v9",
                            "IsDefaultVersion": True,
                            "CreateDate": "2020-01-29 23:23:12+00:00"
                        }
                    ],
                    "PrivilegeEscalation": [],
                    "DataExfiltration": [
                        "s3:GetObject"
                    ],
                    "ResourceExposure": [],
                    "ServiceWildcard": [],
                    "CredentialsExposure": [],
                    "InfrastructureModification": [
                        "s3:GetObject",
                        "s3:PutObject"
                    ],
                    "is_excluded": False
                }
            },
            "inline_policies": {},
            "exclusions": {
                "policies": [
                    "AWSServiceRoleFor*",
                    "*ServiceRolePolicy",
                    "*ServiceLinkedRolePolicy",
                    "AdministratorAccess",
                    "service-role*",
                    "aws-service-role*",
                    "/service-role*",
                    "/aws-service-role*",
                    "MyRole"
                ],
                "roles": [
                    "service-role*",
                    "aws-service-role*"
                ],
                "users": [
                    ""
                ],
                "groups": [
                    ""
                ],
                "include-actions": [
                    "s3:GetObject",
                    "ssm:GetParameter",
                    "ssm:GetParameters",
                    "ssm:GetParametersByPath",
                    "secretsmanager:GetSecretValue",
                    "rds:CopyDBSnapshot",
                    "rds:CreateDBSnapshot"
                ],
                "exclude-actions": [
                    ""
                ]
            }
        }

        # print(json.dumps(results, indent=4))
        self.maxDiff = None
        self.assertDictEqual(results, expected_results)
예제 #19
0
def scan_account_authorization_file(input_file, exclusions, output,
                                    all_access_levels,
                                    skip_open_report):  # 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.
    """
    with open(input_file) as f:
        contents = f.read()
        account_authorization_details_cfg = json.loads(contents)
        check_authorization_details_schema(account_authorization_details_cfg)

    # Scan authorization details. Defaults to modify-only permissions
    if all_access_levels:
        logger.debug(
            "--all-access-levels selected. Identifying all actions that are not leveraging resource "
            "constraints...")
        authorization_details = AuthorizationDetails(
            account_authorization_details_cfg)
        results = authorization_details.missing_resource_constraints(
            exclusions, modify_only=False)
    else:
        logger.debug(
            "--all-access-levels NOT selected. Identifying modify-only actions that are not leveraging "
            "resource constraints...")
        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)

    account_name = Path(input_file).stem

    # 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
    output_directory = output

    # Account metadata
    account_metadata = {
        "account_name":
        account_name,
        "account_id":
        account_id,
        "customer_managed_policies":
        len(authorization_details.customer_managed_policies_in_use),
        "aws_managed_policies":
        len(authorization_details.aws_managed_policies_in_use),
    }

    # Raw data file
    raw_data_file = os.path.join(output, 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, 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)}"
    )

    print("Creating the HTML Report")
    generate_html_report(
        account_metadata,
        results,
        principal_policy_mapping,
        output_directory,
        exclusions.config,
        skip_open_report=skip_open_report,
    )