
Securing S3 Buckets
- 3.2k installs
- 2.2k repo stars
- Updated August 4, 2026
- aws/agent-toolkit-for-aws
securing-s3-buckets is an agent skill for
About
The securing-s3-buckets skill documents agent workflows from the repository SKILL.md. It covers you MUST inform the user if required tools are missing. Key workflows include you SHOULD confirm credentials with aws sts get-caller-identity. Implements layered S3 security controls across five workflows: securing new buckets, auditing existing configurations, remediating findings, configuring encryption, and enabling monitoring. Follows AWS Well-Architected security best practices. Execute commands using the AWS MCP server when connected sandboxed execution, audit logging, observability . Fall back to AWS CLI or shell otherwise. Developers invoke securing-s3-buckets when the task matches the triggers and reference files in SKILL.md for grounded, stepwise execution. Reference files and progressive disclosure keep context focused while preserving concrete commands, configuration fields, and validation checks copied from the upstream documentation. Reference files and progressive disclosure keep context focused while preserving concrete commands, configuration fields, and validation checks copied from the upstream documentation.
- You MUST inform the user if required tools are missing
- You SHOULD confirm credentials with aws sts get-caller-identity
- You MUST ask for all required parameters upfront
- You MUST confirm bucket name and region before any write operation
- You MAY infer region from user context if clearly stated
Securing S3 Buckets by the numbers
- 3,156 all-time installs (skills.sh)
- +389 installs in the week ending Aug 5, 2026 (Skillselion tracking)
- Ranked #183 of 2,203 Security skills by installs in the Skillselion catalog
- Security screen: LOW risk (skills.sh audit)
- Data as of Aug 5, 2026 (Skillselion catalog sync)
securing-s3-buckets capabilities & compatibility
- Capabilities
- you must inform the user if required tools are m · you should confirm credentials with aws sts get · you must ask for all required parameters upfront · you must confirm bucket name and region before a · you may infer region from user context if clearl
- Use cases
- security audit · testing · debugging
What securing-s3-buckets says it does
Create and secure S3 buckets following AWS best practices for access control, encryption,
monitoring, and remediation of misconfigurations. Use when the user wants to
npx skills add https://github.com/aws/agent-toolkit-for-aws --skill securing-s3-bucketsAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 3.2k |
|---|---|
| repo stars | ★ 2.2k |
| Security audit | 3 / 3 scanners passed |
| Last updated | August 4, 2026 |
| Repository | aws/agent-toolkit-for-aws ↗ |
What problem does securing-s3-buckets solve for developers using the documented workflows?
The securing-s3-buckets skill documents agent workflows from the repository SKILL.md. It covers you MUST inform the user if required tools are missing. Key workflows include you SHOULD confirm creden
Who is it for?
Developers working with securing-s3-buckets patterns described in the skill documentation.
Skip if: Skip when docs are empty or the task is outside the skill documented scope.
When should I use this skill?
Use when
What you get
Actionable securing-s3-buckets guidance grounded in SKILL.md workflows and reference files.
- Hardened bucket policy
- Encryption configuration
- Logging and monitoring setup
By the numbers
- Implements five layered S3 security workflows
- Follows AWS Well-Architected security guidance
Files
Overview
Implements layered S3 security controls across five workflows: securing new buckets, auditing existing configurations, remediating findings, configuring encryption, and enabling monitoring. Follows AWS Well-Architected security best practices.
Execute commands using the AWS MCP server when connected (sandboxed execution, audit logging, observability). Fall back to AWS CLI or shell otherwise.
Common Tasks
0. Verify Dependencies
Check for required tools before starting.
Constraints:
- You MUST inform the user if required tools are missing
- You SHOULD confirm credentials with
aws sts get-caller-identity
See references/iam-permissions.md for IAM permissions by workflow.
1. Classify the Request
| User intent | Workflow |
|---|---|
| Secure a new bucket | A: Secure New Bucket |
| Audit / review existing bucket | B: Audit Existing Bucket |
| Fix a specific finding | C: Remediate Issue |
| Configure encryption | D: Configure Encryption |
| Enable logging / monitoring | E: Enable Monitoring |
Constraints:
- You MUST ask for all required parameters upfront
- You MUST confirm bucket name and region before any write operation
- You MAY infer region from user context if clearly stated
- You SHOULD run
aws iam simulate-principal-policyto validate permissions before write operations - You SHOULD display write commands and wait for confirmation before executing
put-bucket-policy Safety Rules
These rules apply to ALL workflows that call put-bucket-policy:
- You MUST attempt to retrieve the existing policy first (
aws s3api get-bucket-policy) —put-bucket-policyreplaces the entire policy - If a policy exists, you MUST back it up before modifying:
aws s3api get-bucket-policy --bucket <name> --output text > backup-policy-$(date +%s).json - If
NoSuchBucketPolicyis returned, proceed with a new policy — no backup is needed - You MUST merge new statements into the existing policy's Statement array (if one exists)
- You MUST validate merged JSON syntax before applying (e.g.
echo '<policy>' | python3 -m json.tool) - You SHOULD display the full
put-bucket-policycommand and wait for confirmation
2. Workflow A — Secure New Bucket
See references/workflows.md for full CLI steps.
Required steps (execute in order, do not skip):
1. Create bucket with --bucket-namespace account-regional 2. Enable versioning 3. Enable encryption (SSE-S3 + Bucket Keys + block SSE-C) 4. Enable logging (ask user which option — conditional) 5. Enforce HTTPS-only via DenyInsecureTransport bucket policy 6. Enable ABAC
Constraints:
- You MUST pass
--bucket-namespace account-regionaloncreate-bucketcall — this is REQUIRED, not optional. Example:
aws s3api create-bucket --bucket <name> --bucket-namespace account-regional --region <region>- You MUST NOT change Block Public Access — S3 enables it by default on new buckets
- You MUST NOT change ACL ownership controls — S3 disables ACLs (
BucketOwnerEnforced) by default - You MUST apply a bucket policy with a
DenyInsecureTransportstatement that deniess3:*whenaws:SecureTransportisfalse— this is REQUIRED, not optional. Example:
aws s3api put-bucket-policy --bucket <name> --policy '{"Version":"2012-10-17","Statement":[{"Sid":"DenyInsecureTransport","Effect":"Deny","Principal":"*","Action":"s3:*","Resource":["arn:aws:s3:::<name>/*","arn:aws:s3:::<name>"],"Condition":{"Bool":{"aws:SecureTransport":"false"}}}]}'- You MUST ask the user which logging option they want before step 4
- You MUST follow the put-bucket-policy safety rules for steps 4 and 5
- You SHOULD confirm each step succeeded before proceeding
3. Workflow B — Audit Existing Bucket
See references/audit-checklist.md for the full checklist.
Constraints:
- You MUST run all read-only audit commands before reporting findings
- You MUST NOT execute any write or modify commands during an audit
- You MUST report each control as PASS / FAIL / NOT CONFIGURED with severity
- For logging: report PASS if either S3 server access logging OR CloudTrail data events are enabled; NOT CONFIGURED only if neither
4. Workflow C — Remediate Issue
See references/remediation.md for fix commands by issue type.
Constraints:
- You MUST identify the issue type before applying any fix
- You MUST follow the put-bucket-policy safety rules when modifying policies
- You MUST re-run the relevant audit check after applying the fix to confirm resolution
5. Workflow D — Configure Encryption
See references/encryption.md for encryption options and commands.
Constraints:
- You MUST default to SSE-S3 with S3 Bucket Keys and SSE-C blocked unless the user explicitly requests KMS
- When using SSE-KMS, you MUST use a customer managed key — NEVER the AWS managed
aws/s3key - You MUST specify customer-managed KMS keys by full ARN, not alias
- You MUST include
BucketKeyEnabled: trueandBlockedEncryptionTypes: [SSE-C]in all configurations - Note: The S3 API accepts
aws/s3and aliases without error — agent-enforced constraints. Verify withget-bucket-encryptionafter applying.
6. Workflow E — Enable Monitoring
See references/workflows.md for full CLI steps.
Constraints:
- You MUST check whether a GuardDuty detector already exists before creating one
- You MUST use the trail's home region (not the bucket's region) for CloudTrail commands
- You SHOULD enable all four core recommended AWS Config rules
Troubleshooting
`ObjectLockConfigurationNotFoundError` — Object Lock is not enabled. Treat as NOT CONFIGURED, not a failure.
`AccessDenied` on audit commands — Check IAM policy, bucket policy, Block Public Access, VPC endpoint policy, and SCPs/RCPs. Use aws iam simulate-principal-policy to diagnose.
`put-bucket-policy` silently removes existing statements — See put-bucket-policy safety rules.
GuardDuty `BadRequestException: detector already exists` — Run aws guardduty list-detectors first; only call create-detector if empty.
CloudTrail changes not taking effect — Verify you are using --region <trail-home-region>, not the bucket's region. Find it with aws cloudtrail describe-trails --query 'trailList[*].[Name,HomeRegion]'.
Additional Resources
- references/iam-permissions.md — IAM permissions by workflow
- references/audit-checklist.md — Per-control checklist with severity and pass conditions
- references/encryption.md — Encryption options, KMS guidance, SSE-C blocking
- references/remediation.md — Fix commands for common findings
- references/workflows.md — Full CLI command sequences for Workflows A and E
- AWS S3 Security Best Practices
- AWS Well-Architected Security Pillar
S3 Security Audit Checklist
Critical (fix immediately)
| Control | Check command | Pass condition |
|---|---|---|
| Block Public Access | get-public-access-block | All 4 flags true |
| No public bucket policy | get-bucket-policy | No "Principal": "*" or "Principal": {"AWS": "*"} with Allow |
| HTTPS enforced | get-bucket-policy | DenyInsecureTransport statement present |
| ACLs disabled | get-bucket-ownership-controls | BucketOwnerEnforced |
High
| Control | Check command | Pass condition |
|---|---|---|
| Default encryption enabled | get-bucket-encryption | SSEAlgorithm set |
| S3 Bucket Keys enabled | get-bucket-encryption | BucketKeyEnabled: true |
| SSE-C blocked | get-bucket-encryption | BlockedEncryptionTypes.EncryptionType contains SSE-C |
| Not using AWS managed key | get-bucket-encryption | KMSMasterKeyID is NOT aws/s3 |
Medium
| Control | Check command | Pass condition |
|---|---|---|
| Versioning enabled | get-bucket-versioning | Status: Enabled |
| Logging enabled | get-bucket-logging + cloudtrail get-event-selectors | PASS if either S3 server access logging OR CloudTrail data events is configured; NOT CONFIGURED if neither |
| GuardDuty S3 Protection | list-detectors + get-detector | S3_DATA_EVENTS feature is ENABLED |
Prerequisites
IAM Access Analyzer: The audit checklist requires an active analyzer. Before running list-findings, verify one exists:
aws accessanalyzer list-analyzers --region <region>If the result is empty, report as a finding: "No IAM Access Analyzer configured in <region>". Creating the analyzer is a remediation action (Workflow C), not part of the audit.
Low / Compliance
| Control | Check command | Pass condition |
|---|---|---|
| Object Lock (WORM) | get-object-lock-configuration | Enabled if compliance required |
| Cross-region replication | get-bucket-replication | Configured if DR required |
| Bucket in account namespace | bucket name | Ends with -<account-id>-<region>-an |
AWS Config Rules
Core (always enable):
s3-bucket-public-read-prohibited
s3-bucket-ssl-requests-only
s3-bucket-versioning-enabled
s3-bucket-logging-enabledOptional (enable if compliance requires):
s3-bucket-public-write-prohibited
s3-account-level-public-access-blocks
s3-bucket-replication-enabled
cloudtrail-s3-dataevents-enabledS3 Encryption Reference
Choosing an Encryption Option
| Option | When to use | BucketKeyEnabled | Block SSE-C |
|---|---|---|---|
| SSE-S3 (AES256) | Default — no KMS needed | true | true |
| SSE-KMS (customer managed key) | Need key policy control or cross-account sharing | true | true |
SSE-KMS (AWS managed aws/s3) | Never — no key policy control, blocks cross-account | — | — |
SSE-S3 (Recommended Default)
aws s3api put-bucket-encryption \
--bucket <bucket-name> \
--server-side-encryption-configuration \
'{"Rules":[{"ApplyServerSideEncryptionByDefault":{"SSEAlgorithm":"AES256"},"BucketKeyEnabled":true,"BlockedEncryptionTypes":{"EncryptionType":["SSE-C"]}}]}'SSE-KMS with Customer Managed Key
You MUST specify the KMS key by its full ARN (arn:aws:kms:<region>:<account>:key/<key-id>). Do NOT use a key alias.
You MUST apply a least-privilege key policy when creating a KMS key. Do NOT rely on the AWS default key policy — it grants kms:* to the account root, which allows any IAM principal with matching IAM permissions to perform all KMS operations on the key.
Important: The S3 API accepts bothaws/s3and key aliases (e.g.alias/my-key) without returning an error — it will store whatever value you provide. These restrictions are agent-enforced constraints, not API-enforced. Always verify the stored value withget-bucket-encryptionafter applying.
Least-Privilege KMS Key Policy Template
Save the following as key-policy.json before creating the key. Replace <account-id>, <region>, and <bucket-name> with actual values.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowKeyAdministration",
"Effect": "Allow",
"Principal": {"AWS": "arn:aws:iam::<account-id>:role/<key-admin-role>"},
"Action": [
"kms:Create*",
"kms:Describe*",
"kms:Enable*",
"kms:List*",
"kms:Put*",
"kms:Update*",
"kms:Revoke*",
"kms:Disable*",
"kms:Get*",
"kms:Delete*",
"kms:TagResource",
"kms:UntagResource",
"kms:ScheduleKeyDeletion",
"kms:CancelKeyDeletion"
],
"Resource": "*"
},
{
"Sid": "AllowS3EncryptionUsage",
"Effect": "Allow",
"Principal": {"AWS": "arn:aws:iam::<account-id>:root"},
"Action": [
"kms:Encrypt",
"kms:Decrypt",
"kms:ReEncrypt*",
"kms:GenerateDataKey*",
"kms:DescribeKey"
],
"Resource": "*",
"Condition": {
"StringEquals": {
"kms:ViaService": "s3.<region>.amazonaws.com",
"kms:CallerAccount": "<account-id>"
}
}
}
]
}Key policy notes:
AllowKeyAdministration— grants key management to a specific admin role. Replace<key-admin-role>with your actual admin role name.AllowS3EncryptionUsage— restricts encrypt/decrypt to S3 in the specified region and account viakms:ViaServiceandkms:CallerAccountconditions. Scope thePrincipaldown to specific roles if cross-account access is not needed.- Do NOT include a blanket
kms:*statement. If you need to grant additional principals access, add narrowly scoped statements.
# Step 1: Create customer managed key with least-privilege policy
aws kms create-key \
--description "S3 bucket encryption key" \
--policy file://key-policy.json
# Step 2: Apply to bucket (use full key ARN, not alias)
aws s3api put-bucket-encryption \
--bucket <bucket-name> \
--server-side-encryption-configuration \
'{"Rules":[{"ApplyServerSideEncryptionByDefault":{"SSEAlgorithm":"aws:kms","KMSMasterKeyID":"arn:aws:kms:<region>:<account>:key/<key-id>"},"BucketKeyEnabled":true,"BlockedEncryptionTypes":{"EncryptionType":["SSE-C"]}}]}'Why S3 Bucket Keys (always enable)
- Reduces KMS API calls by up to 99%
- Lowers KMS costs significantly for high-throughput workloads
- No impact on security posture
Why Block SSE-C (always block)
- SSE-C keys are managed outside AWS — no CloudTrail audit trail
- Key loss = permanent data loss
- Cannot enforce rotation policies
- Incompatible with centralized compliance requirements
Enforce HTTPS in Transit
⚠️ If the bucket already has a policy, merge thisDenyInsecureTransportstatement into the existingStatementarray rather than replacing the whole policy. See put-bucket-policy safety rules.
{
"Version": "2012-10-17",
"Statement": [{
"Sid": "DenyInsecureTransport",
"Effect": "Deny",
"Principal": "*",
"Action": "s3:*",
"Resource": ["arn:aws:s3:::<bucket>/*", "arn:aws:s3:::<bucket>"],
"Condition": {"Bool": {"aws:SecureTransport": "false"}}
}]
}Principal: "*" and Action: "s3:*" are required wildcards — a Deny policy must match all principals and actions to be effective. Do NOT narrow these.
Do NOT pin TLS certificates — AWS rotates them automatically.
IAM Permissions by Workflow
Minimum IAM permissions required for each workflow. Use aws iam simulate-principal-policy to validate effective permissions before write operations.
| Workflow | Minimum permissions needed |
|---|---|
| A — Secure New Bucket | s3:CreateBucket, s3:PutBucketVersioning, s3:PutEncryptionConfiguration, s3:PutBucketLogging, s3:PutBucketPolicy, s3:GetBucketPolicy, s3:PutBucketAbacStatus, cloudtrail:DescribeTrails, cloudtrail:PutEventSelectors |
| B — Audit | s3:GetBucketPublicAccessBlock, s3:GetBucketAcl, s3:GetBucketOwnershipControls, s3:GetEncryptionConfiguration, s3:GetBucketVersioning, s3:GetBucketLogging, s3:GetBucketPolicy, s3:GetBucketObjectLockConfiguration, accessanalyzer:ListAnalyzers, accessanalyzer:ListFindings, cloudtrail:GetEventSelectors, cloudtrail:DescribeTrails, guardduty:ListDetectors, guardduty:GetDetector |
| C — Remediate | s3:PutBucketPublicAccessBlock, s3:GetBucketPolicy, s3:PutBucketPolicy, s3:PutEncryptionConfiguration, kms:CreateKey, kms:PutKeyPolicy, kms:DescribeKey, iam:SimulatePrincipalPolicy |
| D — Encryption | s3:PutEncryptionConfiguration, kms:CreateKey, kms:PutKeyPolicy, kms:DescribeKey |
| E — Monitoring | cloudtrail:DescribeTrails, cloudtrail:PutEventSelectors, guardduty:ListDetectors, guardduty:CreateDetector, config:PutConfigRule |
S3 Security Remediation
Public Bucket Detected
aws s3api put-public-access-block \
--bucket <bucket-name> \
--public-access-block-configuration \
BlockPublicAcls=true,IgnorePublicAcls=true,BlockPublicPolicy=true,RestrictPublicBuckets=true
# WARNING: Do NOT delete the entire bucket policy — it may contain critical controls (HTTPS enforcement, VPC restrictions, etc.).
# Instead, surgically remove only the offending public-grant statement(s):
# 1. Review the current policy:
aws s3api get-bucket-policy --bucket <bucket-name> --output text | jq .
# 2. Back up existing policy before modification:
aws s3api get-bucket-policy --bucket <bucket-name> --output text > backup-policy-$(date +%s).json
# 3. Remove only statements with "Principal": "*" or "AWS": "*" that grant public access.
# 4. Re-apply the scoped-down policy:
aws s3api put-bucket-policy --bucket <bucket-name> --policy file://scoped-down-policy.json
# Verify
aws s3api get-public-access-block --bucket <bucket-name>Unencrypted Objects / Missing Default Encryption
# Set default encryption
aws s3api put-bucket-encryption \
--bucket <bucket-name> \
--server-side-encryption-configuration \
'{"Rules":[{"ApplyServerSideEncryptionByDefault":{"SSEAlgorithm":"AES256"},"BucketKeyEnabled":true,"BlockedEncryptionTypes":{"EncryptionType":["SSE-C"]}}]}'
# Re-encrypt existing objects
# ⚠️ WARNING: --metadata-directive REPLACE without --metadata drops all user-defined metadata.
# Before running, verify no objects carry custom metadata:
# aws s3api head-object --bucket <bucket-name> --key <sample-key>
# If objects have custom metadata, use a per-object script that reads
# metadata via head-object and re-supplies it with --metadata on copy.
aws s3 cp s3://<bucket-name>/ s3://<bucket-name>/ \
--recursive --sse AES256 --metadata-directive REPLACES3 Bucket Keys Not Enabled (high KMS costs)
aws s3api put-bucket-encryption \
--bucket <bucket-name> \
--server-side-encryption-configuration \
'{"Rules":[{"ApplyServerSideEncryptionByDefault":{"SSEAlgorithm":"aws:kms","KMSMasterKeyID":"<key-arn>"},"BucketKeyEnabled":true,"BlockedEncryptionTypes":{"EncryptionType":["SSE-C"]}}]}'Using AWS Managed Key (aws/s3)
You MUST apply a least-privilege key policy — do NOT create a key without --policy file://key-policy.json. See encryption.md § Least-Privilege KMS Key Policy Template for the full template.
# 1. Save the key-policy.json template from encryption.md (replace placeholders)
# 2. Create customer managed key with least-privilege policy
aws kms create-key --description "S3 encryption key" --policy file://key-policy.json
# 3. Update bucket encryption to use the new key (full ARN, not alias)
aws s3api put-bucket-encryption \
--bucket <bucket-name> \
--server-side-encryption-configuration \
'{"Rules":[{"ApplyServerSideEncryptionByDefault":{"SSEAlgorithm":"aws:kms","KMSMasterKeyID":"arn:aws:kms:<region>:<account>:key/<key-id>"},"BucketKeyEnabled":true,"BlockedEncryptionTypes":{"EncryptionType":["SSE-C"]}}]}'SSE-C Not Blocked
aws s3api put-bucket-encryption \
--bucket <bucket-name> \
--server-side-encryption-configuration \
'{"Rules":[{"ApplyServerSideEncryptionByDefault":{"SSEAlgorithm":"AES256"},"BucketKeyEnabled":true,"BlockedEncryptionTypes":{"EncryptionType":["SSE-C"]}}]}'Missing Logging
Enable either S3 server access logging or CloudTrail data events — one is sufficient.
Option A — S3 Server Access Logging (no per-request charge; you pay only for log file storage in S3):
aws s3api put-bucket-logging \
--bucket <bucket-name> \
--bucket-logging-status \
'{"LoggingEnabled":{"TargetBucket":"<logging-bucket>","TargetPrefix":"<bucket-name>/"}}'Option B — CloudTrail Data Events (per-event charge applies; provides full IAM principal attribution, logs anonymous requests and AccessDenied failures, and supports real-time alerting):
# IMPORTANT: use the trail's home region, not the bucket's region
aws cloudtrail describe-trails --query 'trailList[*].[Name,HomeRegion]'
aws cloudtrail put-event-selectors \
--trail-name <trail-name> \
--region <trail-home-region> \
--event-selectors '[{"ReadWriteType":"All","IncludeManagementEvents":true,"DataResources":[{"Type":"AWS::S3::Object","Values":["arn:aws:s3:::<bucket-name>/*"]}]}]'Overly Permissive Bucket Policy
1. Run IAM Access Analyzer to identify external access paths 2. Scope down Action to minimum required 3. Add Condition blocks to restrict by IP, VPC, or MFA
# Simulate effective permissions before changing
aws iam simulate-principal-policy \
--policy-source-arn <role-arn> \
--action-names s3:GetObject \
--resource-arns arn:aws:s3:::<bucket-name>/keyAccess Denied Errors
Diagnosis order:
1. IAM user/role policy — simulate-principal-policy 2. Bucket policy — get-bucket-policy 3. Block Public Access — get-public-access-block 4. VPC endpoint policy (if applicable) 5. SCPs/RCPs (if AWS Organizations) 6. CloudTrail logs for detailed error context
S3 Security Workflows
Workflow A: Secure New Bucket
Run all steps in order. Do not skip.
# 1. Create in account regional namespace (REQUIRED — not global namespace)
# Pattern: <your-prefix>-<account-id>-<region>-an
aws s3api create-bucket \
--bucket <your-prefix>-111122223333-us-east-1-an \
--bucket-namespace account-regional \
--region us-east-1
# Non-us-east-1: add --create-bucket-configuration LocationConstraint=<region>
# NOTE: Do NOT configure Block Public Access or ACL ownership controls.
# S3 enables Block Public Access and disables ACLs (BucketOwnerEnforced) by default on new buckets.
# Changing these defaults is unnecessary and risks misconfiguration.
# 2. Enable versioning
aws s3api put-bucket-versioning \
--bucket <bucket-name> \
--versioning-configuration Status=Enabled
# 3. Enable default encryption (SSE-S3 + Bucket Keys + SSE-C blocked)
aws s3api put-bucket-encryption \
--bucket <bucket-name> \
--server-side-encryption-configuration \
'{"Rules":[{"ApplyServerSideEncryptionByDefault":{"SSEAlgorithm":"AES256"},"BucketKeyEnabled":true,"BlockedEncryptionTypes":{"EncryptionType":["SSE-C"]}}]}'
# 4. Enable logging (CONDITIONAL — choose one option)
#
# Ask the user which option they prefer before proceeding.
# Present the trade-offs:
#
# Option A — S3 Server Access Logging
# - No per-request charge; you pay only for the storage of the log files in S3
# - Captures all HTTP requests including unauthenticated/presigned URL access
# - No IAM principal ARN attribution; limited identity context
# - No real-time alerting capability
# - Good default for cost-sensitive workloads
#
# Option B — CloudTrail Data Events
# - Per-event charge applies (see CloudTrail pricing)
# - Full IAM principal ARN on every event — best for security investigations
# - Integrates with EventBridge and CloudWatch for real-time alerting
# - Logs anonymous (unauthenticated) requests and AccessDenied failures
# - Does NOT log requests that fail authentication (invalid/malformed credentials)
# - Recommended when security attribution or automated response is required
#
# SKIP THIS STEP if the user has already chosen and configured their preferred option.
# --- Option A: S3 Server Access Logging ---
# SKIP THIS STEP if <bucket-name> is itself the logging bucket.
# WARNING: put-bucket-policy replaces the entire existing policy.
# Attempt to retrieve existing policy first:
aws s3api get-bucket-policy --bucket <logging-bucket> --output text
# If NoSuchBucketPolicy is returned, no backup needed — proceed with a new policy containing only the S3LogDelivery statement.
# If a policy exists, back it up before modification:
aws s3api get-bucket-policy --bucket <logging-bucket> --output text > backup-policy-$(date +%s).json
# Add S3LogDelivery statement to existing policy's Statement array, then apply:
aws s3api put-bucket-policy --bucket <logging-bucket> --policy \
'{"Version":"2012-10-17","Statement":[<...existing statements...>,{"Sid":"S3LogDelivery","Effect":"Allow","Principal":{"Service":"logging.s3.amazonaws.com"},"Action":["s3:PutObject"],"Resource":"arn:aws:s3:::<logging-bucket>/*","Condition":{"StringEquals":{"aws:SourceAccount":"<account-id>"},"ArnLike":{"aws:SourceArn":"arn:aws:s3:::<bucket-name>"}}}]}'
aws s3api put-bucket-logging \
--bucket <bucket-name> \
--bucket-logging-status \
'{"LoggingEnabled":{"TargetBucket":"<logging-bucket>","TargetPrefix":"<bucket-name>/"}}'
# --- Option B: CloudTrail Data Events ---
# IMPORTANT: use the trail's home region, not the bucket's region.
# Find trail home region first:
aws cloudtrail describe-trails --query 'trailList[*].[Name,HomeRegion]'
aws cloudtrail put-event-selectors \
--trail-name <trail-name> \
--region <trail-home-region> \
--event-selectors '[{"ReadWriteType":"All","IncludeManagementEvents":true,"DataResources":[{"Type":"AWS::S3::Object","Values":["arn:aws:s3:::<bucket-name>/*"]}]}]'
# 5. Enforce HTTPS-only
# WARNING: put-bucket-policy replaces the entire existing policy.
# Attempt to retrieve existing policy first:
aws s3api get-bucket-policy --bucket <bucket-name> --output text
# If a policy exists, back it up before modification:
aws s3api get-bucket-policy --bucket <bucket-name> --output text > backup-policy-$(date +%s).json
# If NoSuchBucketPolicy is returned, no backup needed — proceed with a new policy.
# Add DenyInsecureTransport statement to existing policy's Statement array (or create new), then apply:
aws s3api put-bucket-policy --bucket <bucket-name> --policy \
'{"Version":"2012-10-17","Statement":[<...existing statements...>,{"Sid":"DenyInsecureTransport","Effect":"Deny","Principal":"*","Action":"s3:*","Resource":["arn:aws:s3:::<bucket-name>/*","arn:aws:s3:::<bucket-name>"],"Condition":{"Bool":{"aws:SecureTransport":"false"}}}]}'
# 6. Enable ABAC (Attribute-Based Access Control)
aws s3api put-bucket-abac \
--bucket <bucket-name> \
--abac-status Status=EnabledWorkflow E: Enable Monitoring
# GuardDuty — check if detector already exists before creating
aws guardduty list-detectors --region <region>
# Only run create-detector if list-detectors returns empty:
aws guardduty create-detector --enable --region <region>Enable these core AWS Config rules (requires a configuration recorder in the region):
s3-bucket-public-read-prohibiteds3-bucket-ssl-requests-onlys3-bucket-versioning-enableds3-bucket-logging-enabled
Optional (enable if compliance requires):
s3-bucket-public-write-prohibiteds3-account-level-public-access-blockss3-bucket-replication-enabledcloudtrail-s3-dataevents-enabled
Note: CloudTrail data event configuration is covered in Workflow A step 4 (logging choice). If the user chose S3 server access logging in Workflow A and later wants to add CloudTrail, use the command below:
# IMPORTANT: use the trail's home region, not the bucket's region
aws cloudtrail describe-trails --query 'trailList[*].[Name,HomeRegion]'
aws cloudtrail put-event-selectors \
--trail-name <trail-name> \
--region <trail-home-region> \
--event-selectors '[{"ReadWriteType":"All","IncludeManagementEvents":true,"DataResources":[{"Type":"AWS::S3::Object","Values":["arn:aws:s3:::<bucket-name>/*"]}]}]'Workflow B: Audit Commands
aws s3api get-public-access-block --bucket <bucket-name>
aws s3api get-bucket-acl --bucket <bucket-name>
aws s3api get-bucket-ownership-controls --bucket <bucket-name>
aws s3api get-bucket-encryption --bucket <bucket-name>
aws s3api get-bucket-versioning --bucket <bucket-name>
aws s3api get-bucket-logging --bucket <bucket-name>
aws s3api get-object-lock-configuration --bucket <bucket-name>
# ObjectLockConfigurationNotFoundError = NOT CONFIGURED (not a failure)
# Policy checks (Critical: public policy + HTTPS enforcement)
aws s3api get-bucket-policy --bucket <bucket-name> --output text
# Logging — CloudTrail data events (Medium)
aws cloudtrail describe-trails --query 'trailList[*].[Name,HomeRegion]'
aws cloudtrail get-event-selectors \
--trail-name <trail-name> \
--region <trail-home-region>
# GuardDuty S3 Protection (Medium)
aws guardduty list-detectors --region <region>
# If a detector exists:
aws guardduty get-detector --detector-id <detector-id> --region <region>
# Check if an analyzer exists
aws accessanalyzer list-analyzers --region <region>
# If empty, report as finding: "No IAM Access Analyzer configured in <region>"
# Do NOT create an analyzer during audit — remediate separately via Workflow C.
# If an analyzer exists, list S3 findings:
aws accessanalyzer list-findings \
--analyzer-arn <analyzer-arn> \
--filter '{"resourceType":{"eq":["AWS::S3::Bucket"]}}' \
--region <region>Related skills
How it compares
Choose securing-s3-buckets over generic AWS CLI guides when you need a structured audit-and-remediate workflow rather than ad-hoc bucket commands.
FAQ
Who is securing-s3-buckets for?
Developers and software engineers working with securing-s3-buckets patterns described in the skill documentation.
When should I use securing-s3-buckets?
When .
Is securing-s3-buckets safe to install?
Review the Security Audits panel on this page before installing in production.