Published on

ABAC and RBAC: A Journey with Terraform and AWS Tagged Resources

Authors

In the world of cloud security, access control is a crucial area that requires your constant vigilance. There are different strategies to handle access control, and two of the most prominent are Attribute-based Access Control (ABAC) and Role-based Access Control (RBAC). But what are they? How do they differ? And how can we implement them using our favorite Infrastructure as Code (IaC) tool, Terraform, in the AWS environment?

To start with, let's define these two concepts:

  • RBAC: In Role-Based Access Control, access permissions are based on the role a user holds within an organization. A user gets assigned a role, and that role has permissions attached to it.
  • ABAC: On the other hand, Attribute-Based Access Control is a bit more flexible. Permissions are not based on roles but on attributes. These attributes could be related to the user, resource, action, or even the environment.

The primary difference is the flexibility and granularity of control. RBAC is simple, easy to understand, and works well in a structured environment. ABAC, however, allows for more granular control and can adapt better to complex environments.

Let's bring this concept into reality with AWS and Terraform.

AWS allows for ABAC by using tags. Tags are basically key-value pairs that you can attach to AWS resources. This feature lets you define permissions based on these tags.

Consider an example where we have an S3 bucket in AWS. We can use Terraform to create this bucket and tag it:

resource "aws_s3_bucket" "bucket" {
  bucket = "supasaf-test-bucket"
  acl    = "private"

  tags = {
    Environment = "Test"
  }
}

With this Terraform code, we've created a private S3 bucket and assigned it a tag Environment with the value Test.

Now, let's use ABAC to control access to this bucket. We can create a policy that allows access only if the Environment tag is Test:

data "aws_iam_policy_document" "s3_limited" {
  statement {
    actions = [
      "s3:ListBucket",
    ]

    resources = [
      aws_s3_bucket.bucket.arn,
    ]
  }

  statement {
    actions = [
      "s3:GetObject",
      "s3:PutObject",
      "s3:PutObjectTagging"
    ]

    resources = [
      "${aws_s3_bucket.bucket.arn}/*",
    ]

    condition {
      test     = "StringEquals"
      variable = "s3:RequestObjectTag/Environment"
      values = [
        "Test",
      ]
    }
  }
}

We could create a new user and attach that policy to her/him:

resource "aws_iam_policy" "s3_limited_policy" {
  name        = "s3_limited"
  description = "S3 limited policy"
  policy      = data.aws_iam_policy_document.s3_limited.json
}

resource "aws_iam_user" "user" {
  name = "s3_limited_user"
}

resource "aws_iam_user_policy_attachment" "user_s3_limited" {
  user       = aws_iam_user.user.name
  policy_arn = aws_iam_policy.s3_limited_policy.arn
}

After executing terraform apply, we could put file into the supasaf-test-bucket:

❯ aws s3api put-object --bucket supasaf-test-bucket --key test.txt --body test.txt --tagging 'Environment=Test' --profile s3_limited_user

{
    "ETag": "\"bc98d84673286ce1447eca1766f28504\"",
    "ServerSideEncryption": "AES256"
}

To make sure the file we just put it into the bucket, just login the AWS console:

In contrast, if we were to use RBAC, we would create roles that would have these permissions and assign users to those roles. The roles would not be aware of the context (i.e., the tags or attributes).

resource "aws_iam_role" "test_role" {
  name = "test_role"

  assume_role_policy = data.aws_iam_policy_document.assume_role.json
}

resource "aws_iam_role_policy_attachment" "test_role_policy" {
  role       = aws_iam_role.test_role.name
  policy_arn = aws_iam_policy.test_policy.arn
}

In this case, any user assigned to test_role would have the permissions defined in test_policy.

Both ABAC and RBAC have their place in AWS and can be implemented efficiently using Terraform. The choice between ABAC and RBAC would depend on the specific needs of your organization and the complexity of your environment.

Remember, security is not a one-size-fits-all solution. It's about understanding your needs, your risks, and applying the appropriate control mechanisms.

In scenarios where the organization structure is well-defined and doesn't change frequently, RBAC can be a suitable model. However, in dynamic environments where resources and their characteristics evolve continually, ABAC may offer more flexibility and finer granularity. ABAC can provide a more detailed control mechanism for complex systems, especially when access to resources must be dynamic and context-aware.

For instance, consider a global organization with multiple departments and projects, constantly evolving resource attributes (like resource types, environment stages), and users who need varying access levels based on these attributes. In such a case, using ABAC could be more practical and efficient. It allows for dynamic access control decisions based on a multitude of attributes related to the user, action, resource, and environment.

It's crucial to note that while ABAC can offer higher granularity and flexibility, it also comes with increased complexity, which could lead to errors if not implemented carefully. Therefore, it's essential to thoroughly plan your access control strategy and continuously monitor and revise it as your environment evolves.

Let's look at an example where we can use Terraform to modify the ABAC policy dynamically:

variable "environment" {
  description = "The environment for which to grant access"
  type        = string
}

data "aws_iam_policy_document" "s3_limited" {
  statement {
    effect = "Allow"

    actions = [
      "s3:*",
    ]

    resources = [
      "${aws_s3_bucket.bucket.arn}/*",
    ]

    condition {
      test     = "StringEquals"
      variable = "s3:ExistingObjectTag/Environment"
      values   = [var.environment]
    }
  }
}

In this example, we're using a Terraform variable to change the environment to which our policy applies dynamically. This is just a simple example, but you can imagine how powerful this could be in a larger, more complex environment.

When exploring RBAC and ABAC models, it's important to understand that these are not mutually exclusive. In many cases, a hybrid approach might be the most effective. You might find that using RBAC for certain resources and ABAC for others is the best fit for your needs. The key is to understand the strengths and weaknesses of each model and apply them where they make the most sense.

Understanding the difference between RBAC and ABAC and knowing how to implement them using tools like Terraform is critical. It provides you with the flexibility to adapt to different environments and requirements, giving you a robust toolset to ensure your resources are secure. As always, remember that the best security is a layered approach, and access control is just one layer of that security onion.