What the heck are Permission Boundaries?

 ·  ☕ 4 min read

How to use this lesser known feature of AWS IAM


A competent understanding of IAM Polices and how they affect the permissions of any User/Role they are attached to is important to understand Permission Boundaries.

Introducing Permissions Boundaries

Boundaries are applied to Users and Roles and they act as the upper-limit (like a Boundary… funny that) to the User/Role, regardless of what might be granted by the attached IAM Policies.

Any IAM Policy could be a Permission Boundary, it’s when it’s attached to the User/Role as a Boundary that it exhibits the different behaviour.

What AWS calls effective permissions of a User/Role is the intersection of what the attached IAM Policies and the Permission Boundary allows.

IAM permissions Venn Diagram

The Boundary does not grant permissions itself (that is still the responsibility of the IAM Policies) but if an action is not permitted by the Boundary then the User/Role is denied that action; even if the IAM Policy explicitly allows it.

By the way: the default Boundary allows all actions on all resources and therefore the only control on the User/Role side is what is granted explicitly in any attached IAM Policies.

The point of Boundaries

By now you might be wondering “why bother with Permission Boundaries”?
If all you are doing is Allowing All, with a Deny on certain actions or only Allowing explicit actions, could the same be done by being careful with the IAM Policies you attach to your Roles, Users and Groups?
The answer is yes, but there is an additional feature of Permissions Boundaries that is not possible with traditional IAM Policies.

You can deny creation of a User/Role if a Boundary is not attached to it on creation.

This simple feature means that you can deny a User/Role the ability to create additional Users or Roles with more permissions than themselves.
This can prevent a privilege escalation vulnerability, where a user with non-admin permissions can create a new user with admin permissions and then switch to that new admin user.
Or you can have multiple admins that can’t delete other admins and take sole control of the account (although root user could recover it).

This is achieved by attaching to the User/Role a policy that explicitly denies the creation of a User/Role unless a certain Boundary applied to that User/Role. This Deny statement could also be a Boundary itself.

SCPs (Service Control Policies) are very similar to Permission Boundaries in that they defone an upper limit to a user or role’s permissions; the difference is that SCPs are attached to an AWS Account or AWS Organization OU thus they are account-wide and not attached to a specific User/Role.

Example Boundary

The below IAM Policy is intended to be used as a Permission Boundary (called “my-permission-boundary”).
It has a number of statements with special purposes. Most are to prevent subverting the Boundary itself.

  • AllowAll - This pushes responsibility to the allowed permissions to the IAM Policy attached to the User/Role (other than the DENY statements later in this policy).
  • NoBoundaryPolicyEdit - Prevent a User/Role with this Boundary from modifying this Boundary (and therefore there own permission upper-bound).
  • NoBoundaryUserDelete - Prevent deleting the Boundary.
  • EnforcePermissionsBoundaryApplication - Prevent creation of Users or Role unless the same Boundary is also attached. This ensures that any User/Role that is created is subject to the same restrictions (forward-enforcement).
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AllowAll",
            "Effect": "Allow",
            "Action": "*",
            "Resource": "*"
        },
        {
            "Sid": "NoBoundaryPolicyEdit",
            "Effect": "Deny",
            "Action": [
                "iam:CreatePolicyVersion",
                "iam:DeletePolicy",
                "iam:DeletePolicyVersion",
                "iam:SetDefaultPolicyVersion"
            ],
            "Resource": [
                "arn:aws:iam::*:policy/my-permission-boundary"
            ]
        },
        {
            "Sid": "NoBoundaryUserDelete",
            "Effect": "Deny",
            "Action": "iam:DeleteUserPermissionsBoundary",
            "Resource": "*"
        },
        {
            "Sid": "EnforcePermissionsBoundaryApplication",
            "Effect": "Deny",
            "Action": [
                "iam:CreateRole",
                "iam:DeleteRolePolicy",
                "iam:AttachRolePolicy",
                "iam:DetachRolePolicy",
                "iam:PutRolePermissionsBoundary",
                "iam:PutRolePolicy",
                "iam:CreateUser",
                "iam:DeleteUserPolicy",
                "iam:AttachUserPolicy",
                "iam:DetachUserPolicy",
                "iam:PutUserPermissionsBoundary",
                "iam:PutUserPolicy"
            ],
            "Resource": "*",
            "Condition": {
                "StringNotEquals": {
                    "iam:PermissionsBoundary": "arn:aws:iam::<ACCOUNT ID>:policy/my-permission-boundary"
                }
            }
        }
    ]
}

Kieran Goldsworthy
WRITTEN BY
Kieran Goldsworthy
Cloud Engineer and Architect


What's on this Page