SAA-C03
Deep Dive
S3 is the most widely used storage service on AWS and one of the most targeted when misconfigured. The SAA-C03 exam tests your ability to protect data in S3 with the correct mechanism for each scenario.
Contents
S3 has multiple access control layers that work together. Block Public Access is the first line of defense — enabled by default on all new accounts.
| Mechanism | Applies to | Recommended use |
|---|---|---|
| Block Public Access | Account or bucket | Always ON in production. Prevents accidental public access. |
| Bucket Policy (resource-based) | Bucket and objects | Cross-account access, CloudFront OAC, policies conditioned on IP/VPC. |
| IAM Identity Policy | IAM user/role | Access for identities within the same AWS account. |
| S3 ACLs | Individual bucket or object | Legacy — only use if you need per-object permissions. AWS recommends disabling them. |
| VPC Endpoint Policy | Access from a VPC | Restriction: only certain buckets are accessible from a specific VPC. |
Common bucket policy scenarios
Cross-account access
Account B accesses a bucket in Account A. Resource policy in Account A + IAM policy in Account B.
"Principal": {"AWS": "arn:aws:iam::ACCOUNT-B:root"}IP-based restriction
Only allow access from corporate IP ranges.
"Condition": {"IpAddress": {"aws:SourceIp": "203.0.113.0/24"}}Deny HTTP (HTTPS only)
Force encryption in transit by denying non-secure requests.
"Condition": {"Bool": {"aws:SecureTransport": "false"}} → DenyVPC-based restriction
Only allow access from a specific VPC (via VPC Endpoint).
"Condition": {"StringEquals": {"aws:sourceVpc": "vpc-xxxxx"}}ACLs — when (not) to use them
AWS recommends disabling ACLs
ACLs are S3's legacy access mechanism. The recommended new configuration is Bucket Owner Enforced (disables ACLs). Every newly created bucket should rely only on bucket policies.
Make an object public
✅ Bucket policy or CloudFront
❌ Object ACL public-read
Cross-account access
✅ Cross-account bucket policy
❌ Bucket ACL grantee
SSE-S3 (Server-Side Encryption with S3-managed keys)
AWS manages keys automatically. AES-256. No extra cost. No per-access key traceability.
SSE-KMS (Server-Side Encryption with KMS keys)
AWS KMS manages the keys. Every access to an object generates an API call to KMS — traceable in CloudTrail.
SSE-C (Server-Side Encryption with customer-provided keys)
The client provides the key on each request. AWS uses it to encrypt/decrypt and discards it. You keep the key.
Client-Side Encryption
The client encrypts before uploading to S3. S3 stores already-encrypted data. AWS never sees the plaintext.
Encryption in transit
S3 supports HTTPS (TLS) to encrypt data in transit. To enforce it, use a bucket policy withaws:SecureTransport: false → Deny. This denies any unencrypted HTTP request to the bucket.
A Presigned URL is a URL that includes temporary signed credentials. It lets any user (without an AWS account) access a private S3 object for a limited time.
How it works
Your application generates a Presigned URL with the AWS SDK
The URL includes: bucket, object, action, expiration and cryptographic signature
The user accesses the object in S3 directly using that URL
S3 verifies the signature and the expiration time
Once expired → access is automatically denied
Exam use cases
Exam trap
The Presigned URL inherits the permissions of the user/role that generated it. If the role no longer has access to the object when the URL is used, access is denied.
S3 Versioning
Keeps multiple versions of an object. Enable it before Object Lock. A "deleted" object actually receives a Delete Marker — previous versions still exist.
S3 Object Lock (WORM)
Write Once Read Many — nobody can modify or delete objects during the retention period. For regulatory compliance (HIPAA, SEC, FINRA).
Governance Mode
Admins with special permissions can override the retention. For internal use.
Compliance Mode
NOBODY can delete the object during retention, not even the account root. For strict regulations.
The most secure pattern for serving content from S3 is keeping the bucket fully private and using CloudFront as the only access point with Origin Access Control (OAC).
Request flow
Bucket policy configuration
Only CloudFront (service principal) can do GetObject:
"Principal": {
"Service": "cloudfront.amazonaws.com"
},
"Condition": {
"StringEquals": {
"AWS:SourceArn": "arn:aws:cloudfront::ACCOUNT:distribution/ID"
}
}OAC vs OAI (legacy)
OAC (recommended)
Supports SSE-KMS, additional HTTP methods, all regions
OAI (legacy)
Only SSE-S3, GET/HEAD. Migrate to OAC.
Did you get this topic?
Test what you just learned
A company stores financial records in S3 that must be retained for exactly 7 years with no possibility of deletion by anyone, not even the account administrator. Which S3 configuration meets this requirement?
Put what you learned to the test with original SAA-C03 exam questions.
Start SAA-C03 mock examUnlimited mock exams with the Pro plan
Log in to track your progress.