Reputation: 9266
I wanna translate this CloudFormation piece into CDK:
Type: AWS::S3::BucketPolicy
Properties:
Bucket:
Ref: S3BucketImageUploadBuffer
PolicyDocument:
Version: "2012-10-17"
Statement:
Action:
- s3:PutObject
- s3:PutObjectAcl
Effect: Allow
Resource:
- ...
Looking at the documentation here, I don't see a way to provide the policy document itself.
Upvotes: 23
Views: 49720
Reputation: 14255
If you really need to update the bucket policy, some of the other answers probably point in the right direction. However, none of them mention the "grant" methods.
From the aws-s3 docs:
Most of the time, you won't have to manipulate the bucket policy directly. Instead, buckets have "grant" methods called to give prepackaged sets of permissions to other resources. For example:
declare const myLambda: lambda.Function; const bucket = new s3.Bucket(this, 'MyBucket'); bucket.grantReadWrite(myLambda);
Will give the Lambda's execution role permissions to read and write from the bucket.
And from the cdk docs:
Every construct that represents a resource that can be accessed, such as an Amazon S3 bucket or Amazon DynamoDB table, has methods that grant access to another entity. All such methods have names starting with grant.
For the OP's case, there's S3.Bucket.grantPut()
(and grantPutAcl()
).
Note the grant methods may achieve the desired result via another route, e.g. by adding an iam policy instead of updating the bucket policy. Check the generated cfn template to see what actually happens.
Upvotes: 1
Reputation: 11
The following functions works for IBucket(Referred bucket) policy update. I've added the imports as well. Hope it helps.
import { Bucket, CfnBucketPolicy, IBucket } from '@aws-cdk/aws-s3';
import { PolicyDocument, PolicyStatement } from '@aws-cdk/aws-iam';
const existingBucket = Bucket.fromBucketAttributes(this, 'ExistingBucket', {
bucketArn: `arn:aws:s3:::${existingBucketName}`,
});
const policyStatement = new iam.PolicyStatement({
actions: [ 's3:GetObject' ],
resources: [ `${existingBucket.bucketArn}`,`${existingBucket.bucketArn}/*` ],
principals: [ new iam.StarPrincipal() ],
});
const bucketPolicy = new CfnBucketPolicy(this, 'cloudfrontAccessBucketPolicy', {
bucket: existingBucket.bucketName,
policyDocument: new PolicyDocument({
statements: [
policyStatement
]
})
});
Upvotes: 1
Reputation: 1641
Building on @Thomas Wagner's answer, this is how I did this. I was trying to limit the bucket to a given IP range:
import * as cdk from '@aws-cdk/core';
import * as s3 from '@aws-cdk/aws-s3';
import * as s3Deployment from '@aws-cdk/aws-s3-deployment';
import * as iam from '@aws-cdk/aws-iam';
export class StaticSiteStack extends cdk.Stack {
constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
// Bucket where frontend site goes.
const mySiteBucket = new s3.Bucket(this, 'mySiteBucket', {
websiteIndexDocument: "index.html"
});
let ipLimitPolicy = new iam.PolicyStatement({
actions: ['s3:Get*', 's3:List*'],
resources: [mySiteBucket.arnForObjects('*')],
principals: [new iam.AnyPrincipal()]
});
ipLimitPolicy.addCondition('IpAddress', {
"aws:SourceIp": ['1.2.3.4/22']
});
// Allow connections from my CIDR
mySiteBucket.addToResourcePolicy(ipLimitPolicy);
// Deploy assets
const mySiteDeploy = new s3Deployment.BucketDeployment(this, 'deployAdminSite', {
sources: [s3Deployment.Source.asset("./mysite")],
destinationBucket: mySiteBucket
});
}
}
I was able to use the s3.arnForObjects() and iam.AnyPrincipal() helper functions rather than specifying ARNs or Principals directly.
The assets I want to deploy to the bucket are kept in the root of my project directory in a directory called mysite
, and then referenced via a call to s3Deployment.BucketDeployment
. This can be any directory your build process has access to, of course.
Upvotes: 21
Reputation: 1996
As per the original question, then the answer from @thomas-wagner is the way to go.
If anyone comes here looking for how to create the bucket policy for a CloudFront Distribution without creating a dependency on a bucket then you need to use the L1 construct CfnBucketPolicy
(rough C# example below):
IOriginAccessIdentity originAccessIdentity = new OriginAccessIdentity(this, "origin-access-identity", new OriginAccessIdentityProps
{
Comment = "Origin Access Identity",
});
PolicyStatement bucketAccessPolicy = new PolicyStatement(new PolicyStatementProps
{
Effect = Effect.ALLOW,
Principals = new[]
{
originAccessIdentity.GrantPrincipal
},
Actions = new[]
{
"s3:GetObject",
},
Resources = new[]
{
Props.OriginBucket.ArnForObjects("*"),
}
});
_ = new CfnBucketPolicy(this, $"bucket-policy", new CfnBucketPolicyProps
{
Bucket = Props.OriginBucket.BucketName,
PolicyDocument = new PolicyDocument(new PolicyDocumentProps
{
Statements = new[]
{
bucketAccessPolicy,
},
}),
});
Where Props.OriginBucket
is an instance of IBucket
(just a bucket).
Upvotes: 4
Reputation: 752
This is an example from a working CDK-Stack:
artifactBucket.addToResourcePolicy(
new PolicyStatement({
resources: [
this.pipeline.artifactBucket.arnForObjects("*"),
this.pipeline.artifactBucket.bucketArn],
],
actions: ["s3:List*", "s3:Get*"],
principals: [new ArnPrincipal(this.deploymentRole.roleArn)]
})
);
Upvotes: 32
Reputation: 8887
The CDK does this a little differently. I believe you are supposed to use bucket.addToResourcePolicy
, as documented here.
Upvotes: 8