AWS IAM Policy Role Mapping


Description

This policy validates that policies that have been explicitly configured to be set to certain roles are still attached to those roles.

Query · python

from panther_base_helpers import deep_get

# This is a mapping of what policies must be attached to what roles in the account.
# The mapping is keyed by string policy names to tuples of role names. Ordering doesn't matter.
# Example:
# POLICY_ROLE_MAPPINGS = {
#   'ExamplePolicyName1': ('ExampleRoleName1', 'ExampleRoleName2', 'ExampleRoleName3'),
#   'ExamplePolicyName2': ('ExampleRoleName1', 'ExampleRoleName3', 'ExampleRoleName4'),
# }
POLICY_ROLE_MAPPINGS = {
    "TestPolicyName": ("TestRole1", "TestRole2"),
}


def policy(resource):
    # Check if there are any required roles for this policy to be attached to
    if resource["PolicyName"] not in POLICY_ROLE_MAPPINGS:
        return True

    # Check if this policy is attached to any roles
    if deep_get(resource, "Entities", "PolicyRoles") is None:
        return False

    # Build the list of role names this policy is actually attached to
    roles_attached = [
        role["RoleName"] for role in deep_get(resource, "Entities", "PolicyRoles", default=[])
    ]

    # For each required role, ensure that role has the policy attached
    for role_needed in POLICY_ROLE_MAPPINGS[resource["PolicyName"]]:
        if role_needed not in roles_attached:
            return False
    return True

Analyst notes

https://docs.runpanther.io/alert-runbooks/built-in-policies/aws-iam-policy-role-mapping-is-respected

Raw source AWS IAM Policy Role Mapping · Panther Python
Esc
Published by panther-labs/panther-analysis ↗, licensed under Apache 2.0 ↗. Reproduced here unmodified.
AnalysisType: policy
Filename: aws_iam_policy_role_mapping.py
PolicyID: "AWS.IAM.Policy.RoleMapping"
DisplayName: "AWS IAM Policy Role Mapping"
Enabled: false
ResourceTypes:
  - AWS.IAM.Policy
Tags:
  - AWS
  - Configuration Required
  - Identity & Access Management
Severity: High
Description: >
  This policy validates that policies that have been explicitly configured to be set to certain roles are still attached to those roles.
Runbook: >
  https://docs.runpanther.io/alert-runbooks/built-in-policies/aws-iam-policy-role-mapping-is-respected
Reference: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles.html
Tests:
  - Name: Policy Applied To Required Roles
    ExpectedResult: true
    Resource:
      {
        "Arn": "arn:aws:iam::123456789012:policy/service-role/example-policy",
        "AttachmentCount": 2,
        "CreateDate": "2019-01-01T00:00:00Z",
        "DefaultVersionId": "v1",
        "Description": null,
        "Entities":
          {
            "PolicyGroups": null,
            "PolicyRoles":
              [
                { "RoleId": "ABCDEFGHIJKLMNOP1", "RoleName": "TestRole1" },
                { "RoleId": "ABCDEFGHIJKLMNOP2", "RoleName": "TestRole2" },
              ],
            "PolicyUsers":
              [{ "UserId": "ABCDEFGHIJKLMNOP", "UserName": "Bobert" }],
          },
        "IsAttachable": true,
        "Path": "/service-role/",
        "PermissionsBoundaryUsageCount": 0,
        "PolicyDocument": "JSON policy document see https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html for details",
        "PolicyId": "ABCDEFGHIJKLMNOP",
        "PolicyName": "TestPolicyName",
        "UpdateDate": "2019-01-01T00:00:00Z",
      }
  - Name: Policy Does Not Have Role Mappings
    ExpectedResult: true
    Resource:
      {
        "Arn": "arn:aws:iam::123456789012:policy/service-role/example-policy",
        "AttachmentCount": 2,
        "CreateDate": "2019-01-01T00:00:00Z",
        "DefaultVersionId": "v1",
        "Description": null,
        "Entities":
          {
            "PolicyGroups": null,
            "PolicyRoles":
              [{ "RoleId": "ABCDEFGHIJKLMNOP", "RoleName": "Example-Role" }],
            "PolicyUsers":
              [{ "UserId": "ABCDEFGHIJKLMNOP", "UserName": "Bobert" }],
          },
        "IsAttachable": true,
        "Path": "/service-role/",
        "PermissionsBoundaryUsageCount": 0,
        "PolicyDocument": "JSON policy document see https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html for details",
        "PolicyId": "ABCDEFGHIJKLMNOP",
        "PolicyName": "Example-Policy",
        "UpdateDate": "2019-01-01T00:00:00Z",
      }
  - Name: Policy Not Applied To Required Roles
    ExpectedResult: false
    Resource:
      {
        "Arn": "arn:aws:iam::123456789012:policy/service-role/example-policy",
        "AttachmentCount": 2,
        "CreateDate": "2019-01-01T00:00:00Z",
        "DefaultVersionId": "v1",
        "Description": null,
        "Entities":
          {
            "PolicyGroups": null,
            "PolicyRoles":
              [{ "RoleId": "ABCDEFGHIJKLMNOP", "RoleName": "Example-Role" }],
            "PolicyUsers":
              [{ "UserId": "ABCDEFGHIJKLMNOP", "UserName": "Bobert" }],
          },
        "IsAttachable": true,
        "Path": "/service-role/",
        "PermissionsBoundaryUsageCount": 0,
        "PolicyDocument": "JSON policy document see https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html for details",
        "PolicyId": "ABCDEFGHIJKLMNOP",
        "PolicyName": "TestPolicyName",
        "UpdateDate": "2019-01-01T00:00:00Z",
      }
  - Name: Policy Not Applied to Anything
    ExpectedResult: true
    Resource:
      {
        "Arn": "arn:aws:iam::123456789012:policy/service-role/example-policy",
        "AttachmentCount": 2,
        "CreateDate": "2019-01-01T00:00:00Z",
        "DefaultVersionId": "v1",
        "Description": null,
        "Entities": null,
        "IsAttachable": true,
        "Path": "/service-role/",
        "PermissionsBoundaryUsageCount": 0,
        "PolicyDocument": "JSON policy document see https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html for details",
        "PolicyId": "ABCDEFGHIJKLMNOP",
        "PolicyName": "Example-Policy",
        "UpdateDate": "2019-01-01T00:00:00Z",
      }


# ------ paired body: aws_iam_policy_role_mapping.py ------

from panther_base_helpers import deep_get

# This is a mapping of what policies must be attached to what roles in the account.
# The mapping is keyed by string policy names to tuples of role names. Ordering doesn't matter.
# Example:
# POLICY_ROLE_MAPPINGS = {
#   'ExamplePolicyName1': ('ExampleRoleName1', 'ExampleRoleName2', 'ExampleRoleName3'),
#   'ExamplePolicyName2': ('ExampleRoleName1', 'ExampleRoleName3', 'ExampleRoleName4'),
# }
POLICY_ROLE_MAPPINGS = {
    "TestPolicyName": ("TestRole1", "TestRole2"),
}


def policy(resource):
    # Check if there are any required roles for this policy to be attached to
    if resource["PolicyName"] not in POLICY_ROLE_MAPPINGS:
        return True

    # Check if this policy is attached to any roles
    if deep_get(resource, "Entities", "PolicyRoles") is None:
        return False

    # Build the list of role names this policy is actually attached to
    roles_attached = [
        role["RoleName"] for role in deep_get(resource, "Entities", "PolicyRoles", default=[])
    ]

    # For each required role, ensure that role has the policy attached
    for role_needed in POLICY_ROLE_MAPPINGS[resource["PolicyName"]]:
        if role_needed not in roles_attached:
            return False
    return True

Detection rules belong to the projects that publish them and remain under their own licenses. This site indexes and links to them; it claims no rights in them.