def audit(policy):
    allowed_actions = policy.get_allowed_actions()

    try:
        config_resources = policy.config["SENSITIVE_ACCESS"]["resources"]
    except KeyError:
        config_resources = {}

    sensitive_resources = defaultdict(list)
    for item in config_resources:
        action = list(item.keys())[0]
        expanded_action = _expand_action(action)
        resources = list(item.values())[0]

        sensitive_resources[expanded_action].extend(resources)

    action_resources = {}
    for action in allowed_actions:
        expanded_action = _expand_action(action)
        service, operation = expanded_action.split(":")
        action_resources[expanded_action] = policy.get_allowed_resources(
            service, operation)

    for action in action_resources:
        for action_resource in action_resources[action]:
            for sensitive_resource in sensitive_resources[action]:
                if is_arn_match("object", action_resource, sensitive_resource):
                    policy.add_finding(
                        "SENSITIVE_ACCESS",
                        location={
                            "resource": action_resource,
                            "actions": action
                        },
                    )
Beispiel #2
0
def get_privilege_statements(policy_doc, privilege_matches, resource_arn,
                             principal, policy_identifier):
    policy = parliament.policy.Policy(policy_doc)
    policy.analyze()

    policy_privilege_matches = []

    for privilege_match in privilege_matches:
        references = policy.get_references(privilege_match["privilege_prefix"],
                                           privilege_match["privilege_name"])

        statements_for_resource = []
        for reference in references:
            expanded_reference = replace_principal_variables(
                reference, principal)
            # TODO I need to do something for NotResource and NotAction
            if parliament.is_arn_match(privilege_match["resource_type"],
                                       expanded_reference, resource_arn):
                # We now have a bunch of statements that match the privileges and resource of interest.
                # Now we need to check if the statement is allowed by its conditions.
                # We'll append the allowed statements to a second list, and then swap that list in.
                stmts = references[reference]
                condition_allowed_stmts = []
                for stmt in stmts:
                    stmt.set_policy_identifier(policy_identifier)
                    allowed_by_conditions = True
                    for condition_function in stmt.stmt.get("Condition", {}):
                        condition_values = stmt.stmt["Condition"][
                            condition_function]
                        condition_result = get_condition_result(
                            condition_function,
                            condition_values,
                            resource_arn,
                            principal,
                        )
                        # TODO Need to do something different for Deny, to avoid false negatives
                        if condition_result is not None:
                            if condition_result == False:
                                allowed_by_conditions = False
                                break
                    if allowed_by_conditions:
                        condition_allowed_stmts.append(stmt)
                references[reference] = condition_allowed_stmts

                statements_for_resource.extend(references[reference])
        if len(statements_for_resource) == 0:
            continue

        policy_privilege_matches.append({
            "privilege":
            privilege_match,
            "matching_statements":
            statements_for_resource,
        })

    return policy_privilege_matches
def audit(policy):
    action_resources = {}
    for action in expand_action("s3:*"):
        # Iterates through a list of containing elements such as
        # {'service': 's3', 'action': 'GetObject'}
        action_name = "{}:{}".format(action["service"], action["action"])
        action_resources[action_name] = policy.get_allowed_resources(
            action["service"], action["action"])

    for action_name in action_resources:
        resources = action_resources[action_name]
        for r in resources:
            if is_arn_match(
                    "object", "arn:aws:s3:::secretbucket*", r) or is_arn_match(
                        "object", "arn:aws:s3:::othersecretbucket*", r):
                policy.add_finding(
                    "SENSITIVE_BUCKET_ACCESS",
                    location={
                        "action": action_name,
                        "resource": r
                    },
                )
Beispiel #4
0
 def test_arn_match(self):
     assert_true(is_arn_match("object", "arn:*:s3:::*/*", "arn:*:s3:::*/*"))
     assert_true(is_arn_match("object", "*", "arn:*:s3:::*/*"))
     assert_true(is_arn_match("object", "arn:*:s3:::*/*", "*"))
     assert_true(
         is_arn_match("object", "arn:*:s3:::*/*", "arn:aws:s3:::*personalize*")
     )
     assert_true(
         is_arn_match("bucket", "arn:*:s3:::mybucket", "arn:*:s3:::mybucket")
     )
     assert_false(
         is_arn_match("bucket", "arn:*:s3:::mybucket", "arn:*:s3:::mybucket/*"),
         "Bucket and object types should not match",
     )
     assert_false(
         is_arn_match("object", "arn:*:s3:::*/*", "arn:aws:s3:::examplebucket"),
         "Object and bucket types should not match",
     )
     assert_true(
         is_arn_match("bucket", "arn:*:s3:::mybucket*", "arn:*:s3:::mybucket2")
     )
     assert_true(is_arn_match("bucket", "arn:*:s3:::*", "arn:*:s3:::mybucket2"))
     assert_false(
         is_arn_match(
             "object", "arn:*:s3:::*/*", "arn:aws:logs:*:*:/aws/cloudfront/*"
         )
     )
     assert_false(
         is_arn_match(
             "object", "arn:aws:s3:::*/*", "arn:aws:logs:*:*:/aws/cloudfront/*"
         )
     )
     assert_true(
         is_arn_match(
             "cloudfront",
             "arn:aws:logs:*:*:/aws/cloudfront/*",
             "arn:aws:logs:us-east-1:000000000000:/aws/cloudfront/test",
         )
     )
Beispiel #5
0
 def test_arn_match_s3_withregion(self):
     assert_false(
         is_arn_match("object", "arn:*:s3:::*/*",
                      "arn:aws:s3:us-east-1::bucket1/*"))
Beispiel #6
0
 def test_arn_match_cloudtrail_emptysegments(self):
     assert_false(
         is_arn_match("cloudtrail", "arn:*:cloudtrail:*:*:trail/*",
                      "arn:::::trail/my-trail"))
Beispiel #7
0
 def test_arn_match_apigw_withaccount(self):
     assert_false(
         is_arn_match(
             "apigateway", "arn:*:apigateway:*::*",
             "arn:aws:apigateway:us-east-1:123412341234:/restapis/a123456789/*"
         ))
Beispiel #8
0
 def test_arn_match_apigw_emptysegments(self):
     assert_false(
         is_arn_match("apigateway", "arn:*:apigateway:*::*",
                      "arn:aws:apigateway:::/restapis/a123456789/*"))
Beispiel #9
0
 def test_arn_match_iam_withregion(self):
     assert_false(
         is_arn_match("role", "arn:*:iam::*:role/*",
                      "arn:aws:iam:us-east-1::role/my-role"))
Beispiel #10
0
 def test_arn_match_iam_emptysegments(self):
     assert_false(
         is_arn_match("role", "arn:*:iam::*:role/*",
                      "arn:aws:iam:::role/my-role"))
Beispiel #11
0
 def test_arn_match_s3_withaccount(self):
     assert_false(
         is_arn_match("object", "arn:*:s3:::*/*",
                      "arn:aws:s3::123412341234:bucket1/*"))