Search code examples
typescriptamazon-web-servicesamazon-s3aws-cdk

Bucket cannot have public ACLs set with BlockPublicAccess enabled


I want to make cloudformation and S3 then put log in S3.

So my code is like this below

const bk = new s3.Bucket(this, `cm-st-cloudfront-bk`, { 
  bucketName: s3_name,
  removalPolicy: RemovalPolicy.DESTROY,
  autoDeleteObjects: true,
  blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL,
  //
  encryption: s3.BucketEncryption.S3_MANAGED,
  versioned:true,
});

const oai = new cloudfront.OriginAccessIdentity(this, `my-oai`,{
  comment:`Access identity for ${targetEnv}`
});

const cf = new cloudfront.CloudFrontWebDistribution(this, `Website-${targetEnv}-Distribution`, {
  comment:`CF for resource S3 ${targetEnv}`,
  viewerCertificate: {
    aliases: [],
    props: {
      cloudFrontDefaultCertificate: true,
    },
  },
  errorConfigurations: [
    {
      errorCode: 403,
      responsePagePath: "/index.html",
      responseCode: 200,
      errorCachingMinTtl: 0,
    },
    {
      errorCode: 404,
      responsePagePath: "/index.html",
      responseCode: 200,
      errorCachingMinTtl: 0,
    },
  ],
  loggingConfig: {
    bucket: bk,
    prefix: "cloudfront/",
  },
});

In this setting,this error comes.

Bucket cannot have public ACLs set with BlockPublicAccess enabled

So I change

blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL,

to

//blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL,

However same situation happens.

Bucket cannot have public ACLs set with BlockPublicAccess enabled 

How can I solve this, and I wonder is it impossible for cloudfront to put log into S3 with Block public access is on?


Thanks to @Dhruv answer, I changed like this,

const bk = new s3.Bucket(this, `cm-st-cloudfront-bk`, { 
  bucketName: s3_name,
  removalPolicy: RemovalPolicy.DESTROY,
  autoDeleteObjects: true,
  blockPublicAccess: s3.BlockPublicAccess.BLOCK_ACLS
  encryption: s3.BucketEncryption.S3_MANAGED,
  versioned:true,
});
bk.addToResourcePolicy(new iam.PolicyStatement({
  actions: ['s3:PutObject'],
  effect: iam.Effect.ALLOW,
  resources: [bk.arnForObjects('*')],
  principals: [new iam.ServicePrincipal('delivery.logs.amazonaws.com')],
}));
const oai = new cloudfront.OriginAccessIdentity(this, `my-oai`,{
  comment:`Access identity for ${targetEnv}`
});

const cf = new cloudfront.CloudFrontWebDistribution(this, `Website-${targetEnv}-Distribution`, {
  comment:`CF for resource S3 ${targetEnv}`,
  viewerCertificate: {
    aliases: [],
    props: {
      cloudFrontDefaultCertificate: true,
    },
  },
  errorConfigurations: [
    {
      errorCode: 403,
      responsePagePath: "/index.html",
      responseCode: 200,
      errorCachingMinTtl: 0,
    },
    {
      errorCode: 404,
      responsePagePath: "/index.html",
      responseCode: 200,
      errorCachingMinTtl: 0,
    },
  ],
  loggingConfig: {
    bucket: bk,
    prefix: "cloudfront/",
  },
});

Now this error occurs, Invalid request provided: The S3 bucket that you specified for CloudFront logs does not enable ACL access


Solution

  • This is because CloudFront needs write access to the S3 bucket in order to store the access logs.

    You can configure the S3 bucket policy to allow write access only from the CloudFront logging service principal. You can modify your S3 bucket definition to allow CloudFront to write logs while still blocking public access:

    // Allow CloudFront logging service principal to write access logs to the bucket
    bk.addToResourcePolicy(new iam.PolicyStatement({
      actions: ['s3:PutObject'],
      effect: iam.Effect.ALLOW,
      resources: [bk.arnForObjects('*')],
      principals: [new iam.ServicePrincipal('delivery.logs.amazonaws.com')],
    }));