IAM Policy Master on AWS (re:Invent 2018)

Policy Types and use cases

  • AWS Organizations
    • Use: Guardrails to disable service access on the principals of the account
    • Service control policies (SCP)
  • AWS Identity and Access Management
    • Use: Grant granular permissions on IAM principals (users and roles) and control the maximum permissions they can set
    • Permission policies
    • Permission boundaries
      • Scale and delegate permissions management to developers safely
      • Control the maximum permissions employees can grant
  • AWS Security Token Service (STS)
    • Use: Reduce general shared permissions further
    • Scoped-down policies
  • Specific AWS Resources
    • Use: Cross-account access and to control access from the resource
    • Resource-based policies
  • VPC Endpoints
    • Use: Controls access to the service with a VPC endpoint
    • Endpoint policies

Policy resolution within an account

Final Policy = [SCP] AND ([IAM Policies] OR [Resource-based Policies]) where: [IAM Policies] = ?[Permission Boundary] AND [Permission Policy (managed / inline)] AND [Scope-down Policy]

Policy resolution across accounts

Final Policy = [SCP] AND ([IAM Policies] AND [Resource-based Policies]) where: [IAM Policies] = ?[Permission Boundary] AND [Permission Policy (managed / inline)] AND [Scope-down Policy]

Example use cases

1. Set permission guardrails across accounts

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "DenyUnapprovedAction",
            "Effect": "Deny",
            "Action" : [
                "ds:*",
                "iam:createUser",
                "cloudtrail:stopLogging"
            ],
            "Resource": [
                "*"
            ]
        }
    ]
}

2. Control creation of resources to regions

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action" : [
                "secretsmanager:*",
                "lambda:*",
                "s3:PutObject",
                "s3:GetObject",
                "s3:DeleteObject",
            ],
            "Resource": [
                "*"
            ],
            "Condition": {
                "StringEquals": {
                    "aws:RequestedRegion": ["us-west-1", "us-west-2"]
                }
            }
        },
        {
            "Effect": "Allow",
            "Action" : [
                "ec2:RunInstances"
            ],
            "Resource": [
                "arn:aws:ec2:*:*::subnet/*",
                "arn:aws:ec2:*:*::key-pair/*",
                "arn:aws:ec2:*:*::instance/*",
                "arn:aws:ec2:*:*::snapshot/*",
                "arn:aws:ec2:*:*::launch-template/*",
                "arn:aws:ec2:*:*::volume/*",
                "arn:aws:ec2:*:*::security-group/*",
                "arn:aws:ec2:*:*::placement-group/*",
                "arn:aws:ec2:*:*::network-interface/*",
                "arn:aws:ec2:*:*::image/*",
                
            ],
            "Condition": {
                "StringEquals": {
                    "aws:RequestedRegion": ["us-west-1", "us-west-2"]
                }
            }
        },
        {
            "Effect": "Allow",
            "Action": [
                "ec2:Describe",
                "ec2:Get",
                "s3:ListBucket",
                "s3:ListAllBuckets",
                "iam:list"
            ],
            "Resource": "*"
        }
    ]
}

3. Enable developers to create roles safely

Enable your developers to create IAM roles and pass to EC2 and Lambda, but ensure they cannot exceed their own permissions

Solution (using Permission Boundaries):

  1. Allow create managed policies
  2. Allow create role, but only with specific permission boundary
  3. Allow attach managed policies, but only to roles with specific permission boundary
  4. Allow passRole for these roles using a naming requirement

In this example, the role created should have unicorns prefix

{
    "Effect": "Allow",
    "Action": [
        "iam:CreatePolicy",
        "iam:CreatePolicyVersion",
        "iam:DeletePolicyVersion"
    ],
    "Resource": "arn:aws:iam::1234567890:policy/unicorns-*"
}
{
    "Effect": "Allow",
    "Action": [
        "iam:DetachRolePolicy",
        "iam:CreateRole",
        "iam:AttachRolePolicy"
    ],
    "Resource": "arn:aws:iam::1234567890:role/unicorns-*",
    "Condition": {
        "StringEquals": {
            "iam:PermissionsBoundary": "arn:aws:iam:1234567890:policy/region-restriction"
        }
    }
}

4. Use tags to scale permission management

Enable developers working on Dorky project and the sneaky project to manage their own resources without also managing the other project’s.

Solution:

Use:

  • RequestTag - condition to require tag value during create actions
  • ResourceTag - control access to resources based on a tag that exists on resource
  1. Allow users to create tags when creating resources, but require specific tags when users create resources

arn:aws:ec2:*:*::instance/* Resource was removed from first policy and expanded in the one below

{
    "Effect": "Allow",
    "Action" : [
        "ec2:RunInstances"
    ],
    "Resource": [
        "arn:aws:ec2:*:*::subnet/*",
        "arn:aws:ec2:*:*::key-pair/*",
        "arn:aws:ec2:*:*::snapshot/*",
        "arn:aws:ec2:*:*::launch-template/*",
        "arn:aws:ec2:*:*::volume/*",
        "arn:aws:ec2:*:*::security-group/*",
        "arn:aws:ec2:*:*::placement-group/*",
        "arn:aws:ec2:*:*::network-interface/*",
        "arn:aws:ec2:*:*::image/*",
        
    ],
    "Condition": {
        "StringEquals": {
            "aws:RequestedRegion": ["us-west-1", "us-west-2"]
        }
    }
}
{
    "Effect": "Allow",
    "Action" : [
        "ec2:CreateTags"
    ],
    "Resource": [
        "*"
    ],
    "Condition": {
        "StringEquals": {
            "ec2:CreateAction": "RunInstances"
        }
    }
}
{
    "Effect": "Allow",
    "Action" : [
        "ec2:RunInstances"
    ],
    "Resource": [
        "arn:aws:ec2:*:*:instance/*"
    ],
    "Condition": {
        "ForAllValues:StringEquals": {
            "aws:TagKeys": ["project", "name"]
        },
        "StringEquals": {
            "aws:RequestTag/project": ["dorky"],
            "aws:RequestedRegion": ["us-west-1", "us-west-2"]
        }
    }
}

2. Control which existing resources and values developers can tag

{
    "Effect": "Allow",
    "Action" : [
        "ec2:createTags"
    ],
    "Resource": [
        "*"
    ],
    "Condition": {
        "StringEquals": {
            "ec2:ResourceTag/project": ["dorky"]
        },
        "ForAllValues:StringEquals": {
            "aws:TagKeys": ["project", "name"]
        },
        "StringEqualsIfExists": {
            "aws:RequestTag/project": ["dorky"]
        }
    }
}

3. Control resources users can manage based on tag values

Users with dorky tag can start/stop instances:

{
    "Effect": "Allow",
    "Action" : [
        "ec2:StartInstances",
        "ec2:StopInstances"
    ],
    "Resource": [
        "*"
    ],
    "Condition": {
        "StringEquals": {
            "ec2:ResourceTag/project": ["dorky"]
        }
    }
}

5. Utilize PrincipalTags in IAM policies

Policies can be adjusted to have a single general policy and tagging users. This can be achieved using ${aws:PrincipalTag/project}.

{
    "Effect": "Allow",
    "Action" : [
        "ec2:RunInstances"
    ],
    "Resource": [
        "arn:aws:ec2:*:*:instance/*"
    ],
    "Condition": {
        "ForAllValues:StringEquals": {
            "aws:TagKeys": ["project", "name"]
        },
        "StringEquals": {
            "aws:RequestTag/project": ["${aws:PrincipalTag/project}"],
            "aws:RequestedRegion": ["us-west-1", "us-west-2"]
        }
    }
}