Example 1 – ABAC Using Tags
Summary
In this example, we will demonstrate ABAC using tags.
We will have two(2) roles: ABACRole1 and ABACRole2. ABACRole1 will assume ABACRole2, which has access to objects in an S3 bucket. ABACRole1 will be allowed to assume ABACRole2 if both have the same value in a particular tag, and ABACRole2 will be allowed to access objects in the S3 bucket if the object has the same value of a specific tag.
Demonstration
- Deploy the application stack.
Clone this CDK folder and deploy the stack.
cdk deploy
The stack will create three (3) resources, namely: (1) IAM role called ABACRole1, (2) IAM role ABACRole2 and (3) an S3 bucket with a name auto-generated by CloudFormation. The stack will also copy a file called “hello_world.txt” into the S3 bucket.
The IAM role ABACRole2 will have the following condition in its trust relationship:
"Condition": {
"ForAnyValue:StringEquals": {
"aws:ResourceTag/team": "${aws:PrincipalTag/team}"
}
}
In its S3 permission policy, it will have the following condition:
"Condition": {
"ForAnyValue:StringEquals": {
"s3:ExistingObjectTag/team": "${aws:PrincipalTag/team}"
}
}
- Assume and switch to ABACRole1.
ROLE_1_TOKENS=$(aws sts assume-role --role-arn arn:aws:iam::<account id>:role/ABACRole1 --role-session-name ABAC-Role-1 --query 'Credentials.[AccessKeyId,SecretAccessKey,SessionToken]' --output text)
export AWS_ACCESS_KEY_ID=$(echo $ROLE_1_TOKENS | cut -d' ' -f1)
export AWS_SECRET_ACCESS_KEY=$(echo $ROLE_1_TOKENS | cut -d' ' -f2)
export AWS_SESSION_TOKEN=$(echo $ROLE_1_TOKENS | cut -d' ' -f3)
aws sts get-caller-identity
Note: The role that you used to deploy the CDK above will be a trusted principal in ABACRole1. This should allow you to assume this role from the role that created the stack.
- Assume ABACRole2.
aws sts assume-role --role-arn arn:aws:iam::<account id>:role/ABACRole1 --role-session-name ABAC-Role-1
This should fail because neither role has any tag.
- Re-run the stack using the step_1 context.
cdk deploy --context step_no=step_1
Under this context, the deployment will add the tag ‘team:abac‘ to both ABACRole1 and ABACRole2
This should be successful.
- Switch to ABACRole2 and copy the file “hello_world.txt” from the S3 bucket.
ROLE_2_TOKENS=$(aws sts assume-role --role-arn arn:aws:iam::<account id>:role/ABACRole2 --role-session-name ABAC-Role-2 --query 'Credentials.[AccessKeyId,SecretAccessKey,SessionToken]' --output text)
export AWS_ACCESS_KEY_ID=$(echo $ROLE_2_TOKENS | cut -d' ' -f1)
export AWS_SECRET_ACCESS_KEY=$(echo $ROLE_2_TOKENS | cut -d' ' -f2)
export AWS_SESSION_TOKEN=$(echo $ROLE_2_TOKENS | cut -d' ' -f3)
aws sts get-caller-identity
aws s3 cp s3://abacsample1stack-bucketxxxxx-yyyyyyyy/hello_world.txt /tmp
This should fail because the S3 object has no tag.
- Re-run the stack using the step_2 context.
cdk deploy --context step_no=step_2
Under this context, the deployment will add the tag ‘team:abac‘ to the S3 object “hello_world.txt”
This should be successful since both the role and the object have the same value in their ‘team’ tag.
Footnotes
- Whenever you need to re-run the CDK, you must switch back to the role that has the privilege to deploy the infrastructure. So when you repeat steps, you need to assume ABACRole1 and ABCRole2 again. Alternatively, you can have another terminal dedicated solely to deploying the CDK.