Amazon Web Services Cloud Partner: Driving Cloud Transformation Together

What Is Attribute Based Access Control (ABAC) in AWS? A Practical Guide

Neil Clark
Senior Cloud Solutions Architect | Telefónica Tech UK&I
15 December 2025

What Is Attribute Based Access Control (ABAC) in AWS? A Practical Guide

Attribute Based Access Control (ABAC) has been around for a while now and is gaining a lot of traction in environments due to its ability to scale and provide fast onboarding for new projects.  In this blog will explore ABAC to give you a flavour of what it can do and why you may want to consider it for your environment as cloud journey progresses.

What is ABAC?

Attribute Based Access Control is an access model where permissions are granted dynamically based on metadata about the user (principal), the resource, the action and the environment.  In AWS, for ABAC we commonly use tags and session attributes like “aws:PrincipalTag” and “aws:ResourceTag” in AWS Identity and Access Management policies to allow or deny actions when specific attributes match.  For example: a user with the tag “project :alpha” can only access resources that have been tagged with “project :alpha”. 

Why does ABAC matter?

Let’s start by answering this question with another question.  Have you ever felt like you are drowning in IAM roles and bespoke policies?  Yeah, me too…  this is where ABAC strengths come into play.  ABAC allows you to move fast and scale without the need for hardcoding permissions per role, because ABAC attributes are evaluated at the time of request, it allows for access to automatically adapt as teams, projects and environments change and grow.  In AWS this means you can onboard new services or projects faster by setting consistent tagging policies,  this will result in fewer policies to maintain, cleaner separation of duties, and easier audits while preserving least privilege principles,  this means users and services only get the access their attributes match,  all of this means centralised governance through tag standards and guardrails. 

Where can we apply ABAC?

ABAC shows up across AWS wherever attributes (usually tags) can drive authorisation decisions. Let’s check out the common ones:  

  • IAM Policies
  • Resource Policies (Amazon Simple Storage Service (Amazon S3) Buckets, AWS Key Management Service (AWS KMS) Keys, AWS Secrets Manager Secrets)
  • Session Tags (Passed through by AWS Security Token Service (AWS STS) TagSession or Mapped from AWS IAM Identity Center)
  • AWS Organizations

Foundations: Tags and Governance

ABAC succeeds when your tags are consistent, meaningful, and enforced. You must start with a simple tag strategy that every team can follow, making things to complex or overbearing will result slow development and deployment or worse teams trying to circumvent these protections. Most organisations do well with three core tags “project”, “owner” and “environment” then expand gradually to include “costcenter” or “dataclassification” as governance matures. Keeping values standardised and predictable is really key, advice from mme…se lower-case, avoid spaces, and define allowed lists (e.g., dev, test, stage, prod). Treat “owner” as a real contact (like an email or group), not a nickname, so you can route alerts and approvals reliably.

Enforcement has to begin at creation, not after the fact. Using AWS Organizations’ Service Control Policies (SCPs) to deny resource creation unless your required tags are provided, and to restrict who can set or change sensitive tags like “environment” or “dataclassification” ensure you get off to a great start. This prevents drift and ensures that ABAC conditions have clean inputs from day one. But what about ongoing assurance, this is where we enable AWS Config rules to check tag compliance across accounts and services. We can even take things a step further with some lightweight remediation, using an Amazon EventBridge” rule and a AWS Lambda function we can notify owners, add a temporary quarantine tag, or auto-correct simple issues until a team fixes the root cause, this provides some powerful interventions if needed.

It won’t surprise you that documentation matters as much as tooling when using ABAC. We need to ensure we publish a central, versioned tag dictionary that explains each tag’s purpose, allowed values, who has permissions to edit it, and examples of how to use them. Ensure that the ownership model is explicitly defined and understood, will make things easy to follow and it can be as simple as the platform team defines and enforces standards, while application teams keep their resources correctly tagged. To keep everyone aligned we can add things like dashboards that show tag coverage and trends, making gaps visible and easy to address.

There are a few good habits to keep ABAC clean over time:

  • Default to fail closed if tags are missing, access should not be granted
  • Normalise tag values in pipelines before deployment to avoid case mismatches
  • Start small with the three core tags and iterate quarterly, ensure you retire unused keys, resolve exceptions, and refresh the dictionary based on real-world learnings

With strong tag hygiene and clear governance, ABAC stays reliable, scalable, and easy for customers to understand and trust. 

How about a walkthrough of a real-world example?

So, let’s take the example of an IAM Policy with the “aws:PrincipalTag” and S3. So, we have a user that we want to allow to access, and S3 Bucket based on the tags on their user and the destination bucket matching.

So, let’s say we have a new project called “mustang”, we will use the tag “project:mustang” as the way to ensure my user can only see the S3 Bucket with the matching project tag.

The first thing we need to do is tag the user identity in IAM or Identity Centre with the tag “project:mustang”

We then need to make sure that the target bucket has the same tag applied.

Next because we have standardised S3 IAM policies already created and applied to our existing user we are ready to go.

Below is an example of what the IAM policy could look like from a basic viewpoint

{
“Version”: “2012-10-17”,
“Statement”: [
{
“Sid”: “AllowS3AccessToMatchingProjectResources”,
“Effect”: “Allow”,
“Action”: [
“s3:DeleteObject”,
“s3:PutObject”
],
“Resource”: “arn:aws:s3:::*/*”,
“Condition”: {
“StringEquals”: {
“aws:ResourceTag/project”: “${aws:PrincipalTag/project}”
}
}
},
{
“Sid”: “AllowGetBucketsWithMatchingProjectTag
“Effect”: “Allow”,
“Action”: [
“s3:GetObject”
],
“Resource”: “arn:aws:s3:::*”,
“Condition”: {
“StringEquals”: {
“aws:ResourceTag/project”: “${aws:PrincipalTag/project}”
}
}
},
{
“Sid”: “DenyAccessToUntaggedResources”,
“Effect”: “Deny”,
“Action”: [
“s3:GetObject”,
“s3:PutObject”
],
“Resource”: “arn:aws:s3:::*/*”,
“Condition”: {
“Null”: {
“aws:ResourceTag/project”: “true”
}
}
}
]
}

So, if we look through this IAM policy we see that for the user can carry out Gets, Puts and Lists on S3 buckets that meet the condition that the Principal Tag “project” and resource tag “project” match. If they do not match or the entry is null, then access is denied.

You can start to see how this really scales now as I didn’t need to do anything to my IAM policy as it already contained the logic needed to allow access just by adding the correct tags.

Is there a potential problem with the above example?

The eagle eyed amongst you may have noticed a little bit of an issue depending on the types of security policies you have internally…  Now I will admit the above example is very simple and would work well in lots of situations,  however let me ask this question what if I have certain members of the project team that I only want to be able to carry out certain actions while others can do others?  Yeah, now you see it, the example above would essentially let all users with the appropriate tag to be able to do whatever the policy allows even if they shouldn’t be able to. 

This is where we would introduce a “permissionlevel” tag, this would be an additional identity tag based on the user’s role within the project.   

For example we may have users that we only want to allow to manage data in a bucket i.e. they only need Put and Delete permissions but don’t need to read the data,  and we have other users that only need to read the data and not manage it.   

In this scenario we need to make some changes to the IAM policy, and it is not as much as you might think.  We are going to need to add an additional condition to each permission block, we will be adding “aws:PrincipalTag/permissionlevel“: “tag to define the permissions 

So, in this Instance we would have two “perminssionlevel” tags “write” or “read 

The below shows how little code needs to be added to the IAM policy for this to be implemented

{

“Version”: “2012-10-17”,

“Statement”: [

{

“Sid”: “AllowS3AccessToMatchingProjectResources”,

“Effect”: “Allow”,

“Action”: [

“s3:DeleteObject”,

“s3:PutObject”

],

“Resource”: “arn:aws:s3:::*/*”,

“Condition”: {

“StringEquals”: {

“aws:ResourceTag/project”: “${aws:PrincipalTag/project}”,

“aws:PrincipalTag/permissionlevel”: “write”

}

}

},

{

“Sid”: “AllowGetBucketsWithMatchingProjectTag

“Effect”: “Allow”,

“Action”: [

“s3:GetObject”

],

“Resource”: “arn:aws:s3:::*”,

“Condition”: {

“StringEquals”: {

“aws:ResourceTag/project”: “${aws:PrincipalTag/project}”,

“aws:PrincipalTag/permissionlevel”: “read”

}

}

},

{

“Sid”: “DenyAccessToUntaggedResources”,

“Effect”: “Deny”,

“Action”: [

“s3:*”

],

“Resource”: “arn:aws:s3:::*/*”,

“Condition”: {

“Null”: {

“aws:ResourceTag/project”: “true”

}

}

}

]

}

Now we have some additional control and can ensure that we have separation of responsibilities within our user base to ensure that they can only carry out the tasks they are meant to.

Are there times I shouldn’t use ABAC (At least on its own)?

This is an unanimous yes… ABAC is powerful, but it’s not a silver bullet. Some situations call for explicit controls, tighter governance, or a hybrid model combining ABAC with RBAC and resource scoping.

Let’s look at some situations where ABAC may not be a suitable option:

  • Highly Regulated or Audit heavy workloads – If your controls or auditors require explicit whitelists of resource ARNs (e.g., KMS keys, specific S3 buckets), ABAC’s dynamic matching may be too open-ended.
  • Services with limited ABAC support or uneven condition keys – Not every AWS service supports the same tag condition keys, and some operations don’t evaluate resource tags cleanly (especially create-time or cross-account scenarios). In these areas, use role-based scopes and explicit ARNs.
  • Safety-critical operations and break-glass access – For actions like deleting data, rotating KMS keys, or changing network boundaries, explicit approvals and tightly scoped roles are safer than attribute-matched access. Keep ABAC for day-to-day access but gate high-risk actions behind separate RBAC roles and workflow.
  • Immature or inconsistent tagging – ABAC depends on clean, consistent tags. If your tag coverage is spotty, values vary in casing, or ownership isn’t enforced, ABAC can fail open or cause surprises. Start with RBAC + tag governance (SCPs, AWS Config), then introduce ABAC once tags are reliable.
  • Cross-account and third-party integrations – In multi-account or partner setups, you may not control the other side’s tagging. Prefer explicit resource policies, trusted principals, and scoped ARNs. Use ABAC only where you own both principal and resource attributes end-to-end.
  • Fine-grained data authorisation that exceeds tag granularity – When decisions depend on row/column-level sensitivity, item attributes, or complex business rules (beyond simple project/environment), you’ll likely need application-level authorisation or service-native fine-grained controls. ABAC can still gate coarse scopes, but don’t rely on it alone for deep data policies.
  • Performance and predictability concerns – Dynamic attribute matching can be harder to reason about during incidents or migrations. For critical migrations, prefer explicit allowlists to avoid unexpected denies due to tag drift, then revert to ABAC after stabilization.

What are you waiting for, give it a go…

I hope this has shown you how simple it can be to get going with ABAC but ensure that you fully understand the how and when to use it, ultimately it is a great technique for scaling and onboarding new services fast however it is not always the best tool in every situation. I would certainly say the hybrid approach is the best option this ensures your projects and scale and onboard quickly, but more granular and auditable tasks can be covered by specific roles and policies to ensure your environment is protected.

Telefónica Tech UK