AWS Security Hub · CloudFront
CloudFront.5: Distributions should have logging enabled
Written and reviewed by Emnode · Last reviewed
What does AWS Security Hub CloudFront.5 check?
CloudFront.5 checks whether standard (legacy) access logging is enabled on a distribution. It reports FAILED when the `Logging.Enabled` field is false. It only evaluates standard logging to S3 — a distribution streaming real-time logs to Kinesis but with standard logging off still fails.
Why does CloudFront.5 matter?
CloudFront sits at the very edge, so its access logs carry the cleanest record of client behaviour — true viewer IP, exact requested URI, and HTTP status before caching or load balancing obscures the trail. With logging off, a breach investigation can't determine which objects were accessed at all, and the gap maps to NIST AU-2/AU-3/AU-12 and PCI DSS 10.4.2, so an auditor can verify it in seconds.
How do I fix CloudFront.5?
- Prepare an S3 log bucket with ACLs enabled (Object Ownership set to Bucket owner preferred) so CloudFront's `awslogsdelivery` group can write, and add a lifecycle rule to bound retention.
- Fetch the full config and ETag, set the `Logging` block (Enabled, Bucket, Prefix, IncludeCookies), and push it back with `update-distribution --if-match <ETag>`.
- Confirm gzipped log files appear under the prefix and stand up an Athena table so the logs are queryable.
- Deploy the `cloudfront-accesslogs-enabled` Config rule so new distributions are caught at creation.
Remediation script · bash
# 1. Lock an S3 origin: only THIS distribution may read the bucket.
cat > bucket-policy.json <<'JSON'
{
"Version": "2012-10-17",
"Statement": [{
"Sid": "AllowCloudFrontServicePrincipalReadOnly",
"Effect": "Allow",
"Principal": { "Service": "cloudfront.amazonaws.com" },
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::my-downloads-bucket/*",
"Condition": { "StringEquals": {
"AWS:SourceArn": "arn:aws:cloudfront::111122223333:distribution/E2QWRUHAPOMQZL"
} }
}]
}
JSON
aws s3api put-bucket-policy --bucket my-downloads-bucket --policy file://bucket-policy.json
# 2. Raise the minimum TLS version (the field is nested in ViewerCertificate, so send the whole config back).
aws cloudfront get-distribution-config --id E2QWRUHAPOMQZL > dist.json
ETAG=$(python3 -c "import json;print(json.load(open('dist.json'))['ETag'])")
# ... edit dist.json: ViewerCertificate.MinimumProtocolVersion = TLSv1.2_2021, ViewerProtocolPolicy = redirect-to-https ...
aws cloudfront update-distribution --id E2QWRUHAPOMQZL \
--distribution-config file://distribution-config.json --if-match "$ETAG"
# 3. Confirm the second door is shut: a raw S3 GET should now return 403.
curl -s -o /dev/null -w '%{http_code}\n' https://my-downloads-bucket.s3.amazonaws.com/file.pdf Full walkthrough (console steps, edge cases and verification) in the lesson Protect CloudFront distributions and origins.
Is CloudFront.5 a false positive?
Real-time logging to Kinesis does not satisfy CloudFront.5 — the control checks the standard `Logging.Enabled` field only, so distributions with real-time logs still need standard logging enabled to pass.
More CloudFront controls
- CloudFront.1 No default root object, exposing the distribution listing
- CloudFront.3 Distributions should require encryption in transit
- CloudFront.6 Distributions should have WAF enabled
- CloudFront.9 Distributions should encrypt traffic to custom origins
- CloudFront.10 No deprecated SSL protocols to custom origins
- CloudFront.12 A distribution points at a non-existent S3 origin (takeover risk)
- CloudFront.13 Distributions should use origin access control
- CloudFront.15 Distributions should use recommended TLS policy
- CloudFront.16 OAC for Lambda function URL origins
- CloudFront.17 Use trusted key groups for signed URLs/cookies