← All posts
2 min read

Enable S3 server access logging safely

#aws#cli#s3#storage#observability
📑 On this page

Part 61 of AWS from Zero. This lesson keeps the scope to one S3 behavior you can verify from the terminal.

What we are learning

Server access logging records requests to a source bucket. The destination needs a policy that allows the S3 logging service to write only the intended prefix.

Before you run it

REGION="ap-south-1"
SOURCE_BUCKET="replace-with-source-bucket"
LOG_BUCKET="replace-with-dedicated-log-bucket"
ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)

Use two buckets in the same Region. Keep Block Public Access enabled on both.

Cost note: Delivered logs consume S3 storage and requests in the destination bucket.

The command

cat > logging.json <<EOF
{
  "LoggingEnabled": {
    "TargetBucket": "$LOG_BUCKET",
    "TargetPrefix": "access-logs/$SOURCE_BUCKET/"
  }
}
EOF
 
cat > log-destination-policy.json <<EOF
{
  "Version": "2012-10-17",
  "Statement": [{
    "Sid": "S3ServerAccessLogsPolicy",
    "Effect": "Allow",
    "Principal": {"Service": "logging.s3.amazonaws.com"},
    "Action": "s3:PutObject",
    "Resource": "arn:aws:s3:::$LOG_BUCKET/access-logs/$SOURCE_BUCKET/*",
    "Condition": {
      "ArnLike": {"aws:SourceArn": "arn:aws:s3:::$SOURCE_BUCKET"},
      "StringEquals": {"aws:SourceAccount": "$ACCOUNT_ID"}
    }
  }]
}
EOF
 
aws s3api put-bucket-policy \
  --bucket "$LOG_BUCKET" \
  --policy file://log-destination-policy.json
 
aws s3api put-bucket-logging \
  --bucket "$SOURCE_BUCKET" \
  --bucket-logging-status file://logging.json

The dedicated destination policy grants only the S3 logging service, only from this account and source bucket, permission to write the chosen prefix.

Inspect the result

aws s3api get-bucket-logging \
  --bucket "$SOURCE_BUCKET"

Confirm the target bucket and prefix. Log delivery is best effort and not immediate.

One tiny variation

aws s3api put-bucket-logging \
  --bucket "$SOURCE_BUCKET" \
  --bucket-logging-status '{}'

An empty status disables server access logging on the source bucket.

Common mistake

Do not log a bucket into itself. That can create recursive log objects and unnecessary cost.

Cleanup

aws s3api put-bucket-logging \
  --bucket "$SOURCE_BUCKET" \
  --bucket-logging-status '{}'
aws s3api delete-bucket-policy --bucket "$LOG_BUCKET"
rm logging.json log-destination-policy.json

Disable the source configuration, then retain or delete delivered logs according to your audit policy.

Next, we will learn Inspect S3 server access logging status.

Official AWS CLI reference