Skip to content

How do I send CloudFront logs from one account to an Amazon S3 bucket in a different account?

3 minute read
0

I want my Amazon CloudFront distribution to send logs from one AWS account to an Amazon Simple Storage Service (Amazon S3) bucket that's in a different account. However, I receive an Access Denied (403) error message when I try to configure the cross-account logging destination.

Short description

To resolve the "Access Denied" error and correctly configure cross-account logging, you must give CloudFront permission to write logs to your S3 bucket.

Important: If you use an S3 bucket in the same account, then you don't need to set up cross-account logging. CloudFront automatically creates the required S3 bucket policy.

Resolution

Note: If you receive errors when you run AWS Command Line Interface (AWS CLI) commands, then see Troubleshooting errors for the AWS CLI. Also, make sure that you're using the most recent AWS CLI version.

In the following resolution, Account A is the account where your CloudFront distribution is located. Account B is the destination account where your S3 bucket is located.

To set up cross-account logging and give CloudFront permission to write logs to your S3 bucket, complete the following steps:

  1. In Account A, set up standard logging (v2).
    Note: It's a best practice to use standard logging (v2) instead of legacy standard logging (v1).
  2. In Account A, run the following put-delivery-source AWS CLI command to create a delivery source with your CloudFront distribution:
    aws logs put-delivery-source \
    --name DELIVERY_SOURCE_NAME \
    --resource-arn arn:aws:cloudfront::SOURCE_ACCOUNT_ID:distribution/DISTRIBUTION_ID \
    --log-type ACCESS_LOGS \
    --region us-east-1
    Note: Replace DELIVERY_SOURCE_NAME, SOURCE_ACCOUNT_ID, DISTRIBUTION_ID, and ACCESS_LOGS with your values.
  3. In Account B, add the following bucket policy to the S3 bucket to allow the delivery.logs.amazonaws.com service principal to upload logs:
    {
        "Version": "2012-10-17",
        "Statement": [
            {
                "Sid": "AWSLogsDeliveryWrite",
                "Effect": "Allow",
                "Principal": {
                    "Service": "delivery.logs.amazonaws.com"
                },
                "Action": "s3:PutObject",
                "Resource": "arn:aws:s3:::BUCKET_NAME/PREFIX/*",
                "Condition": {
                    "StringEquals": {
                        "aws:SourceAccount": "SOURCE_ACCOUNT_ID",
                        "s3:x-amz-acl": "bucket-owner-full-control"
                    },
                    "ArnLike": {
                        "aws:SourceArn": "arn:aws:logs:us-east-1:SOURCE_ACCOUNT_ID:delivery-source:DELIVERY_SOURCE_NAME"
                    }
                }
            }
        ]
    }
    Note: Replace BUCKET_NAME, PREFIX, SOURCE_ACCOUNT_ID, and DELIVERY_SOURCE_NAME with your values.
  4. In Account B, run the following put-delivery-destination command to create the delivery destination:
    aws logs put-delivery-destination \
    --name DELIVERY_DESTINATION_NAME \
    --delivery-destination-configuration destinationResourceArn=arn:aws:s3:::BUCKET_NAME/PREFIX \
    --region us-east-1
    Note: Replace DELIVERY_DESTINATION_NAME, BUCKET_NAME, and PREFIX with your values. Account B creates a delivery destination policy in your new delivery destination. The policy gives Account A permission to create a log delivery.
  5. Use your preferred JSON editor to create the following destination policy:
    {
        "Version": "2012-10-17",
        "Statement": [{
            "Sid": "AllowCreateDelivery",
            "Effect": "Allow",
            "Principal": {
                "AWS": "SOURCE_ACCOUNT_ID"
            },
            "Action": [
                "logs:CreateDelivery"
            ],
            "Resource": "arn:aws:logs:us-east-1:DESTINATION_ACCOUNT_ID:delivery-destination:DELIVERY_DESTINATION_NAME"
        }]
    }
    Note: Replace SOURCE_ACCOUNT_ID, DESTINATION_ACCOUNT_ID, and DELIVERY_DESTINATION_NAME with your values.
  6. Name the policy destination-policy-s3.json, and then save the file to your local machine.
  7. In Account B, run the following put-delivery-destination-policy command to add the destination-policy-s3.json policy to the delivery destination:
    aws logs put-delivery-destination-policy \
    --delivery-destination-name DELIVERY_DESTINATION_NAME  \
    --delivery-destination-policy file://destination-policy-s3.json \
    --region us-east-1
    Note: Replace DELIVERY_DESTINATION_NAME with your value.
  8. In Account A, run the following create-delivery command to connect the delivery source in Account A to the delivery destination in Account B:
    aws logs create-delivery \
    --delivery-source-name S3-delivery \
    --delivery-destination-arn arn:aws:logs:us-east-1:DESTINATION_ACCOUNT_ID:delivery-destination:DELIVERY_DESTINATION_NAME \
    --region us-east-1
    Note: Replace DESTINATION_ACCOUNT_ID and DELIVERY_DESTINATION_NAME with your values.
  9. In Account A, perform an operation on your CloudFront distribution to verify that your distribution delivered logs to the S3 bucket in Account B.
    Note: It might take several minutes for the logs to appear in the bucket.

Related information

Cross-account delivery example

AWS OFFICIALUpdated 3 months ago