Adventures with Boundary Policies in AWS IAM

John Byrd
4 min readDec 16, 2018

Being the gatekeeper to identity in AWS is something that gets very old very quickly. As developers ramp up their cloud adoption, the person holding IAM hostage is quickly identified as a blocker. To remove myself from being that block, I’ve started to implement a solution that is inspired by (or a rip off of) Brigid Johnson’s blog post and re:Invent talk (here and here, respectively)

This is meant as a rough overview of my experiences in hopes to help clarify, fill in the gaps, or provide ideas around the IAM service. We’ll begin by providing users a means to create IAM resources with some simple guardrails and then take it a step further to manage the permissions of the roles being created by the users.

First, take a Developer role that has the PowerUserAccess* AWS managed policy attached and create an inline policy to add the ability to create roles and policies. Then, limit the roles and policies to a specific key — I’m using “example-” in the policy below. I’ve added some additional permissions that I’ve found to be needed for most day to day use beyond just creating roles as we’re discussing here.

{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor1",
"Effect": "Allow",
"Action": [
"iam:ListPolicies",
"iam:GetPolicyVersion",
"iam:PassRole",
"iam:GetPolicy",
"iam:GenerateServiceLastAccessedDetails",
"iam:RemoveRoleFromInstanceProfile",
],
"Resource": "*"
},
{
"Sid": "VisualEditor2",
"Effect": "Allow",
"Action": [
"iam:CreateInstanceProfile",
"iam:DeleteInstanceProfile",
"iam:GetRole",
"iam:ListRoleTags",
"iam:RemoveRoleFromInstanceProfile",
"iam:DeleteRole",
"iam:PutRolePolicy",
"iam:AddRoleToInstanceProfile",
"iam:CreatePolicy",
"iam:ListPolicyVersions",
"iam:ListAttachedRolePolicies",
"iam:DeleteRolePolicy",
"iam:ListRolePolicies",
"iam:GetRolePolicy",
"iam:CreatePolicyVersion",
"iam:DetachRolePolicy",
"iam:CreateRole",
"iam:AttachRolePolicy"
],
"Resource": [
"arn:aws:iam::<acctid>:policy/example-*",
"arn:aws:iam::<acctid>:role/example-*",
"arn:aws:iam::<acctid>:instance-profile/example-*"
]
}
]
}

*Managed PowerUserAccess policy grants access to all services except iam and organizations. It does grant ListRoles, CreateServiceLinkedRole, DeleteServiceLinkedRole IAM permissions, which is why you don’t see those listed here.

Once the inline policy is applied, the developer role will now be able to create roles and policies that match the defined key in the policy (“example-” here).

For this example, since I’m pretending to be a developer, I’m going to slap on AdministratorAccess, because I can and who’s going to stop me?

When you go to name the role, unless it starts with the “example-” prefix, you’re prompted with a permissions error.

However, once the prefix is added, the role is created without a problem.

To limit the roles the Developer is creating, we’re going to use Permission Boundaries.

In this example, we don’t want the roles developers are creating to have access to Create or Delete anything related to IAM.

To do this, we begin by creating a policy that we will use to set boundaries on the new roles being created by the developer. Here, we use NotAction to provide *:* permissions except for those listed. Inversely, using Action here instead results in a whitelist of permissions instead of the effective blacklist created here. The developers will need to be required to attach this policy to all the new roles being created.

{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"NotAction": [
"iam:Create*",
"iam:Delete*"
],
"Resource": "*"
}
]
}

To assist in this effort, we will modify the policy being used by the Developer to include a condition (in italics below) that any role creation or policy modification must include the boundary policy.

{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"iam:DetachRolePolicy",
"iam:CreateRole",
"iam:AttachRolePolicy"
],
"Resource": "arn:aws:iam::<
acctid>:role/example-*",
"Condition": {
"StringEquals": {
"iam:PermissionsBoundary": "arn:aws:iam::<
acctid>:policy/BoundaryPolicy"
}
}
},

{
"Sid": "VisualEditor1",
"Effect": "Allow",
"Action": [
"iam:ListPolicies",
"iam:GetPolicyVersion",
"iam:PassRole",
"iam:GetPolicy",
"iam:GenerateServiceLastAccessedDetails",
"iam:RemoveRoleFromInstanceProfile"
],
"Resource": "*"
},
{
"Sid": "VisualEditor2",
"Effect": "Allow",
"Action": [
"iam:CreateInstanceProfile",
"iam:DeleteInstanceProfile",
"iam:GetRole",
"iam:ListRoleTags",
"iam:RemoveRoleFromInstanceProfile",
"iam:DeleteRole",
"iam:PutRolePolicy",
"iam:AddRoleToInstanceProfile",
"iam:CreatePolicy",
"iam:ListPolicyVersions",
"iam:ListAttachedRolePolicies",
"iam:DeleteRolePolicy",
"iam:ListRolePolicies",
"iam:GetRolePolicy",
"iam:CreatePolicyVersion"
],
"Resource": [
"arn:aws:iam::<acctid>:policy/example-*",
"arn:aws:iam::<acctid>:role/example-*",
"arn:aws:iam::<acctid>:instance-profile/example-*"
]
}
]
}

Now, the Developer will need to attach this new policy to any new roles created. Otherwise, they will be faced with a permission denied for CreateRole.

--

--

John Byrd
John Byrd

Written by John Byrd

Modernizing companies’ AWS security and governance programs at scale.

No responses yet