Cross-Account AWS CloudFront Logging: Configure S3 Bucket Access for Multi-Account Log Aggregation


2 views

When managing multiple AWS accounts, centralizing CloudFront access logs in a single S3 bucket becomes crucial for streamlined monitoring and analysis. The key challenge lies in properly configuring cross-account permissions while maintaining security best practices.

To enable CloudFront from Account A to write logs to an S3 bucket in Account B, you need to establish these permissions:

Account A (CloudFront) → IAM Trust → Account B (S3 Bucket)

1. Configure the Destination Bucket Policy

In Account B, apply this bucket policy to your logging bucket (replace placeholders):

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowCloudFrontLogDelivery",
      "Effect": "Allow",
      "Principal": {
        "Service": "delivery.logs.amazonaws.com"
      },
      "Action": [
        "s3:PutObject",
        "s3:PutObjectAcl"
      ],
      "Resource": "arn:aws:s3:::your-log-bucket-name/AWSLogs/account-A-id/*",
      "Condition": {
        "StringEquals": {
          "s3:x-amz-acl": "bucket-owner-full-control"
        }
      }
    }
  ]
}

2. Set CloudFront Distribution Logging

In Account A, configure your CloudFront distribution with the cross-account bucket ARN:

aws cloudfront update-distribution \
  --id EDFDVBD6EXAMPLE \
  --distribution-config file://dist-config.json

Where dist-config.json contains:

{
  "CallerReference": "my-distribution",
  "Logging": {
    "Enabled": true,
    "IncludeCookies": false,
    "Bucket": "your-log-bucket-name.s3.amazonaws.com",
    "Prefix": "AWSLogs/account-A-id/"
  }
}

After implementation:

  • Trigger requests to your CloudFront distribution
  • Check S3 bucket for new log files (may take 5-60 mins)
  • Verify ACLs on delivered logs show proper ownership

403 Access Denied Errors

If logs fail to deliver, check:

  • Bucket policy syntax and ARN formats
  • Account ID in the resource path matches CloudFront account
  • No S3 bucket ACLs are blocking the delivery service

Log Delivery Latency

Remember CloudFront logs are delivered asynchronously. Implement S3 event notifications if you need real-time processing:

aws s3api put-bucket-notification-configuration \
  --bucket your-log-bucket-name \
  --notification-configuration file://notification.json

When managing multiple AWS accounts, consolidating CloudFront access logs into a centralized S3 bucket presents unique permission challenges. The standard documentation doesn't clearly address this cross-account scenario, particularly regarding bucket ACLs and IAM policies.

For this setup, you'll need:

  • A destination S3 bucket in the centralized logging account
  • IAM permissions to modify both the bucket policy and CloudFront distributions
  • The canonical ID of the CloudFront service account for your region

First, retrieve the CloudFront canonical ID for your region (this example uses us-east-1):

aws cloudfront list-cloud-front-origin-access-identities \
    --query 'CloudFrontOriginAccessIdentityList.Items[?Comment==OAI-for-S3].Id' \
    --output text

Apply this bucket policy to your centralized logging bucket:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AllowCloudFrontLogDelivery",
            "Effect": "Allow",
            "Principal": {
                "Service": "delivery.logs.amazonaws.com"
            },
            "Action": [
                "s3:GetBucketAcl",
                "s3:PutObject"
            ],
            "Resource": [
                "arn:aws:s3:::your-central-log-bucket",
                "arn:aws:s3:::your-central-log-bucket/*"
            ],
            "Condition": {
                "StringEquals": {
                    "aws:SourceAccount": [
                        "source-account-id-1",
                        "source-account-id-2"
                    ]
                },
                "ArnLike": {
                    "aws:SourceArn": [
                        "arn:aws:cloudfront::source-account-id-1:distribution/*",
                        "arn:aws:cloudfront::source-account-id-2:distribution/*"
                    ]
                }
            }
        }
    ]
}

Configure each distribution to log to the central bucket:

aws cloudfront update-distribution \
    --id YOUR_DISTRIBUTION_ID \
    --distribution-config file://dist-config.json

Where dist-config.json contains:

{
    "Logging": {
        "Enabled": true,
        "IncludeCookies": false,
        "Bucket": "your-central-log-bucket.s3.amazonaws.com",
        "Prefix": "cloudfront-logs/account-id-1/"
    }
}

Common issues include:

  • Missing PutObject permission for the log delivery service
  • Incorrect bucket policy conditions
  • Bucket encryption conflicts

Check CloudTrail logs for permission errors if logs don't appear within 24 hours of configuration.

For infrastructure-as-code users, here's a Terraform example:

resource "aws_s3_bucket_policy" "cloudfront_logs" {
  bucket = aws_s3_bucket.central_logs.id
  policy = data.aws_iam_policy_document.cloudfront_log_delivery.json
}

data "aws_iam_policy_document" "cloudfront_log_delivery" {
  statement {
    principals {
      type        = "Service"
      identifiers = ["delivery.logs.amazonaws.com"]
    }
    actions = [
      "s3:GetBucketAcl",
      "s3:PutObject"
    ]
    resources = [
      aws_s3_bucket.central_logs.arn,
      "${aws_s3_bucket.central_logs.arn}/*"
    ]
    condition {
      test     = "StringEquals"
      variable = "aws:SourceAccount"
      values   = var.source_account_ids
    }
  }
}