What happens when bucket.grantRead() in AWS CDK

What happens when bucket.grantRead() in AWS CDK

Diving deep on how grant works in AWS CDK

Pahud Hsieh
Amazon Employee
Published Aug 3, 2024
Last Modified Sep 11, 2024
Have you ever wondered what actually happens when you grantRead from a S3 bucket to an IAM role?

identity-based and resource-based policies

In AWS, when an identity is accessing a resource, both IAM policies(identity-based policies) and resource-based policies (like S3 bucket policies) are evaluated together to determine the effective permissions.
In CDK, when resource.grantRead(identity), it essentially execute the addToPrincipalOrResource() method. What's happening behind the scene:
  1. CDK first tries to add relevant read permissions to that identity if it's an IAM principal.(update identity-based policies)
  2. If it doesn't work, it tries to add relevant statements to the resource policies.(update resource-based policies)
Now, if the identity is a role created from new iam.Role(), which is created by CDK, 1) would work as CDK would render the policies for the iam.Role it is creating. However, if the role is from iam.Role.fromRoleArn() or fromRoleName(), which returns the IRole interface. CDK would not add identity-based policies to it. Because that role as type IRole could already be created out of current CDK stack and it would not be able to update the existing iam policies attached to this role. When this happens, step 1 would not change anything, falling to step 2.
Similarly, in step 2, if the resource is actually an interface like IBucket, it would not add any statements to the resource-based policy because that could be created out of this CDK stack.

IBucket v.s. Bucket

You get a concrete Bucket when you new s3.Bucket() in current stack otherwise you would get IBucket interface when you use the fromXxx() methods to reference an existing resource or simply reference another bucket from another stack. That returns IBucket to you as well.

Things to Know

Next time when you use construct methods like resource.grantRead(identity), grantWrite() or grantInvoke(). Think about it:
  1. Is the identity an IAM principal like IAM role? If yes, is it a concrete principal or just an interface that references an existing one?
  2. Does the resource have resource-based policies? If yes, is it a concrete resource or just an interface that references an existing one?
bucket.grantRead() won't work if both resource-based and identity-based policies can't be updated. For example:
  1. Both the iam principal and resource are created out of CDK and we just reference them as interfaces in CDK.
  2. The identity could be something like CloudFront OAI, which is not an IAM principal and the bucket is actually IBucket, which references an existing bucket in another stack or created out of CDK.

Related Issues

Any opinions in this post are those of the individual author and may not reflect the opinions of AWS.

1 Comment