Course outline

10.9

MFA Delete, Logs, Pre-signed URLs, Object Lock and Access Points

Protecting versions, access logs (and the logging loop), temporary links, WORM storage, access points and Object Lambda.

28 min Reading + animations

Tip: tap or hover any dotted-underlined term to see what it means.

By the end of this lesson you will be able to

  • Explain what MFA Delete protects, who can turn it on and how, and what it does not stop.
  • Set up server access logging correctly, avoid the logging loop, and choose between access logs and CloudTrail.
  • Create pre-signed URLs, predict when they really expire, and explain whose permissions they use.
  • Tell Glacier Vault Lock, Object Lock governance mode, compliance mode and legal hold apart, and predict who can delete what, and when.
  • Use access points to split one bucket’s security per team, restrict an access point to a VPC, and serve a multi-Region dataset through a Multi-Region Access Point.
  • Describe S3 Object Lambda, its 2025 availability change, and the replacements AWS recommends.
  • Map every exam keyword in this area to the right feature.

#Six extra locks for a bucket

The earlier lessons gave a bucket its basic protection: IAM and bucket policies decide who may do what (lesson 10.2), versioning keeps old copies (lesson 10.4) and encryption hides the bytes (lesson 10.8). This lesson adds the tools you reach for when “a policy” is not enough:

FeatureProtects againstExam keyword
MFA DeleteStolen keys or a careless admin permanently deleting versions“extra protection against accidental deletion”, “who can enable it?” → root
Server access logsNot knowing who touched the data“audit every request to the bucket”
Pre-signed URLsMaking a bucket public just to share one file“temporary access without AWS credentials”
Glacier Vault Lock / S3 Object LockAnyone, even an admin or root, changing or deleting records“WORM”, “SEC / FINRA”, “even root cannot delete”
Access points (incl. VPC and Multi-Region)One huge, fragile bucket policy shared by many teams; internet exposure; one Region“bucket policy too complex”, “only from the VPC”, “one global endpoint”
S3 Object LambdaKeeping several altered copies of the same data“redact PII on the fly without a second copy”

#MFA Delete

#What needs the code, and what does not

MFA Delete is an extra switch on a versioned bucket. When it is on, two operations need an MFA code sent with the request, on top of normal credentials:

  • permanently deleting an object version (a delete that names a version ID);
  • changing the versioning state of the bucket (suspending versioning, or turning MFA Delete off).

Everything else works as before. You do not need a code to enable versioning, to upload, to read, to list versions (including deleted ones), or to make a simple delete without a version ID, which only adds a delete marker and destroys nothing.

The code travels in the x-amz-mfa request header: the device’s serial number (for a virtual device, its ARN), a space, and the 6-digit code. Requests that carry it must use HTTPS.

#Who can turn it on, and how

  • Only the root user of the bucket owner’s account can enable or disable MFA Delete, using the root user’s MFA device. An IAM user or role, even with AdministratorAccess, can enable versioning but not MFA Delete.
  • Not from the console. You use the AWS CLI, an SDK or the REST API, with the same call that sets versioning (put-bucket-versioning). MFA Delete is stored in the bucket’s versioning configuration.
  • Versioning must be enabled (you can enable both in the same call).
  • After that, permanent deletes need the bucket owner’s (root) MFA, so in practice only the root user, with its device in hand, can permanently delete versions.

Lesson 2.3 listed MFA Delete among the root-only tasks; here is the full story. Because root should have no access keys, the usual way is to sign in as root, open a shell in the browser console, run the one command, and sign out.

MFA Delete on a versioned bucket

A payroll bucket keeps every version of every payslip. MFA Delete adds one more lock: a permanent delete or a versioning change must carry a code from the root user’s MFA device.

Scenario

Only the root user can enable it, and only from the CLI or API.

Root userowns the MFA
IAM adminfull access
Attackerstolen keys
payslips-exampleversioned
reads the 6-digit code
Step 1 of 5
1

The S3 console has no MFA Delete switch. The root user runs the versioning command from the CLI (for example in a shell opened while signed in as root) and adds the MFA device’s serial number and the current code.

#What MFA Delete does not do

  • It does not stop simple deletes (delete markers). Data is safe, but the application sees “file gone” until someone restores it.
  • It does not stop overwrites: a new upload becomes a new version; the old one stays.
  • It cannot be used with lifecycle configurations. A lifecycle rule cannot type an MFA code, so you choose between automatic expiry of old versions and MFA Delete.
  • It depends on one person and one device. For large-scale, rule-based protection (keep everything 7 years, then expire it), Object Lock is the modern answer, later in this lesson.

#Server access logs

#What a log record contains

Server access logging writes a line for each request made to a bucket: the bucket owner, bucket, time, remote IP, requester (IAM identity or anonymous), request ID, operation (REST.GET.OBJECT, REST.PUT.OBJECT…), key, HTTP status, error code, bytes sent, total time and more. Requests from any account, allowed or denied, are logged. You use the logs for security reviews (who keeps getting 403?), usage analysis (which photos are popular?) and charging teams for what they use.

#Setting it up: the target bucket rules

Logs are delivered as text files into a target bucket that you choose, under an optional prefix such as logs/shop-images/. The rules for the target:

  • It must be in the same Region and the same account as the source bucket.
  • It should not be the source bucket (see the loop below).
  • It must not have an Object Lock default retention period.
  • Its default encryption must be SSE-S3; SSE-KMS is not supported for log delivery.
  • Its bucket policy must allow the logging service principal logging.s3.amazonaws.com to write (the console adds this; ACL-based grants are the old way).

Delivery is best effort: most records arrive within a few hours, but a record can arrive late, be duplicated, or very rarely be missing. Turning logging on or changing the target also takes time to take effect. Delivery itself is free; you pay to store the files, so add a lifecycle rule on the log bucket to expire old logs (lesson 10.5). To analyse them, query them in place with Athena (chapter 17).

#The logging loop

If the target is the same bucket you are logging, every log file written is itself a request to that bucket, which creates a new log record, which is delivered as another log file, which is logged again. The bucket keeps growing on its own, even at night with no visitors, and the useful lines drown in noise. AWS’s warning is blunt: never set the monitored bucket as its own log target.

Server access logs and the logging loop

A Dhaka e-commerce shop keeps product photos in shop-images-example. Server access logging writes a record of every request, allowed or denied, as files in a target bucket.

Scenario

Source and target are different buckets in the same Region and account.

Shoppers
Scanner bot
shop-imagessource
Log delivery
shop-logstarget
Athena
GET /p/42.jpg
Step 1 of 4
1

Shoppers download photos. Each GET is served normally; S3 also notes who asked, from which IP, for which key, the result code and the bytes sent.

#Access logs or CloudTrail?

Server access logsCloudTrail data events for S3
WhatEvery request to the bucket, in text linesObject-level API calls as JSON events with the full IAM identity
DeliveryBest effort, usually within hoursReliable, usually within minutes
CostFree delivery, pay for storagePaid per event
Typical useTraffic analysis, billing per customer, cheap broad auditSecurity investigations, compliance evidence, triggering alerts

For a compliance audit that must not miss an event, use CloudTrail data events (chapter 19); for cheap, broad traffic logs, server access logs.

Self-checkQuestion

A team turns on server access logging for shop-images and sets the target to shop-images itself. A week later the bucket has millions of small log objects even though traffic is low. What is the right fix?

#Pre-signed URLs

#How a pre-signed URL works

A pre-signed URL lets someone without AWS credentials perform one specific operation on one specific object for a limited time: download (GET), upload (PUT) or read metadata (HEAD). Someone who has permission creates it by signing the request in advance with their own credentials (Signature Version 4). The signature, the access key ID, the time and the expiry ride in the URL’s query string.

  • Signing happens locally, in the SDK or CLI. S3 is not contacted, so creating a URL never fails because of permissions.
  • When the URL is used, S3 checks the signature and the expiry, then evaluates the request as if the signer made it. The URL can never do more than its creator may do.
  • The URL can be used many times until it expires: it is a bearer token. Whoever holds it can use it.
  • Changing anything that was signed (method, key, signed headers) breaks the signature: a PUT URL for uploads/u7/avatar.png cannot write to admin/config.json.

You create one from the S3 console (Object actions → Share with a pre-signed URL), the AWS CLI (aws s3 presign, for downloads), or any SDK (needed for upload URLs).

#How long it lives

Created withExpiry you can set
S3 console1 minute to 12 hours (720 minutes)
AWS CLI aws s3 presign--expires-in in seconds; default 3,600 (1 hour), maximum 604,800 (7 days)
SDKsup to 7 days with SigV4

The credentials that sign it set a second limit, and the URL dies at whichever comes first:

Signing credentialsThe URL works at most…
IAM user (long-term access key)up to 7 days
IAM role session (assumed role, STS)until the session expires (1 hour by default for an assumed role)
EC2 instance profile roleuntil those role credentials rotate (typically about 6 hours)
Any credentials that are revoked, deleted or deactivatedstops working at once

S3 checks the expiry when a request starts: a 2 GB download that began one second before the expiry finishes, but a resume after the expiry fails.

#Who the URL acts as

The URL carries the signer’s identity. If the signing role is allowed to read videos/*, so is anyone holding the link, for that one object. If the role is not allowed (or a bucket policy denies it), the link returns 403 Access Denied even though it looked valid. The same is true when the bucket policy restricts by network: a URL used from outside an allowed IP range or VPC endpoint is refused.

Pre-signed URLs: who the link acts as

A streaming site keeps premium videos in a private bucket. The app, running on EC2 with an IAM role, signs short-lived links for logged-in subscribers.

Scenario

Subscriber
Video appIAM role
videos-exampleprivate
Someone else
GET /watch/42
Step 1 of 6
1

The subscriber is logged in to the website, not to AWS. She has no AWS credentials at all.

#Keeping pre-signed URLs safe

  • Keep expiries short (minutes for downloads) and create URLs on demand, after your app has checked who the user is.
  • Sign with a dedicated role that can reach only the prefixes it must share.
  • Add bucket policy conditions where it makes sense: aws:SourceIp or aws:SourceVpce for network limits, s3:signatureAge to refuse signatures older than, say, 10 minutes, s3:authType to forbid query-string authentication entirely on sensitive buckets.
  • Remember that revoking the signer’s credentials kills every link they signed: useful in an incident.

Pre-signed URLs are also one of the 13 ways data moves into S3; the upload side (browser uploads, multipart with pre-signed parts) is taught in lesson 10.12. For links in front of a CDN, CloudFront has its own signed URLs (chapter 11).

#WORM storage: Vault Lock and Object Lock

Some records must be stored write once, read many (WORM): once written, nobody may change or delete them for a set time. Broker-dealers in the US must keep trade records this way (SEC Rule 17a-4, FINRA rules), and many banks, hospitals and regulators elsewhere have similar retention rules. AWS offers two WORM tools.

#Glacier Vault Lock

Glacier Vault Lock works on a whole vault in the original Amazon S3 Glacier service (the vault-based API, not the S3 storage classes). You write a Vault Lock policy in IAM policy language (for example “deny deleting archives younger than 2,555 days”) and lock it so it can never change.

  1. Initiate the lock: the policy is attached, the lock enters an in-progress state and you get a lock ID. The policy is already enforced, so you can test it.
  2. Within 24 hours, complete the lock with the lock ID. From then on the policy can never be changed or deleted, by anyone.
  3. If testing shows a mistake, abort and start again. If you do nothing, the lock ID expires after 24 hours and the policy is removed: the vault is not locked automatically.

A vault can also have a normal vault access policy for everyday, changeable permissions; only the Vault Lock policy is frozen.

Glacier Vault Lock: 24 hours to test, then forever

A brokerage must keep trade records unchanged for 7 years. Vault Lock attaches a policy to a whole Glacier vault and then freezes that policy.

Scenario

Compliance admin
trades-vaultGlacier vaultin progress, 24 h
Archiver app
initiate lock: deny delete if age < 2,555 days
Step 1 of 4
1

Step 1 attaches the Vault Lock policy (IAM policy language) and puts the lock in an in-progress state. S3 Glacier returns a lock ID.

#S3 Object Lock

S3 Object Lock brings WORM to normal buckets, per object version:

  • Versioning is required. Once Object Lock is enabled, it cannot be disabled, and versioning cannot be suspended.
  • You can enable it on a new bucket or, since late 2023, on an existing bucket (console, CLI or API).
  • Each object version can carry a retention period (with a mode and a retain-until date), a legal hold, or both.
  • A default retention (mode plus days or years) can be set on the bucket, so every new version is locked automatically; an explicit setting on an upload overrides the default.

Object Lock protects versions, not names. A simple delete still adds a delete marker (the old version stays locked underneath), and uploading the same key creates a new version; the locked one is untouched.

#Retention modes: governance and compliance

Governance modeCompliance mode
Delete or overwrite the version before the dateOnly principals with s3:BypassGovernanceRetention who also send the header x-amz-bypass-governance-retention: true (the console sends it for you)Nobody, not even the root user
Shorten the period or remove the lockSame special permission and headerNever
Extend the periodAnyone with s3:PutObjectRetentionAnyone with s3:PutObjectRetention
Change the modeWith the special permissionNever
Typical useProtect against mistakes and most users, keep an emergency exit; test settings before complianceRegulatory WORM: SEC 17a-4, FINRA, bank and health records

The only way to remove a compliance-mode version before its date is to close the whole AWS account. That is why you test with governance first.

Governance modeCompliance mode

A bank’s strong room with a time lock that the branch manager’s special key can override. Ordinary staff cannot open it; the manager can, and the override is logged.

A time-lock safe whose timer nobody can override, not the manager, not the bank’s owner. It opens on the date set, and not a minute earlier.

A legal hold is an on/off flag on an object version with no end date. While it is on, the version cannot be deleted or overwritten, whatever the retention says.

  • It is independent of retention: a version can have a hold and no retention, retention and no hold, or both. If retention expires while the hold is on, the version stays protected; if the hold is removed while retention is active, retention still protects it.
  • Anyone with s3:PutObjectLegalHold can place or remove it freely; no special mode is needed.
  • Use it when you do not know how long: a lawsuit, an investigation, an audit in progress.

#Try the locks yourself

Set a mode, a legal hold and the clock, choose an action, then see what an app user, a compliance officer and the root user each get.

Object Lock simulator

A bank keeps statement stmt-0412.pdf (version v1) with a retain-until date of 31 Dec 2033. Set the lock, move the clock, pick an action, then let three people try it.

Retention mode on v1

Most users cannot delete or overwrite this version or loosen its lock. Principals with s3:BypassGovernanceRetention can, if they send the bypass header.

Legal hold on v1

Clock

Action

DELETE stmt-0412.pdf?versionId=v1

Press “Try it as all three” to see what S3 answers each of them.

Self-checkQuestion

An object version is in governance mode until 2030. A user with s3:BypassGovernanceRetention runs a CLI delete with the version ID but without the bypass header. What happens?

#S3 Access Points

#One bucket, many doors

A shared data-lake bucket used by finance, sales, analytics and a dozen applications ends up with one enormous bucket policy. Every change risks breaking another team, and a bucket policy is limited to 20 KB. Access points fix this:

  • An access point is a named network endpoint attached to one bucket, with its own hostname, its own ARN and its own access point policy (same language as a bucket policy, also up to 20 KB).
  • Each team or application gets its own access point, with a short policy: finance can read and write finance/*, analytics can read everything, a partner can read exports/*.
  • Each access point has its own Block Public Access settings and a network origin: Internet or VPC.
  • An access point is used for object operations (GET, PUT, list…), not for bucket management such as creating replication rules.
  • Up to 10,000 access points per account per Region (a soft quota). Each access point is tied to one bucket forever; its network origin and Block Public Access settings cannot be changed after creation.

#Access point policies and delegating from the bucket

A request through an access point must be allowed by both the access point policy and the bucket policy (plus the caller’s IAM policy, as always, lesson 2.2). Rather than repeating every grant in the bucket policy, AWS recommends delegating access control to the access points with one statement:

{
  "Effect": "Allow",
  "Principal": { "AWS": "*" },
  "Action": "*",
  "Resource": ["arn:aws:s3:::company-data-example", "arn:aws:s3:::company-data-example/*"],
  "Condition": { "StringEquals": { "s3:DataAccessPointAccount": "111122223333" } }
}

This means “allow anything that comes through an access point owned by account 111122223333”; the access point policies then decide. Two traps:

  • Access points do not change the bucket’s own behaviour. Someone whose IAM policy allows S3 can still call the bucket directly. To force everyone through the doors, add an explicit Deny for requests that do not come through an access point.
  • An access point can narrow access, never widen it beyond what the bucket allows.

Access points: one bucket, a door per team

company-data-example holds finance/ and sales/ data. Instead of one huge bucket policy, each team gets its own access point with its own short policy.

Scenario

Finance team
Analytics team
finance-ap
analytics-ap
Bucketcompany-data
GET finance/q3.xlsx

Policies in play

finance-ap policyanalytics-ap policyBucket policy
Finance: read/write finance/*Analytics: read alldelegates to own access points
Step 1 of 3
1

Finance reads finance/q3.xlsx through finance-ap. Each access point has its own DNS name and its own policy; the bucket policy just delegates to the account’s access points.

#VPC-only access points

An access point with network origin VPC accepts requests only from one specified VPC. Requests from the internet are refused, whatever credentials they carry.

  • Traffic from the VPC reaches it through a VPC endpoint for S3: a gateway endpoint or an interface endpoint both work (how they work, and every other private path to S3, is lesson 10.10; the full endpoint lesson is 22.2).
  • Three policies must all allow the request: the endpoint policy (it must allow the access point’s ARN as well as the bucket), the access point policy and the bucket policy.
  • To keep the whole bucket off the internet, add a bucket policy that denies object access unless s3:AccessPointNetworkOrigin is VPC; an organization-wide SCP can forbid creating internet-origin access points at all (chapter 20).

A VPC-only access point

A hospital’s report job runs in a private subnet. Its access point has network origin VPC, so it accepts requests only from that VPC, through a VPC endpoint.

Scenario

VPC10.0.0.0/16
Report job
S3 endpoint
scans-vpc-ap
Bucketscans
Home laptop
GET scan-881.dcm

Three policies must all allow

Endpoint policyAccess point policyBucket policy
allowsallowsallows
Step 1 of 3
1

The job asks for a scan through the access point’s name. The route table sends S3 traffic to the endpoint (a gateway or an interface endpoint, both work).

#Multi-Region Access Points

A Multi-Region Access Point (MRAP) gives one global endpoint in front of buckets in several Regions:

  • Requests enter the AWS network at the nearest edge (MRAP runs on AWS Global Accelerator, chapter 11) and go to the closest bucket with an active routing status: lower latency and fewer internet hops.
  • MRAP does not copy data. You set up Cross-Region Replication between the buckets yourself (lesson 10.4), usually in both directions. A read right after a write in another Region can miss until replication catches up.
  • Failover controls let you run active-active or active-passive and shift traffic away from a troubled Region within minutes; you can also use them for disaster-recovery drills.
  • Limits: up to 17 Regions per MRAP and 100 MRAPs per account; the set of buckets is fixed when you create it; requests are signed with SigV4A (the SDKs do this for you); from a VPC you reach it through an interface endpoint (not a gateway endpoint).

Multi-Region Access Point

A news site stores photos in Singapore and N. Virginia and replicates them both ways. One global MRAP name serves each reader from the nearest healthy bucket.

Scenario

ap-southeast-1
us-east-1
photos-sg
photos-us
Reader, Dhaka
MRAPglobal endpoint
Reader, New York
GET /2026/flood.jpgGET /2026/flood.jpg
Step 1 of 2
1

Both readers use the same hostname. Requests enter the AWS network at the nearest edge (MRAP is built on Global Accelerator, chapter 11) instead of crossing the public internet.

#S3 Object Lambda

S3 Object Lambda puts your own Lambda function in the path of GET requests (also HEAD and list requests), so each caller can receive a changed version of the object while the stored object stays the same.

  • You create a supporting access point on the bucket and, on top of it, an Object Lambda access point that names the function.
  • A caller sends an ordinary GET to the Object Lambda access point. S3 invokes the function with a pre-signed link to the original; the function reads it, transforms it, and returns the result, which S3 sends to the caller.
  • One bucket and one copy of the data serve different views: analysts get a redacted version, admins read the original through the normal access point.

Typical uses:

  • Redacting PII (national ID numbers such as an NID or a US SSN, phone numbers, account numbers) for analytics or non-production environments.
  • Converting formats, such as XML to JSON for an application that expects JSON.
  • Resizing and watermarking images on the fly, using details of the caller (for example, a watermark with the user’s name).

S3 Object Lambda: change the data on the way out

A telecom stores customer records with NID numbers. Analysts must see them masked, support admins in full, and nobody wants two copies.

Scenario

Support admin
Analytics app
Object Lambdaaccess point
redact-nid
Supportingaccess point
customers-example
GET customers/2026-10.json
Step 1 of 6
1

The analytics app sends an ordinary GET, but to the Object Lambda access point instead of the bucket.

#Choosing the right control

The question says…Answer
Extra protection against permanent deletion of versions; who can enable?MFA Delete; root only, CLI/API only, versioning required
Audit every request to a bucket, including denied ones, cheaplyServer access logs to a separate bucket (same Region and account)
Complete record of who called which object API, for security investigationsCloudTrail data events
Temporary download or upload for someone without AWS credentialsPre-signed URL
WORM on a Glacier vault, policy locked foreverGlacier Vault Lock (initiate, test 24 h, complete)
WORM on S3 objects, nobody including root can deleteObject Lock, compliance mode
WORM, but special admins can remove itObject Lock, governance mode
Hold data with no end date (lawsuit)Legal hold
Bucket policy too complex for many teamsAccess points
Only reachable from a VPCVPC-origin access point + VPC endpoint
One global endpoint across Regions, nearest Region, failoverMulti-Region Access Point
Same data, different views (redact, convert, resize), no copiesS3 Object Lambda (new accounts: Lambda behind a function URL or CloudFront)

#Advanced S3 security in system design

  • Layer the protections. A bank’s statement bucket: Block Public Access on, versioning on, default encryption, Object Lock compliance mode with a 7-year default retention, CloudTrail data events for evidence, access logs to a separate log bucket, and one access point per application.
  • Prefer Object Lock over MFA Delete for ransomware defence. Backups written with a compliance-mode retention survive even a stolen root password. Keep MFA Delete for small, hand-managed buckets.
  • Log centrally, but deliver locally. Classic access logs go to a log bucket in the same Region and account; replicate or ship them (or use the newer CloudWatch Logs delivery) to a central security account.
  • Never make a bucket public to share files. Use short-lived pre-signed URLs from an app that has checked the user, or CloudFront with signed URLs for large audiences.
  • Give every application its own door. Access points with narrow policies and a delegating bucket policy, plus an explicit deny for direct access; VPC-origin access points for internal data such as hospital scans.
  • Go multi-Region deliberately. MRAP plus two-way replication for global, latency-sensitive reads and Region failover; remember that replication is asynchronous.

#Try it yourself

The commands use made-up bucket names and account 111122223333. Some need the root user (MFA Delete) or settings that cannot be undone (compliance mode): try them in a sandbox account.

# 1. MFA Delete (run as the root user, for example from a console shell while signed in as root)
aws s3api put-bucket-versioning --bucket payslips-example \
  --versioning-configuration Status=Enabled,MFADelete=Enabled \
  --mfa "arn:aws:iam::111122223333:mfa/root-account-mfa-device 123456"
aws s3api get-bucket-versioning --bucket payslips-example        # Status + MFADelete
# A permanent delete must now carry the code:
aws s3api delete-object --bucket payslips-example --key 2026/oct.pdf \
  --version-id <version-id> --mfa "arn:aws:iam::111122223333:mfa/root-account-mfa-device 654321"

# 2. Server access logs into a separate bucket in the same Region
cat > logging.json <<'EOF'
{ "LoggingEnabled": { "TargetBucket": "shop-logs-example", "TargetPrefix": "shop-images/" } }
EOF
aws s3api put-bucket-logging --bucket shop-images-example --bucket-logging-status file://logging.json
aws s3api get-bucket-logging --bucket shop-images-example

# 3. Pre-signed URL: default 1 hour, here 15 minutes
aws s3 presign s3://videos-example/premium/42.mp4 --expires-in 900
curl -s -o /dev/null -w "%{http_code}\n" "<paste the URL>"      # 200 now, 403 after 15 minutes

# 4. Object Lock on a new bucket, governance by default for 30 days
aws s3api create-bucket --bucket statements-example --object-lock-enabled-for-bucket
aws s3api put-object-lock-configuration --bucket statements-example \
  --object-lock-configuration '{"ObjectLockEnabled":"Enabled","Rule":{"DefaultRetention":{"Mode":"GOVERNANCE","Days":30}}}'
aws s3api put-object --bucket statements-example --key stmt-0412.pdf --body stmt-0412.pdf
aws s3api get-object-retention --bucket statements-example --key stmt-0412.pdf
aws s3api put-object-legal-hold --bucket statements-example --key stmt-0412.pdf --legal-hold Status=ON
# Delete a governance-locked version (needs s3:BypassGovernanceRetention):
aws s3api delete-object --bucket statements-example --key stmt-0412.pdf \
  --version-id <version-id> --bypass-governance-retention

# 5. Access points: one internet-origin, one VPC-only
aws s3control create-access-point --account-id 111122223333 --name finance-ap \
  --bucket company-data-example
aws s3control create-access-point --account-id 111122223333 --name scans-vpc-ap \
  --bucket scans-example --vpc-configuration VpcId=vpc-0abc1234example
aws s3api get-object --bucket arn:aws:s3:ap-south-1:111122223333:accesspoint/finance-ap \
  --key finance/q3.xlsx q3.xlsx

# 6. Glacier Vault Lock (existing vault customers only)
aws glacier initiate-vault-lock --account-id - --vault-name trades-vault --policy file://lock.json
aws glacier complete-vault-lock --account-id - --vault-name trades-vault --lock-id <lock-id>

Look at a delivered log line with aws s3 cp s3://shop-logs-example/shop-images/<file> - and find the requester, the operation and the HTTP status. Then try deleting the locked version without --bypass-governance-retention and read the 403.

#Summary

Key takeaways

  • MFA Delete: needs an MFA code to permanently delete a version or change versioning; not for enabling versioning, listing versions or simple deletes. Versioning required, root user only, CLI/API only, not with lifecycle rules.
  • Server access logs: every request, allowed or denied, as text files in a target bucket in the same Region and account; best effort, hours late; target SSE-S3, no Object Lock default retention. Never log a bucket into itself (logging loop). CloudTrail data events for complete, identity-rich audit. New (June 2026): delivery to CloudWatch Logs.
  • Pre-signed URL: temporary GET/PUT for one object without AWS credentials; acts with the signer’s permissions; console 1 min–12 h, CLI default 1 h, max 7 days; dies early when the signing credentials expire or are revoked; bearer token, so keep it short.
  • Glacier Vault Lock: Vault Lock policy on a whole vault; initiate → test → complete within 24 h, or it expires; once locked, never changeable. Vault service closed to new customers since December 2025.
  • Object Lock: WORM per object version; versioning required, cannot be turned off; works on existing buckets; default retention per bucket.
  • Governance: special users with s3:BypassGovernanceRetention + header can delete or shorten. Compliance: nobody, root included; period can be extended, never shortened.
  • Legal hold: no end date, independent of retention, on/off with s3:PutObjectLegalHold. New (September 2026): event holds for variable retention.
  • Access points: one endpoint and policy per team; both access point and bucket policy must allow (delegate with s3:DataAccessPointAccount); network origin Internet or VPC, fixed at creation; 10,000 per account per Region.
  • VPC access point: only from one VPC through a gateway or interface endpoint; endpoint, access point and bucket policies must all allow.
  • MRAP: one global endpoint on Global Accelerator, nearest active bucket, failover controls; you configure replication; up to 17 Regions; SigV4A.
  • S3 Object Lambda: Lambda transforms GET results (redact PII, XML → JSON, resize/watermark) via an Object Lambda access point on a supporting access point; closed to new customers since November 2025.