Attribute-based access control in AWS
When a company grows, the number of developers and resources increase, it can be cumbersome to always modify IAM permissions and policies to keep up with the changing environment.
One solution that can ease this problem is attribute-based access control (ABAC).
1. What is ABAC?
Attribute-based access control is an authorization strategy that lets us create fine-grained permissions based on user attributes.
It scales well as the company grows because we won’t necessarily need to create new permissions and policies when a new resource or team member is introduced.
2. ABAC vs RBAC
In the traditional role-based access control (RBAC) we create permissions to the resource, add the permissions to policies, and attach the policies to users or roles.
If we want to follow the least privilege principle (and we do want to follow it), we’ll need to create minimum permissions for the IAM identity to get the job done.
This means that if Identity1 wants to access Resource1 and Identity2 needs Resource2, then we should have two policies, one for Identity1 and Resource1 and another one for Identity2 and Resource2. Resources are specific in the policy, and as a new resource is added or some other changes occur in the application, we’ll need to modify the policy.
With ABAC, the number of permissions can be reduced, which means multiple users can use the same policy to access different resources. When a new resource is added or a new member joins the team, we won’t necessarily need to update the policy as long as the new resource and team member have the correct attributes attached. This also means that all resources with the relevant attributes can be accessed.
If the ABAC has been planned correctly, team or project changes will become easy, too. We only need to change the relevant attribute on the user or role, and the corresponding resources will be accessible.
3. ABAC elements
Before going into detail about the elements of ABAC, let’s quickly recap how AWS authorizes requests.
3.1. Request authorization
When a principal (user or role) wants to access a resource via the AWS Console or CLI, AWS will create an context object. Context will contain a lot of information about the request itself, and we can write policies about these context attributes.
When the request is made, AWS will check all the relevant policies, and if there is an overall ALLOW
permission (given that there’s no explicit DENY
), it will let the principal access the resource.
3.2. Use tags for ABAC
On AWS, the attributes are tags, and we use the Condition
element in the policy to control access to the resources.
Based on the authorization process above, tags can be attached to the request, resource, and principal (can be hardcoded on the IAM identity or passed in the session when users federate through their identity provider).
4. Example
Let’s see some examples how we can control access to SNS using tags.
The scenario is the following: We have two teams, Red and Blue. The Red team should only create, modify, use and delete SNS resources that belong to the Red team but not the Blue team. The Blue team will control the Blue resources but not the Red ones.
The following policy statements are excerpts from the policy which is attached to the Red and Blue team roles. Using ABAC, we can attach the same policy to both roles, and we won’t need to specify either Red or Blue resources.
We will use the project
tag for authorization, and as such the permissions are built around this tag key and its value. This way the Red and Blue roles need to have the project: red
and project: blue
tags, respectively. Of course, they can have other tags as well, but they are not relevant to the authorization process.
4.1. Tags in the request
Tags can be passed in the request. In this case, we use the aws:RequestTag/<key-name>
condition key. The RequestTag
will be the new tag on the resource to be created.
{
"Sid": "CreateTopic",
"Effect": "Allow",
"Action": "sns:CreateTopic",
"Resource": "*",
"Condition": {
"StringEquals": {
"aws:RequestTag/project": "${aws:PrincipalTag/project}"
},
"ForAllValues:StringEquals": {
"aws:TagKeys": [
"project",
"application"
]
}
}
}
This statement only allows the topic creation if the request contains the project
key (aws:RequestTag/project
), and it matches the project
tag of the role that is submitting the request. In the case of the Red team, they will need to add the project: red
tag in the request.
For example, the CLI command can look like this:
aws sns create-topic --name test-red-topic --tags 'Key=project,Value=red' --region us-east-1
The TagKeys
condition key contains all tags that can be passed in the request. In this case, the Red team can only pass the project
and application
tags when creating a topic but not else. TagKeys
also helps prevent the use of the same keys with a different spelling. Condition keys are case insensitive, so both project
and Project
would work if we didn’t specify the lower case version in the TagKeys
array.
This statement by itself is not enough to create the topic. The Red role also needs the sns:TagResource
permission, which can look like this:
{
"Sid": "TagTopic",
"Effect": "Allow",
"Action": "sns:TagResource",
"Resource": "*",
"Condition": {
"StringEqualsIfExists": {
"aws:ResourceTag/project": "${aws:PrincipalTag/project}",
"aws:RequestTag/project": "${aws:PrincipalTag/project}"
},
"ForAllValues:StringEquals": {
"aws:TagKeys": [
"project",
"application",
"name",
"environment"
]
}
}
}
The statement above can be applied when a new resource is created with the relevant project
tag (the resource tag is conditional because there cannot be a project
tag on the topic if the topic doesn’t exist yet), or an existing topic needs additional tags (the request project
tag is conditional because the tag already exists along with the topic, so the request doesn’t need to have the project: red
or project: blue
tag).
4.2. Tags on the resource
After the resource (in this case the new topic) has been created, the Red team can use the topic. The policy has the aws:ResourceTag
condition key to allow access to the resource whose project
tag matches the project
tag of the Red role (which has the value of red
).
{
"Sid": "UseTopic",
"Effect": "Allow",
"Action": [
"sns:Publish",
"sns:DeleteTopic",
"sns:Unsubscribe",
"sns:Subscribe",
"sns:GetTopicAttributes",
"sns:ListTagsForResource",
"sns:ListSubscriptionsByTopic",
"sns:SetTopicAttributes"
],
"Resource": "*",
"Condition": {
"StringEquals": {
"aws:ResourceTag/project": "${aws:PrincipalTag/project}"
}
}
}
The difference between aws:RequestTag
and aws:ResourceTag
is that the former specifies the tag to be added to the resource while the latter refers to an existing tag of an existing resource.
4.3. Tags on the principal
In both cases, the matching is checked using the aws:PrincipalTag
tag key. The request will contain the Red role’s project: red
tag (and the Blue role’s project: blue
tag), and the ${aws:PrincipalTag/project}
policy variable will have the tag value when the policy evaluation occurs.
5. Summary
Attribute-based access control is a great way to simplify permission management. It scales well when the resources or the IAM identities start to grow.
ABAC makes it possible to add new users, roles, and resources without modifying the policy, which would be a required step if we used the traditional role-based access control.
This way, attribute-based access control gives us the possibility to create granular permissions without modification these permissions.
You can find the list of AWS services supporting ABAC in the Authorization based on tags column.
6. References, further reading and watching
Scale Permissions Management in AWS w/ Attribute-Based Access Control, AWS re:Inforce 2019, Brigid Johnson - great video on the topic, it’s a must if you are interested to learn more
What is ABAC for AWS? - Short summary on AWS ABAC
What is ABAC for AWS? - Collection of ABAC resources on the AWS ABAC landing page