S3 Bucket Policy Example in AWS CDK

avatar

Borislav Hadzhiev

Wed Apr 28 20213 min read

banner

Photo by Muye Ma

Creating an S3 Bucket Policy in AWS CDK #

Bucket policies are used to grant permissions to an S3 bucket.

There are 2 ways to create a bucket policy in AWS CDK:

The approach with the addToResourcePolicy method is implicit - once we add a policy statement to the bucket, CDK automatically creates a bucket policy for us.

The second approach is explicit and a bit easier for the reader of our code to understand.

The code for this article is available on GitHub

Let's look at an example of both. We will start with the addToResourcePolicy method first:

lib/cdk-starter-stack.ts
import * as iam from '@aws-cdk/aws-iam'; import * as s3 from '@aws-cdk/aws-s3'; import * as cdk from '@aws-cdk/core'; export class CdkStarterStack extends cdk.Stack { constructor(scope: cdk.App, id: string, props?: cdk.StackProps) { super(scope, id, props); // ๐Ÿ‘‡ create the s3 bucket const bucket1 = new s3.Bucket(this, 'bucket-id-1', { removalPolicy: cdk.RemovalPolicy.DESTROY, }); // ๐Ÿ‘‡ `addToResourcePolicy` creates a Bucket Policy automatically bucket1.addToResourcePolicy( new iam.PolicyStatement({ effect: iam.Effect.ALLOW, principals: [new iam.ServicePrincipal('lambda.amazonaws.com')], actions: ['s3:GetObject'], resources: [`${bucket1.bucketArn}/*`], }), ); // ๐Ÿ‘‡ access the bucket policy bucket1.policy?.document.addStatements( new iam.PolicyStatement({ effect: iam.Effect.ALLOW, principals: [new iam.ServicePrincipal('lambda.amazonaws.com')], actions: ['s3:GetBucketTagging'], resources: [bucket1.bucketArn], }), ); } }

Let's go over what we did in the code snippet.

  1. we created an s3 bucket
  2. we used the addToResourcePolicy method on the bucket instance passing in a policy statement as the only parameter. A bucket policy was automatically created for us by CDK, once we added a policy statement.
  3. we directly accessed the bucket policy to add another policy statement to it

After I've ran the npx cdk deploy command, we can see that the bucket policy has been attached:

bucket policy attached

Let's look at an example, where we use the explicit approach - by instantiating the BucketPolicy class to achieve the same result.

lib/cdk-starter-stack.ts
import * as iam from '@aws-cdk/aws-iam'; import * as s3 from '@aws-cdk/aws-s3'; import * as cdk from '@aws-cdk/core'; export class CdkStarterStack extends cdk.Stack { constructor(scope: cdk.App, id: string, props?: cdk.StackProps) { super(scope, id, props); // ... rest // ๐Ÿ‘‡ create the s3 bucket const bucket2 = new s3.Bucket(this, 'bucket-id-2', { removalPolicy: cdk.RemovalPolicy.DESTROY, }); // ๐Ÿ‘‡ create the bucket policy const bucketPolicy = new s3.BucketPolicy(this, 'bucket-policy-id-2', { bucket: bucket2, }); // ๐Ÿ‘‡ add policy statements ot the bucket policy bucketPolicy.document.addStatements( new iam.PolicyStatement({ effect: iam.Effect.ALLOW, principals: [new iam.ServicePrincipal('lambda.amazonaws.com')], actions: ['s3:GetObject'], resources: [`${bucket2.bucketArn}/*`], }), ); } }

Let's go over the code snippet.

  1. we created an S3 bucket
  2. we created a bucket policy by instantiating the BucketPolicy class. We've passed in the bucket we created in the props object.
  3. we added a policy statement to the S3 bucket policy. In our case the statement allows the lambda service to get objects from the bucket.

Let's execute a deployment:

shell
npx cdk deploy

If we take a look at the S3 management console, we can see that the bucket policy has been attached successfully:

bucket policy attached

Further Reading #

Add me on LinkedIn

I'm a Web Developer with TypeScript, React.js, Node.js and AWS experience.

Let's connect on LinkedIn

Join my newsletter

I'll send you 1 email a week with links to all of the articles I've written that week

Buy Me A Coffee