One of the biggest challenges nearly all engineering organizations face is scaling up without slowing down productivity or compromising on security standards. One area where we at Island encountered this challenge is in controlling access and permissions to AWS without compromising on speed and developer autonomy.
While AWS IAM is packed with features, including support for ABAC (attribute-based access-control), It is often very hard to control who can tag what at scale. In this blog post, we’ll dive into the deep waters of AWS IAM, face its problems and learn how to leverage IAM policies to make ABAC scalable.
This journey walks through parts of a talk I gave at fwd:cloudsec 2022 called "The Power of AWS Tags". I encourage you to watch it here
A journey for developer autonomy
You might be familiar with RBAC (role-based access-control), where access is granted for specific roles on specific resources, which typically requires an administrator to handle permission requests from R&D teams and adjust their roles accordingly. In many organizations - this is a slow process.
On the other hand, if permissions are managed with ABAC (attribute-based access-control), it is easier for the administrator to create rules to match resources by the attributes set on both resource and actor. That way permissions would be granted dynamically, lowering the number of requests from R&D teams and giving teams more autonomy and control over the resources they own.
For example, here is a rule an admin may configure: “users of team: infra can read data from DynamoDB tables tagged with owner: infra.”
This IAM policy would look like this:
Where it gets more complex
What if a bad actor from the infra team had access to modify the tags of his own user or role, or even modify the tags of other DynamoDB tables? Privilege escalation is pretty easy.
In order to mitigate this, we’ll need to protect our owner tag. Let’s write statement like this:
Now, imagine you manage 30 of those tags. Adding a protection statement for each kind of tag sounds pretty cumbersome, and with IAM policies contain as many as 6144 characters, it’s probably a good idea to propose a solution that will allow scaling ABAC with more ease.
Reaching separation of concerns
Looking at the previous policy we came up with, it is easy to distinguish each statement as its own role:
- The first statement is responsible for the access-control logic itself - these kinds of data plane statements are to be distributed so it can be attached to different users, roles or groups or the whole organization, according to the business needs.
- The second statement is responsible for the tagging integrity, the control plane, and we want it to be as generic and centralized. This policy will be attached as an SCP to all accounts in the organization.
Modeling privileged tags
Think of a UNIX filesystem. If I’m granted permissions to my home directory at `/home/itamar` I can write anything under that path, since this is my grant area.
Translating this into IAM, we’ll assign each user/role with a grant path of their own that will define their tagging grant area: if a role’s grant path points to “ctl/v1/admin” then users assuming this role can tag anything under that path, like “ctl/v1/admin/owner” (but not “ctl/v1/bagels”).
Setting the grant path
In our UNIX filesystem we’d have a special file, in which every entry will be a username and its grant area, and no one would have write access to it (unless they’re using sudo). Like this:
Yet in IAM, we don’t have the equivalent of a centralized file, so each principal will hold its own grant path in a tag key (which itself, is a control tag under a meta subtree) that no one can create, delete or modify (unless they use “sudo”, we’ll get to that..). In that case, the tag value will be a pointer to the grant area.
Introducing Control Tags
Control Tags are a privileged set of tags. Any tag that starts with `ctl/` is a Control Tag.
Let’s see the IAM statements behind this control plane:
Let’s break this down:
- We do not allow principals that don’t have grant path configured to tag any control tag.
- We do not allow principals to tag outside of their grant area, or other allowed set of tags, such as “environment”, or “info/*”
Revisiting our first example
It’s THAT simple
Recipe: How to Use Control Tags
- Define the meta grant_path tag key, and set grant paths for your principals.
- Attach the Control Plane as an SCP to your AWS account.
- Define data-plane policies and attach them to your roles/accounts/resources.
NOTE: NEVER SET THE GRANT_PATH TAG TREE TO ANY OF THE PRINCIPALS.
Managing grant paths for users
Say you want to introduce a new team to this scheme, change paths or add a broader grant area for some users.
There are two main options to manage grant paths for your users:
- Using 2PA, 2PA is a concept we created to implement the two-person rule in the cloud. Learn more about it in our fwd:cloudsec lecture!
- Temporarily exempt yourself from the Control Plane SCP. Just add another Condition to assert your user/role can tag under the meta grant path.
To sum up, Control Tags are a great way to manage tagging permissions and enable some developer autonomy in your organization. Check out my entire presentation to learn more tricks Control Tags have up their sleeves