Using Amazon S3 server access logs for Security, Compliance & Auditing
Overview
Organizations running workloads on AWS often store their most critical data in Amazon S3, from application data and analytics datasets to backups, logs, and regulated content. With that responsibility comes a fundamental question: how do I know who is accessing my data, what they're doing with it, and whether those actions comply with my security policies?
Amazon S3 server access logs answer that question by recording requests made to your buckets, successful or failed, authenticated or anonymous, with HTTP-level detail not available in other common log sources. With Amazon S3 server access logs now available as a native data source for CloudWatch unified data store, those logs are automatically delivered to CloudWatch without the need to build custom ETL pipelines or transformation workflows. CloudWatch unified data store transforms the raw Amazon S3 server access log data into a structured, queryable format, enabling immediate use of CloudWatch Logs Insights, metric filters, Contributor Insights rules, and Amazon S3 Tables integration. Combined with AWS CloudTrail management events, server access logs become a powerful, cost-effective pillar of your Amazon S3 security and compliance posture.
The Customer Challenge
Many teams face a common set of questions when monitoring Amazon S3 data-plane activity:
- Visibility gaps: CloudTrail management events (included at no additional cost) cover bucket-level configuration changes but don't show who is reading, writing, or deleting individual objects.
- Cost at scale: High-volume buckets (millions of requests per day) need visibility without unbounded cost growth.
- Pipeline complexity: Traditional server access log setups required bucket policies, lifecycle management, and custom transformation workflows to make the logs queryable in tools like CloudWatch. CloudWatch unified data store now eliminates the need to build custom ETL pipelines to deliver and structure those logs for analysis.
- Compliance evidence: Frameworks like PCI-DSS, HIPAA, SOC 2, and FedRAMP require proof of encryption-in-transit (TLS version), access controls, and data retention. These fields are uniquely available in server access logs.
- Operational depth: Request latency, bytes transferred, HTTP status codes, and Amazon S3 lifecycle operations (expirations, transitions) are only captured in server access logs.
This guide shows how Amazon S3 server access logs, delivered natively into CloudWatch unified data store, address these challenges and how to use them alongside CloudTrail for defense in depth.
With Amazon S3 server access logs as a native CloudWatch unified data store data source, you get broad, low-cost visibility with built-in transformation and immediate queryability, combined with guaranteed delivery from scoped CloudTrail data events on your most sensitive buckets. No custom ETL pipelines, no additional transformation workflows. Just enable the native integration and start querying, filtering, and alerting on your Amazon S3 access data.
CloudTrail Amazon S3 data events and server access logs: complementary strengths
Both CloudTrail Amazon S3 data events and Amazon S3 server access logs record object-level activity, and there is meaningful overlap in the operations they capture. Understanding what each source brings to the table helps you design a logging strategy that maximizes coverage while managing costs.
Where They Overlap
The core data-plane operations (GetObject, PutObject, DeleteObject, CopyObject, HeadObject, multipart uploads, and ListObjects) appear in both log sources when both are enabled. For these operations, you get two independent records of the same request.
What Each Source Uniquely Provides
Rather than choosing one over the other, consider what each source adds that the other cannot:
- ☁️ CloudTrail Data Events
- 📋 Server Access Logs
- 🤝 Shared Fields
| Capability | Detail |
|---|---|
| Delivery guarantee | ✅ Every API call is recorded and delivered |
| Delivery latency | Typically 5–15 minutes |
| IAM identity detail | ✅ Full userIdentity block: ARN, session context, assumed role chain, MFA status |
| Request/response parameters | ✅ Full JSON: encryption settings, ACL grants, condition keys |
| Streaming destinations | ✅ Amazon S3, CloudWatch Logs, or CloudTrail Lake |
| Selective logging | ✅ Advanced event selectors filter by bucket ARN, event name, read/write |
| Per-event cost | Per-event charge (see pricing) |
| Capability | Detail |
|---|---|
| HTTP-level detail | ✅ http_status, bytes_sent_size, object_size, total_duration, turn_around_duration, referer |
| Signature version | ✅ Explicit signature_version field (SigV2 vs SigV4) |
| Authentication type | ✅ Explicit field (AuthHeader, QueryString, or null for anonymous) |
| ACL required | ✅ acl_required field for ownership controls migration |
| S3 lifecycle operations | ✅ S3.EXPIRE.OBJECT, S3.TRANSITION_SIA.OBJECT, etc. |
| Source region | ✅ source_region (originating region, useful for cross-region detection) |
| Native CloudWatch unified data store integration | ✅ Logs flow directly into CloudWatch unified data store with immediate access to Logs Insights, metric filters, Contributor Insights, and Amazon S3 Tables |
| Built-in transformation | ✅ CloudWatch unified data store automatically transforms raw Amazon S3 server access logs into a structured, queryable format with no custom ETL pipelines required |
| Per-event cost | ✅ CloudWatch Logs ingestion + storage (see pricing). Amazon S3 server access log events are significantly smaller than CloudTrail data events, resulting in lower per-event ingestion cost |
Both sources provide these fields, and either source works:
| Field | Description |
|---|---|
| TLS version and cipher suite | Transport-layer security details for the connection |
| Source IP address | IP address of the requester |
| User agent | Client tool or SDK that made the request |
| Error codes | Amazon S3 error responses (e.g., AccessDenied, NoSuchKey) |
| Object key | The object name that was accessed |
| Bucket name | The target bucket for the request |
When to Lean on Each Source
- CloudTrail Strengths
- Server Access Log Strengths
- 🔒 Compliance audits requiring complete accounting of every object access. Guaranteed delivery means no gaps in the audit trail.
- 🔍 Forensic investigations where you need the full IAM identity chain: who assumed which role, whether MFA was used, what session context was active.
- 📋 Understanding request parameters: what encryption algorithm was applied to a PutObject, what ACL grants were set, what condition keys were evaluated.
- ⚡ Real-time streaming to CloudWatch Logs or CloudTrail Lake for immediate analysis, alerting, and dashboarding.
- 🎯 Selective, cost-controlled logging. Advanced event selectors let you log only write operations on specific buckets, so you pay only for what matters most.
- 🔑 Detecting deprecated SigV2 usage. The
signature_versionfield is only available in server access logs. - ♻️ Tracking Amazon S3 lifecycle operations. Expirations, transitions, and delete marker creation are internal Amazon S3 actions that CloudTrail does not log.
- ⏱️ Performance analysis. Request latency (
total_duration,turn_around_duration), bytes transferred, and object size are only in server access logs. - 💰 High-volume buckets with cost efficiency. For buckets handling millions of requests per day, server access logs delivered through CloudWatch unified data store provide comprehensive visibility at CloudWatch Logs ingestion and storage cost. Because Amazon S3 server access log events are significantly smaller than CloudTrail data events, the per-event ingestion cost is substantially lower, and CloudWatch's volume-tiered pricing further reduces cost at scale (see CloudWatch pricing).
- 🔄 Zero pipeline management. CloudWatch unified data store automatically transforms raw Amazon S3 server access log data into a structured, queryable format upon ingestion. This eliminates the need to provision a destination Amazon S3 bucket, manage bucket policies, configure log object lifecycle rules, or build custom ETL pipelines to parse and normalize the data.
- 📊 Immediate observability. Because Amazon S3 server access logs land directly in CloudWatch unified data store, you get instant access to Logs Insights queries, metric filters, Contributor Insights rules, and Amazon S3 Tables integration without any additional configuration or pipeline setup.
- 🏷️ Identifying ACL-dependent requests. The
acl_requiredfield helps you plan a migration to bucket-owner-enforced Object Ownership.
The hybrid approach: defense in depth
A hybrid strategy combines the strengths of both sources to deliver broad coverage at a manageable cost. The Amazon S3 security best practices documentation recommends enabling server access logging and using AWS CloudTrail as separate monitoring and auditing best practices. Using both together gives you defense in depth.
Three-Layer Architecture
| Layer | What to Enable | Purpose | Cost |
|---|---|---|---|
| 1. CloudTrail management events | Trail (first copy at no additional cost) | Bucket-level config changes, PutBucketPolicy, DeleteBucketEncryption, etc. Guaranteed delivery. | No additional cost (first copy) |
| 2. Amazon S3 server access logs (via CloudWatch unified data store) | Enable on all buckets with CloudWatch unified data store as the destination | Broad data-plane visibility with HTTP-level detail, lifecycle tracking, SigV2 detection, and performance metrics. Logs are automatically transformed into a structured, queryable format by CloudWatch unified data store with no ETL required. Immediate access to Logs Insights, metric filters, Contributor Insights, and Amazon S3 Tables. | CloudWatch Logs ingestion + storage (Amazon S3 server access log events are smaller than CloudTrail data events, resulting in lower per-event cost; volume-tiered pricing reduces cost further at scale) |
| 3. CloudTrail data events (scoped) | Write-only on sensitive buckets via advanced event selectors | Guaranteed delivery for the most critical mutations, PutObject, DeleteObject, CopyObject on buckets holding PII, financial data, or regulated content. | Per-event charge (see pricing), scoped to reduce volume |
Scoping CloudTrail Data Events to Control Cost
The key to making the hybrid approach cost-effective is using advanced event selectors to log only what matters most. For example, logging only write operations on three sensitive buckets:
[
{
"Name": "S3WriteOnlySensitiveBuckets",
"FieldSelectors": [
{ "Field": "eventCategory", "Equals": ["Data"] },
{ "Field": "resources.type", "Equals": ["AWS::S3::Object"] },
{ "Field": "readOnly", "Equals": ["false"] },
{ "Field": "resources.ARN", "StartsWith": [
"arn:aws:s3:::my-pii-bucket/",
"arn:aws:s3:::my-financial-data/",
"arn:aws:s3:::my-compliance-archive/"
]
}
]
}
]
This selector logs only write operations (PutObject, DeleteObject, CopyObject, etc.) on three specific buckets. This dramatically reduces cost compared to logging all data events on all buckets, while guaranteeing delivery for the most security-critical mutations. Apply it to your trail or event data store using the CloudTrail console, CLI (
put-event-selectors), or CloudFormation.
Cost at Scale
The cost advantage of the hybrid approach becomes clear when you compare CloudWatch Logs ingestion pricing for the two data sources side by side.
Amazon S3 server access logs are classified as CloudWatch vended logs, which benefit from volume-tiered ingestion pricing. The per-GB rate decreases as your monthly ingestion volume grows (for example, $0.50/GB for the first 10 TB, dropping to $0.05/GB above 50 TB in US East). This makes server access logs progressively more cost-effective at scale. Additionally, Amazon S3 server access log events are significantly smaller in size compared to CloudTrail data events, meaning you ingest fewer GB for the same number of requests.
CloudTrail events (management and data events) delivered to a CloudWatch Logs log group are charged for delivery plus CloudWatch custom logs ingestion pricing. CloudTrail data events provide additional context (see What each source uniquely provides), making them the right choice for your most sensitive buckets where you need complete audit trails with no gaps.
The combination of volume-tiered pricing and smaller event size means that, at high request volumes, Amazon S3 server access logs can cost significantly less per request to ingest into CloudWatch than CloudTrail data events. By scoping CloudTrail data events to write-only operations on your most sensitive buckets (using advanced event selectors), you limit that higher-cost ingestion to only the fraction of traffic that requires guaranteed delivery. Server access logs cover the remaining breadth at a lower per-GB rate.
CloudWatch unified data store also eliminates the operational cost and complexity of building custom ETL pipelines. The logs are natively delivered and automatically transformed into structured JSON upon ingestion, removing the need for destination bucket provisioning, log object lifecycle management, or custom transformation workflows.
Pricing changes over time. Before finalizing your logging strategy, review the latest rates on the Amazon CloudWatch pricing page. Compare the Vended Logs tier (for Amazon S3 server access logs) against the Custom Logs ingestion rate (for CloudTrail events delivered to CloudWatch Logs). Use the AWS Pricing Calculator to help calculate the cost.
Decision Guide
Use this quick reference to decide your logging strategy per bucket:
- Q1: Sensitive Data?
- Q2: Unique Fields?
- Q3: High Volume?
Does this bucket hold regulated, sensitive, or business-critical data?
✅ Yes → Enable CloudTrail data events (write-only at minimum) for guaranteed delivery and full identity chain. Also enable server access logs via CloudWatch unified data store for HTTP-level detail, lifecycle tracking, and built-in transformation with no ETL required.
➡️ No → See Q2.
Do you need to detect SigV2 usage, track lifecycle operations, or analyze request latency?
✅ Yes → Enable server access logs via CloudWatch unified data store. These fields are only available in Amazon S3 server access log, and CloudWatch unified data store automatically transforms the logs into a structured, queryable format for immediate analysis.
➡️ No → See Q3.
Is the bucket high-volume (millions of requests/day) with cost sensitivity?
✅ Yes → Enable server access logs via CloudWatch unified data store. Amazon S3 server access log events are significantly smaller than CloudTrail data events, keeping CloudWatch ingestion costs low even at high request volumes. CloudWatch's volume-tiered pricing further reduces cost at scale. CloudWatch unified data store automatically transforms the logs for immediate querying with no ETL pipeline required. Use CloudTrail management events (included at no additional cost) for bucket-level config change alerting.
❌ No → Enable CloudTrail data events for guaranteed, queryable object-level logging. Server access logs via CloudWatch unified data store are optional but add HTTP-level detail, lifecycle tracking, and performance metrics at a lower per-event cost than CloudTrail data events.
What Amazon S3 server access logs capture
Every request to an Amazon S3 bucket with server access logging enabled generates a log record with over 25 fields. The fields most relevant to security, compliance, and auditing are grouped below by use case.
- 👤 Identity & Access
- 📦 Request Details
- 📊 Response & Performance
- 🔐 Encryption & Compliance
- ♻️ Lifecycle & Internal
| Field | Value | Example |
|---|---|---|
requester | IAM principal (canonical user ID or assumed-role ARN) | arn:aws:sts::123456789012:assumed-role/MyRole/session |
remote_ip | Source IP of the requester | 203.0.113.42 |
authentication_type | How the request was authenticated | AuthHeader, QueryString, or null (anonymous) |
signature_version | Signing protocol used | SigV4 or SigV2 (deprecated) |
acl_required | Whether ACL authorization was needed (boolean) | true, false, or null |
access_point_arn | S3 Access Point ARN (if used) | arn:aws:s3:us-east-1:123456789012:accesspoint/my-ap |
These fields answer who accessed your data and how they authenticated. Use them to detect anonymous access (authentication_type IS NULL), deprecated SigV2 clients, and requests routed through Access Points.
| Field | Value | Example |
|---|---|---|
operation | The Amazon S3 operation performed | REST.GET.OBJECT, REST.DELETE.OBJECT, S3.EXPIRE.OBJECT |
key_name | Object key accessed | /data/customers/export-2025.csv |
bucket_name | Target bucket | my-production-bucket |
source_region | AWS Region the request originated from | us-east-1 or null |
user_agent | Client tool or SDK | aws-cli/2.15.0, curl/7.88.1, Boto3/1.34.0 |
These fields answer what was accessed and from where. Use them to detect unexpected operations on sensitive objects, cross-region access patterns, and unauthorized tooling (curl, wget on production buckets).
| Field | Value | Example |
|---|---|---|
http_status | HTTP response code | 200, 403, 404, 503 |
error_code | Amazon S3 error string | AccessDenied, NoSuchKey, SlowDown |
bytes_sent_size | Response bytes transferred | 2662992 |
object_size | Total size of the object | 3462992 |
total_duration | End-to-end request duration (ms) | 70 |
turn_around_duration | Amazon S3 processing time (ms) | 10 |
These fields answer what happened and how fast. Use them to detect 403/404 spikes (brute-force), large data exfiltration (bytes_sent_size), 5xx throttling (SlowDown), and performance degradation.
| Field | Value | Example |
|---|---|---|
tls_version | TLS version negotiated | TLSv1.2, TLSv1.3 |
cipher_suite | TLS cipher suite used | ECDHE-RSA-AES128-GCM-SHA256 |
signature_version | Signing protocol | SigV4 or SigV2 |
These fields provide compliance evidence for encryption-in-transit requirements. PCI-DSS, FedRAMP, and NIST 800-53 mandate TLS 1.2+. The signature_version field is the only way to find clients still using deprecated SigV2.
S3 lifecycle operations are only recorded in server access logs. CloudTrail does not log these internal actions.
| Operation | Meaning |
|---|---|
S3.EXPIRE.OBJECT | Object expired by a lifecycle rule |
S3.CREATE.DELETEMARKER | Delete marker created by lifecycle on a versioned bucket |
S3.TRANSITION_SIA.OBJECT | Object transitioned to Amazon S3 Standard-IA |
S3.TRANSITION_ZIA.OBJECT | Object transitioned to Amazon S3 One Zone-IA |
S3.TRANSITION_INT.OBJECT | Object transitioned to Amazon S3 Intelligent-Tiering |
S3.TRANSITION_GIR.OBJECT | Object transitioned to Amazon S3 Glacier Instant Retrieval |
S3.TRANSITION.OBJECT | Object transitioned to Amazon S3 Glacier Flexible Retrieval |
S3.TRANSITION_GDA.OBJECT | Object transitioned to Amazon S3 Glacier Deep Archive |
These lifecycle operations are not available in CloudTrail data events. If you need to prove that your data retention policies are being enforced (expirations, transitions, delete markers), server access logs are the only source.
Enabling Amazon S3 Server Access Logging for CloudWatch
Setting up delivery takes a few steps in the Amazon S3 console, or a few API calls with the AWS CLI. You can also standardize delivery across your AWS Organization with CloudWatch Telemetry Enablement Rules.
Option 1: Telemetry Enablement Rules
CloudWatch Telemetry Enablement Rules let you automatically enable Amazon S3 server access log delivery to CloudWatch Logs for buckets, both new and existing, without per-bucket setup. Rules can be scoped at the individual account level or across an AWS Organization. For organization-wide rules, you must configure them from the management account or a delegated administrator account.
- Open the CloudWatch console.
- In the navigation pane, choose Ingestion.
- Choose the Enablement rules tab, then choose Add rule.
- Select Configure telemetry for Amazon S3.
- Enter a descriptive Rule name (e.g.,
S3-Access-Logs-Enablement). - Optionally add Tag Key/Value under Select data source scope to scope the rule to specific resources.
- For Target regions, leave the default for the current region or select specific regions. Choose Next.
- Configure the Log group name pattern and Retention setting. Choose Next.
- Review and choose Configure Amazon S3 Logs.
Once active, CloudWatch begins ingesting Amazon S3 logs from resources within scope. Logs are automatically transformed into structured JSON with no additional Lambda functions or Glue jobs required.
Option 2: Amazon S3 Console (Per Bucket)
- Open the Amazon S3 console, navigate to your bucket, and choose the Properties tab.
- In the Log delivery to CloudWatch section, choose Add → To Amazon CloudWatch Logs.
- Select a Destination log group. To also query with SQL, select Enable Amazon S3 Tables integration.
- Under Service access, leave Auto-create a new role with default permissions selected.
- Choose Add.
Option 3: AWS CLI (Automation)
For scripted or automated deployments across multiple buckets, the AWS CLI gives you full control over each step.
Step 1: Create a delivery source (per source bucket)
aws logs put-delivery-source \
--name my-sal-source \
--resource-arn arn:aws:s3:::my-bucket \
--log-type S3_SERVER_ACCESS_LOGS \
--region us-east-1
Step 2: Create a delivery destination (once per log group)
aws logs put-delivery-destination \
--name my-sal-destination \
--delivery-destination-configuration \
'{"destinationResourceArn": "arn:aws:logs:us-east-1:123456789012:log-group:/aws/vendedlogs/s3/my-bucket"}' \
--region us-east-1
Step 3: Create a delivery (per source bucket)
aws logs create-delivery \
--delivery-source-name my-sal-source \
--delivery-destination-arn arn:aws:logs:us-east-1:123456789012:delivery-destination:my-sal-destination \
--region us-east-1
Step 4: Enable the Amazon S3 Tables integration (once per account per Region, optional)
aws observabilityadmin create-s3-table-integration \
--role-arn arn:aws:iam::123456789012:role/CWLogsS3TableIntegrationRole \
--encryption '{"SseAlgorithm":"AES256"}' \
--region us-east-1
Then associate the Amazon S3 server access log data source:
aws logs associate-source-to-s3-table-integration \
--integration-arn arn:aws:observabilityadmin:us-east-1:123456789012:s3tableintegration/s3tableintegration \
--data-source '{"name":"amazon_s3","type":"server_access"}' \
--region us-east-1
Security & Compliance Queries
The following OpenSearch SQL queries run in CloudWatch Logs Insights against your Amazon S3 server access log group. Select "OpenSearch SQL" from the language dropdown before running. Replace YOUR_S3_ACCESS_LOG_GROUP with your actual log group name.
- 🚨 Security
- ✅ Compliance