- Newest
- Most votes
- Most comments
The issue you're experiencing is related to how CloudFront handles permissions for log delivery to S3 buckets when configured programmatically versus through the console.
When you enable CloudFront logging through the console, CloudFront automatically updates the bucket's ACL to give the awslogsdelivery account FULL_CONTROL permission to write logs to your bucket. However, when using CLI or Terraform, you need to ensure that:
-
Your IAM role has the necessary permissions to modify the bucket ACL (
s3:GetBucketAclands3:PutBucketAcl). -
The S3 bucket must have ACLs enabled. If you're using the "Bucket owner enforced" setting for S3 Object Ownership (which disables ACLs), CloudFront cannot write logs to the bucket.
CloudFront uses a different permissions model than other AWS services that send logs to S3. While your bucket policy correctly grants the cloudfront.amazonaws.com service principal the s3:PutObject permission, CloudFront specifically requires ACL permissions rather than just bucket policy permissions.
To fix this issue:
-
Make sure ACLs are enabled on your S3 bucket by checking the Object Ownership setting (it should be "Bucket owner preferred" or "Object writer" instead of "Bucket owner enforced").
-
Ensure your IAM role has the
s3:GetBucketAclands3:PutBucketAclpermissions. -
If you're using standard logging (v2), consider following the cross-account logging setup which uses the delivery.logs.amazonaws.com service principal instead.
The console handles these ACL modifications automatically, which is why it works there but fails when using CLI or Terraform.
Sources
Access control in Amazon S3 - Amazon Simple Storage Service
Configure standard logging (legacy) - Amazon CloudFront
Logs sent to Amazon S3 - Amazon CloudWatch Logs
Send CloudFront logs to an S3 bucket in another account | AWS re:Post
hi,
This is a complex scenario, while you have done configuration for both side terraform and s3 bucket policy right, as per the docs, I see.
as accessdiend is basically policies and configuration issues.
here in your situation access denied issue is
An error occurred (AccessDenied) when calling the UpdateDistribution operation: You don't have permission to access the S3 bucket for CloudFront logs: <your-bucket-name>.s3.amazonaws.com If you're using IAM, you need s3:GetBucketAcl and s3:PutBucketAcl permissions to create a distribution or to update log settings for an existing distribution. In addition, the S3 ACL for the bucket must grant you FULL_CONTROL.
as error says "You don't have permission to access the S3 bucket for CloudFront logs"
so, in my understanding S3 bucket policy is denying,
Your original bucket policy with the s3:x-amz-acl condition is technically correct, **but **if you can temporarily remove this condition, and rely on the ACLs and Object Ownership (which are necessary anyway) to enforce the delivery, thereby satisfying the API's less restrictive check during the update operation.
temporarily removing the condition and see if it works?
Best,
Hi, Thanks for your reply! I tried removing the "s3:x-amz-acl" condition from the bucket policy, but unfortunately I’m still getting the same error.
Just to clarify, this is my rest Terraform configuration for the S3 bucket that CloudFront should write logs to: resource "aws_s3_bucket" "cloudfront_logs" { bucket ="bucket-name"
tags = { Name = "bucket-name" } }
resource "aws_s3_bucket_public_access_block" "cloudfront_logs" { bucket = aws_s3_bucket.cloudfront_logs.id
block_public_acls = true block_public_policy = true ignore_public_acls = true restrict_public_buckets = true }
resource "aws_s3_bucket_ownership_controls" "cloudfront_logs" { bucket = aws_s3_bucket.cloudfront_logs.id
rule { object_ownership = "BucketOwnerPreferred" } }
resource "aws_s3_bucket_acl" "cloudfront_logs_acl" { bucket = aws_s3_bucket.cloudfront_logs.id acl = "log-delivery-write"
depends_on = [aws_s3_bucket_ownership_controls.cloudfront_logs] }
resource "aws_s3_bucket_lifecycle_configuration" "cloudfront_logs" { bucket = aws_s3_bucket.cloudfront_logs.id rule { id = "log" status = "Enabled" filter { prefix = "/" } expiration { days = 1 } } }
I’m using: Object ownership = BucketOwnerPreferred ACL = log-delivery-write Admin permissions on my IAM role (including s3:GetBucketAcl and s3:PutBucketAcl)
what you think i can do?
Hi again,
As per my understanding from the docs
When using: object_ownership = "BucketOwnerPreferred"
Terraform applies the ACL log-delivery-write, which grants access to the S3 Log Delivery group, not to the CloudFront canonical user.
However, CloudFront requires permissions for its own canonical user ID, which is different from the “log-delivery-write” group.
[https://docs.aws.amazon.com/AmazonS3/latest/userguide/about-object-ownership.html
OR
switching to BucketOwnerEnforced solves the issue without needing the CloudFront canonical user ID, since ACLs are disabled entirely. and remove the condition "s3:x-amz-acl": "bucket-owner-full-control" because ACLs are disabled in this mode.
This is my current understanding I faced a similar issue using CloudFormation last year
make sure the bucket name matches the actual S3 bucket name (not ARN)
Best
Thanks for the detailed explanation Just to clarify a few things based on what I tested on my side: Using only the bucket name in the logging_config does not work, cloudFront returns this error unless I provide the ARN: Error: updating CloudFront Distribution: InvalidArgument: The S3 bucket that you specified for CloudFront logs does not enable ACL access: aws-cloudfront-logs-sandbox-digitalidf-il.s3.amazonaws.com When I switch to the ARN — the validation passes.
I tried your first recommendation (BucketOwnerEnforced) CloudFront fails with the ACL-based error, because CloudFront still expects ACLs for log delivery: InvalidArgument: The S3 bucket that you specified for CloudFront logs does not enable ACL access So ACL-disabled mode is incompatible with CloudFront logging at this moment.
I tried the approach using aws_canonical_user_id Still ends with: AccessDenied: You don't have permission to access the S3 bucket for CloudFront logs If you're using IAM, you need s3:GetBucketAcl and s3:PutBucketAcl permissions... and the S3 ACL for the bucket must grant you FULL_CONTROL. Which is the same main issue I’ve been stuck on.
So: The bucket name alone is rejected — ARN is required. BucketOwnerEnforced mode fails because CloudFront needs ACL access. Granting canonical user permissions still leads to the same AccessDenied error.
Let me know if you've seen a Terraform-specific workaround, or if there's something else I'm missing in the policy/ACL setup.
thanks for sharing your testing scenarios.
Here is a scenario I used with my existing CloudFront distribution, sending logs to a newly created S3 bucket using Terraform. I also included my CLI output for verification.
google docs created for this scenario: https://docs.google.com/document/d/e/2PACX-1vT81wh3algLi8vRWxzINZUGYIrMWiR-7UorjkcOooqsEUj4ehIrn0Hrso7UiTdG3sWvK3LOzo5Cq_eA/pub
After running the CLI linking command, I waited a few minutes for the logs to populate, and it worked. Output shows:
malini@Malini:~/projects/cloudfront-logging-demo$ aws cloudfront get-distribution --id EO9YJD19H7YWS --query 'Distribution.DistributionConfig.Logging'
{
"Enabled": true,
"IncludeCookies": false,
"Bucket": "malini-cloudfront-logs-demo.s3.amazonaws.com",
"Prefix": "cf-logs/"
}
Conclusion:-> CloudFront logging requires ACL-based delivery. Using BucketOwnerPreferred with ACLs enabled and granting CloudFront bucket-owner-full-control resolves AccessDenied errors. This setup works across any region
Best,
Relevant content
- asked 2 years ago

I am not using cross-account logging.
I am using an IAM role with full Administrator permissions, which includes s3:GetBucketAcl and s3:PutBucketAcl.
The S3 bucket is configured with Object Ownership = Bucket owner preferred, so ACLs are enabled.
Additionally, I have explicitly set the bucket ACL for CloudFront log delivery: resource "aws_s3_bucket_acl" "cloudfront_logs_acl" { bucket = aws_s3_bucket.cloudfront_logs.id acl = "log-delivery-write" }
Despite all this, enabling CloudFront logging via CLI or Terraform fails with AccessDenied, while it works via the AWS Console.
Could this behavior be caused by CloudFront requiring something additional beyond standard admin permissions and ACL settings when configured programmatically?