11

I'm working on adding resource policy document to S3 bucket.

It works fine when I create a new Bucket:

const newbucket = new s3.Bucket(this, 'newBucket', {
      websiteIndexDocument : 'index.html',
      bucketName : 'NewBucket'
});

newbucket.addToResourcePolicy(new iam.PolicyStatement({
      effect : iam.Effect.ALLOW,
      actions: ['s3:*'],
      resources: [newbucket.arnForObjects('*')],
      principals: [new iam.AnyPrincipal],
    }));

newbucket.addToResourcePolicy(new iam.PolicyStatement({
      effect : iam.Effect.DENY,
      actions: ['s3:*'],
      resources: [newbucket.arnForObjects('*')],
      principals: [new iam.AnyPrincipal],
      conditions : {
        'NotIpAddress' : {
          'aws:SourceIp' : '***.***.***.***'
        }
      }
    }));

But if I try to get a bucket that already exists and add policy document it doesn't work:

const existingbucket = Bucket.fromBucketAttributes(this, 'ImportedBucket',{
      bucketName :'ExistingBucket'
    })

existingbucket.addToResourcePolicy(new iam.PolicyStatement({
      effect : iam.Effect.ALLOW,
      actions: ['s3:*'],
      resources: [existingbucket.arnForObjects('*')],
      principals: [new iam.AnyPrincipal],
    }));

Resource Policy document won't be added.

Furthermore this code deletes existing policy document and make it blank.

Anyone have experience or solution about this issue?

Jamie
  • 1,530
  • 1
  • 19
  • 35
HanBinKim
  • 113
  • 1
  • 1
  • 4
  • Does your CDK stack have permission to modify existing buckets? – Jamie Feb 11 '20 at 15:04
  • I had similar issue, please refer [60905976](https://stackoverflow.com/questions/60905976/cloudfront-give-access-denied-response-created-through-aws-cdk-python-for-s3-buc) for the solution – santosh Apr 02 '20 at 07:16

3 Answers3

4

yeah,its possible and i did it using the python cdk. There's a work around here. https://github.com/aws/aws-cdk/issues/6548 The CfnBucketPolicy was used there.

existing_bucket=s3.Bucket.from_bucket_attributes(self, 'ImportedBucket', 
            bucket_arn="arn:aws:s3:::bucket"       
        )

        bucket_policy=iam.PolicyStatement(
            actions=["s3:Get*", "s3:List*"],
            resources=[existing_bucket.arn_for_objects('*')],
            principals=[iam.AccountRootPrincipal()]
        )

        s3.CfnBucketPolicy(self, 'bucketpolicy',
            bucket=existing_bucket.bucket_name,
            policy_document=iam.PolicyDocument(statements=[bucket_policy])
        )
Kayode
  • 64
  • 2
  • While this code may solve the question, [including an explanation](//meta.stackexchange.com/q/114762) of how and why this solves the problem would really help to improve the quality of your post, and probably result in more up-votes. Remember that you are answering the question for readers in the future, not just the person asking now. Please [edit] your answer to add explanations and give an indication of what limitations and assumptions apply. – Yunnosch Jul 16 '21 at 13:38
  • This says, ``The bucket policy already exists on bucket `` – logan Oct 06 '21 at 08:45
1

I'm grappling with the same issue. After digging around I found this, which implies it's just not possible with the CDK:

enter image description here

As a workaround what I'm planning to do is to output the exact AWS S3 command that needs to be run from the command line in order to append the S3 bucket resource policy. This way the user that deploys the stack (I'm using server stack) knows of this additional manual step. Hopefully the AWS CLI supports

Update: Found a way to do this programmatrically, using a GET/SET approach on the bucket policy. The below is a Node.js zx script:

#!/usr/bin/env zx

const fs = require('fs')

...

async function updateBucketPolicy ({
                                                     awsProfile,
                                                     bucket,
                                                     lambdaOneRoleArn: lambdaOneRoleArn,
                                                     lambdaTwoRoleArn: lambdaTwoRoleArn
                                                   }) {
  const policyTmpl = '{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":{"AWS":"[LAMBDA_ONE_ROLE_ARN]"},"Action":"s3:PutObject","Resource":"arn:aws:s3:::[BUCKET]/*"},{"Effect":"Allow","Principal":{"AWS":"[LAMBDA_TWO_ROLE_ARN]"},"Action":"s3:GetObject","Resource":"arn:aws:s3:::[BUCKET]/*"},{"Effect":"Allow","Principal":{"AWS":"[LAMBDA_TWO_ROLE_ARN]"},"Action":"s3:ListBucket","Resource":"arn:aws:s3:::[BUCKET]"}]}'
  const policyAmendments = JSON.parse(policyTmpl.replace(/\[BUCKET\]/g, bucket).replace(/\[LAMBDA_ONE_ROLE_ARN\]/g, lambdaOneRoleArn)
    .replace(/\[LAMBDA_TWO_ROLE_ARN\]/g, lambdaTwoRoleArn))

  // First get the current bucket policy
  await $`AWS_PROFILE=${awsProfile} aws s3api get-bucket-policy --bucket ${bucket} --output text > /tmp/policy.json`
  const currentBucketPolicy = JSON.parse(fs.readFileSync('/tmp/policy.json'))

  // Now update it, and put it right back
  const newPolicy = currentBucketPolicy
  newPolicy.Statement = currentBucketPolicy.Statement.concat(policyAmendments.Statement)
  fs.writeFileSync('/tmp/new-policy.json', JSON.stringify(newPolicy))
  await $`AWS_PROFILE=${awsProfile} aws s3api put-bucket-policy --bucket ${bucket} --policy file:///tmp/new-policy.json`
  console.log(`Updated  bucket ${bucket} policy with ${JSON.stringify(newPolicy, null, ' ')}`)
}

This solution is even suggested by AWS in aws s3api get-bucket-policy help manual:

Get and put a bucket policy The following example shows how you can download an Amazon S3 bucket policy, make modifications to the file, and then use put-bucket-policy to apply the modified bucket policy. To download the bucket policy to a file, you can run:

      aws s3api get-bucket-policy --bucket mybucket --query Policy --output text > policy.json

   You can then modify the policy.json file as needed.   Finally  you  can
   apply this modified policy back to the S3 bucket by running:

      aws s3api put-bucket-policy --bucket mybucket --policy file://policy.json
Jose Quijada
  • 558
  • 6
  • 13
-1

I believe you cannot modify the policy of an existing bucket through your CDK App. That is why it works perfectly when you create a new bucket.

If you need to make changes to that bucket's resource policy, I'm afraid you might need to do it manually.