s3-bucket-policy

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

AWS S3 Bucket Policy Expert

AWS S3存储桶策略专家

Expert guidance on creating, analyzing, and optimizing AWS S3 bucket policies with focus on security, access control, and compliance.
为创建、分析和优化AWS S3存储桶策略提供专业指导,重点关注安全性、访问控制与合规性。

Policy Structure

策略结构

json
{
  "Version": "2012-10-17",
  "Id": "PolicyIdentifier",
  "Statement": [
    {
      "Sid": "StatementIdentifier",
      "Effect": "Allow | Deny",
      "Principal": {
        "AWS": "arn:aws:iam::account-id:root"
      },
      "Action": [
        "s3:GetObject",
        "s3:PutObject"
      ],
      "Resource": [
        "arn:aws:s3:::bucket-name",
        "arn:aws:s3:::bucket-name/*"
      ],
      "Condition": {
        "StringEquals": {
          "s3:x-amz-acl": "bucket-owner-full-control"
        }
      }
    }
  ]
}
json
{
  "Version": "2012-10-17",
  "Id": "PolicyIdentifier",
  "Statement": [
    {
      "Sid": "StatementIdentifier",
      "Effect": "Allow | Deny",
      "Principal": {
        "AWS": "arn:aws:iam::account-id:root"
      },
      "Action": [
        "s3:GetObject",
        "s3:PutObject"
      ],
      "Resource": [
        "arn:aws:s3:::bucket-name",
        "arn:aws:s3:::bucket-name/*"
      ],
      "Condition": {
        "StringEquals": {
          "s3:x-amz-acl": "bucket-owner-full-control"
        }
      }
    }
  ]
}

Core Principles

核心原则

yaml
security_principles:
  least_privilege:
    description: "Grant only minimum necessary permissions"
    practice: "Start with deny all, add specific allows"

  explicit_deny:
    description: "Deny always overrides Allow"
    practice: "Use Deny for security guardrails"

  defense_in_depth:
    description: "Multiple layers of security"
    practice: "Combine bucket policy + IAM + ACL + encryption"

  avoid_wildcards:
    bad: '"Principal": "*"'
    better: '"Principal": {"AWS": "arn:aws:iam::123456789012:root"}'

common_mistakes:
  - "Using Principal: * without conditions"
  - "Missing resource ARN for objects (/*)"
  - "Forgetting to block public access"
  - "Not enabling versioning before policies"
yaml
security_principles:
  least_privilege:
    description: "仅授予必要的最小权限"
    practice: "从拒绝所有权限开始,逐步添加特定的允许规则"

  explicit_deny:
    description: "拒绝权限始终优先于允许权限"
    practice: "使用拒绝规则作为安全防护措施"

  defense_in_depth:
    description: "多层安全防护"
    practice: "结合存储桶策略 + IAM + ACL + 加密"

  avoid_wildcards:
    bad: '"Principal": "*"'
    better: '"Principal": {"AWS": "arn:aws:iam::123456789012:root"}'

common_mistakes:
  - "使用不带条件的Principal: *"
  - "遗漏对象的资源ARN (/*)"
  - "忘记阻止公共访问"
  - "在配置策略前未启用版本控制"

Common Policy Patterns

常见策略模式

Public Read for Static Website

静态网站公共读取权限

json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "PublicReadGetObject",
      "Effect": "Allow",
      "Principal": "*",
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::my-website-bucket/*",
      "Condition": {
        "StringEquals": {
          "s3:ExistingObjectTag/public": "true"
        }
      }
    }
  ]
}
json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "PublicReadGetObject",
      "Effect": "Allow",
      "Principal": "*",
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::my-website-bucket/*",
      "Condition": {
        "StringEquals": {
          "s3:ExistingObjectTag/public": "true"
        }
      }
    }
  ]
}

Cross-Account Access

跨账户访问

json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "CrossAccountAccess",
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::987654321098:root"
      },
      "Action": [
        "s3:GetObject",
        "s3:PutObject",
        "s3:ListBucket"
      ],
      "Resource": [
        "arn:aws:s3:::shared-bucket",
        "arn:aws:s3:::shared-bucket/*"
      ],
      "Condition": {
        "StringEquals": {
          "s3:x-amz-acl": "bucket-owner-full-control"
        }
      }
    }
  ]
}
json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "CrossAccountAccess",
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::987654321098:root"
      },
      "Action": [
        "s3:GetObject",
        "s3:PutObject",
        "s3:ListBucket"
      ],
      "Resource": [
        "arn:aws:s3:::shared-bucket",
        "arn:aws:s3:::shared-bucket/*"
      ],
      "Condition": {
        "StringEquals": {
          "s3:x-amz-acl": "bucket-owner-full-control"
        }
      }
    }
  ]
}

CloudFront Origin Access Control

CloudFront源访问控制

json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowCloudFrontServicePrincipal",
      "Effect": "Allow",
      "Principal": {
        "Service": "cloudfront.amazonaws.com"
      },
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::my-cdn-bucket/*",
      "Condition": {
        "StringEquals": {
          "AWS:SourceArn": "arn:aws:cloudfront::123456789012:distribution/EDFDVBD6EXAMPLE"
        }
      }
    }
  ]
}
json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowCloudFrontServicePrincipal",
      "Effect": "Allow",
      "Principal": {
        "Service": "cloudfront.amazonaws.com"
      },
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::my-cdn-bucket/*",
      "Condition": {
        "StringEquals": {
          "AWS:SourceArn": "arn:aws:cloudfront::123456789012:distribution/EDFDVBD6EXAMPLE"
        }
      }
    }
  ]
}

Enforce Encryption

强制加密

json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "DenyUnencryptedUploads",
      "Effect": "Deny",
      "Principal": "*",
      "Action": "s3:PutObject",
      "Resource": "arn:aws:s3:::secure-bucket/*",
      "Condition": {
        "StringNotEquals": {
          "s3:x-amz-server-side-encryption": "aws:kms"
        }
      }
    },
    {
      "Sid": "DenyIncorrectKMSKey",
      "Effect": "Deny",
      "Principal": "*",
      "Action": "s3:PutObject",
      "Resource": "arn:aws:s3:::secure-bucket/*",
      "Condition": {
        "StringNotEquals": {
          "s3:x-amz-server-side-encryption-aws-kms-key-id": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012"
        }
      }
    }
  ]
}
json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "DenyUnencryptedUploads",
      "Effect": "Deny",
      "Principal": "*",
      "Action": "s3:PutObject",
      "Resource": "arn:aws:s3:::secure-bucket/*",
      "Condition": {
        "StringNotEquals": {
          "s3:x-amz-server-side-encryption": "aws:kms"
        }
      }
    },
    {
      "Sid": "DenyIncorrectKMSKey",
      "Effect": "Deny",
      "Principal": "*",
      "Action": "s3:PutObject",
      "Resource": "arn:aws:s3:::secure-bucket/*",
      "Condition": {
        "StringNotEquals": {
          "s3:x-amz-server-side-encryption-aws-kms-key-id": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012"
        }
      }
    }
  ]
}

IP-Based Restrictions

基于IP的访问限制

json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowFromCorporateNetwork",
      "Effect": "Allow",
      "Principal": "*",
      "Action": [
        "s3:GetObject",
        "s3:PutObject"
      ],
      "Resource": "arn:aws:s3:::internal-bucket/*",
      "Condition": {
        "IpAddress": {
          "aws:SourceIp": [
            "192.0.2.0/24",
            "203.0.113.0/24"
          ]
        }
      }
    },
    {
      "Sid": "DenyFromOtherIPs",
      "Effect": "Deny",
      "Principal": "*",
      "Action": "s3:*",
      "Resource": [
        "arn:aws:s3:::internal-bucket",
        "arn:aws:s3:::internal-bucket/*"
      ],
      "Condition": {
        "NotIpAddress": {
          "aws:SourceIp": [
            "192.0.2.0/24",
            "203.0.113.0/24"
          ]
        }
      }
    }
  ]
}
json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowFromCorporateNetwork",
      "Effect": "Allow",
      "Principal": "*",
      "Action": [
        "s3:GetObject",
        "s3:PutObject"
      ],
      "Resource": "arn:aws:s3:::internal-bucket/*",
      "Condition": {
        "IpAddress": {
          "aws:SourceIp": [
            "192.0.2.0/24",
            "203.0.113.0/24"
          ]
        }
      }
    },
    {
      "Sid": "DenyFromOtherIPs",
      "Effect": "Deny",
      "Principal": "*",
      "Action": "s3:*",
      "Resource": [
        "arn:aws:s3:::internal-bucket",
        "arn:aws:s3:::internal-bucket/*"
      ],
      "Condition": {
        "NotIpAddress": {
          "aws:SourceIp": [
            "192.0.2.0/24",
            "203.0.113.0/24"
          ]
        }
      }
    }
  ]
}

VPC Endpoint Access Only

仅允许VPC端点访问

json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "DenyNonVPCAccess",
      "Effect": "Deny",
      "Principal": "*",
      "Action": "s3:*",
      "Resource": [
        "arn:aws:s3:::private-bucket",
        "arn:aws:s3:::private-bucket/*"
      ],
      "Condition": {
        "StringNotEquals": {
          "aws:SourceVpce": "vpce-1234567890abcdef0"
        }
      }
    }
  ]
}
json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "DenyNonVPCAccess",
      "Effect": "Deny",
      "Principal": "*",
      "Action": "s3:*",
      "Resource": [
        "arn:aws:s3:::private-bucket",
        "arn:aws:s3:::private-bucket/*"
      ],
      "Condition": {
        "StringNotEquals": {
          "aws:SourceVpce": "vpce-1234567890abcdef0"
        }
      }
    }
  ]
}

MFA Delete Protection

MFA删除保护

json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "RequireMFAForDelete",
      "Effect": "Deny",
      "Principal": "*",
      "Action": [
        "s3:DeleteObject",
        "s3:DeleteObjectVersion"
      ],
      "Resource": "arn:aws:s3:::critical-bucket/*",
      "Condition": {
        "Bool": {
          "aws:MultiFactorAuthPresent": "false"
        }
      }
    }
  ]
}
json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "RequireMFAForDelete",
      "Effect": "Deny",
      "Principal": "*",
      "Action": [
        "s3:DeleteObject",
        "s3:DeleteObjectVersion"
      ],
      "Resource": "arn:aws:s3:::critical-bucket/*",
      "Condition": {
        "Bool": {
          "aws:MultiFactorAuthPresent": "false"
        }
      }
    }
  ]
}

Time-Based Access

基于时间的访问控制

json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "BusinessHoursOnly",
      "Effect": "Deny",
      "Principal": "*",
      "Action": "s3:*",
      "Resource": [
        "arn:aws:s3:::business-bucket",
        "arn:aws:s3:::business-bucket/*"
      ],
      "Condition": {
        "DateGreaterThan": {
          "aws:CurrentTime": "2024-01-01T18:00:00Z"
        },
        "DateLessThan": {
          "aws:CurrentTime": "2024-01-02T09:00:00Z"
        }
      }
    }
  ]
}
json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "BusinessHoursOnly",
      "Effect": "Deny",
      "Principal": "*",
      "Action": "s3:*",
      "Resource": [
        "arn:aws:s3:::business-bucket",
        "arn:aws:s3:::business-bucket/*"
      ],
      "Condition": {
        "DateGreaterThan": {
          "aws:CurrentTime": "2024-01-01T18:00:00Z"
        },
        "DateLessThan": {
          "aws:CurrentTime": "2024-01-02T09:00:00Z"
        }
      }
    }
  ]
}

CloudTrail Logging

CloudTrail日志记录

json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AWSCloudTrailAclCheck",
      "Effect": "Allow",
      "Principal": {
        "Service": "cloudtrail.amazonaws.com"
      },
      "Action": "s3:GetBucketAcl",
      "Resource": "arn:aws:s3:::cloudtrail-logs-bucket",
      "Condition": {
        "StringEquals": {
          "AWS:SourceArn": "arn:aws:cloudtrail:us-east-1:123456789012:trail/mytrail"
        }
      }
    },
    {
      "Sid": "AWSCloudTrailWrite",
      "Effect": "Allow",
      "Principal": {
        "Service": "cloudtrail.amazonaws.com"
      },
      "Action": "s3:PutObject",
      "Resource": "arn:aws:s3:::cloudtrail-logs-bucket/AWSLogs/123456789012/*",
      "Condition": {
        "StringEquals": {
          "s3:x-amz-acl": "bucket-owner-full-control",
          "AWS:SourceArn": "arn:aws:cloudtrail:us-east-1:123456789012:trail/mytrail"
        }
      }
    }
  ]
}
json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AWSCloudTrailAclCheck",
      "Effect": "Allow",
      "Principal": {
        "Service": "cloudtrail.amazonaws.com"
      },
      "Action": "s3:GetBucketAcl",
      "Resource": "arn:aws:s3:::cloudtrail-logs-bucket",
      "Condition": {
        "StringEquals": {
          "AWS:SourceArn": "arn:aws:cloudtrail:us-east-1:123456789012:trail/mytrail"
        }
      }
    },
    {
      "Sid": "AWSCloudTrailWrite",
      "Effect": "Allow",
      "Principal": {
        "Service": "cloudtrail.amazonaws.com"
      },
      "Action": "s3:PutObject",
      "Resource": "arn:aws:s3:::cloudtrail-logs-bucket/AWSLogs/123456789012/*",
      "Condition": {
        "StringEquals": {
          "s3:x-amz-acl": "bucket-owner-full-control",
          "AWS:SourceArn": "arn:aws:cloudtrail:us-east-1:123456789012:trail/mytrail"
        }
      }
    }
  ]
}

Condition Keys Reference

条件键参考

yaml
condition_keys:
  global:
    aws:SourceIp: "IP address or CIDR"
    aws:SourceVpc: "VPC ID"
    aws:SourceVpce: "VPC endpoint ID"
    aws:PrincipalOrgID: "AWS Organization ID"
    aws:CurrentTime: "ISO 8601 datetime"
    aws:MultiFactorAuthPresent: "true/false"
    aws:SecureTransport: "true/false"

  s3_specific:
    s3:x-amz-acl: "ACL to apply"
    s3:x-amz-server-side-encryption: "AES256 or aws:kms"
    s3:x-amz-server-side-encryption-aws-kms-key-id: "KMS key ARN"
    s3:ExistingObjectTag/<key>: "Object tag value"
    s3:RequestObjectTagKeys: "Tags being set"
    s3:prefix: "Object key prefix"
    s3:max-keys: "Max keys in ListBucket"
    s3:object-lock-mode: "GOVERNANCE or COMPLIANCE"

  operators:
    StringEquals: "Exact match"
    StringNotEquals: "Not equal"
    StringLike: "Wildcard match (*)"
    IpAddress: "IP in CIDR"
    NotIpAddress: "IP not in CIDR"
    DateGreaterThan: "After date"
    DateLessThan: "Before date"
    Bool: "Boolean check"
    Null: "Key exists/not exists"
yaml
condition_keys:
  global:
    aws:SourceIp: "IP地址或CIDR段"
    aws:SourceVpc: "VPC ID"
    aws:SourceVpce: "VPC端点ID"
    aws:PrincipalOrgID: "AWS组织ID"
    aws:CurrentTime: "ISO 8601格式时间"
    aws:MultiFactorAuthPresent: "true/false"
    aws:SecureTransport: "true/false"

  s3_specific:
    s3:x-amz-acl: "要应用的ACL"
    s3:x-amz-server-side-encryption: "AES256或aws:kms"
    s3:x-amz-server-side-encryption-aws-kms-key-id: "KMS密钥ARN"
    s3:ExistingObjectTag/<key>: "对象标签值"
    s3:RequestObjectTagKeys: "正在设置的标签"
    s3:prefix: "对象键前缀"
    s3:max-keys: "ListBucket中的最大键数"
    s3:object-lock-mode: "GOVERNANCE或COMPLIANCE"

  operators:
    StringEquals: "精确匹配"
    StringNotEquals: "不匹配"
    StringLike: "通配符匹配(*)"
    IpAddress: "IP在CIDR段内"
    NotIpAddress: "IP不在CIDR段内"
    DateGreaterThan: "晚于指定日期"
    DateLessThan: "早于指定日期"
    Bool: "布尔值检查"
    Null: "键存在/不存在"

Security Best Practices

安全最佳实践

yaml
security_checklist:
  block_public_access:
    setting: "Block all public access"
    how: |
      aws s3api put-public-access-block \
        --bucket my-bucket \
        --public-access-block-configuration \
        "BlockPublicAcls=true,IgnorePublicAcls=true,BlockPublicPolicy=true,RestrictPublicBuckets=true"

  enable_versioning:
    purpose: "Protect against accidental deletion"
    how: |
      aws s3api put-bucket-versioning \
        --bucket my-bucket \
        --versioning-configuration Status=Enabled

  enable_logging:
    purpose: "Audit access"
    how: |
      aws s3api put-bucket-logging \
        --bucket my-bucket \
        --bucket-logging-status '{"LoggingEnabled":{"TargetBucket":"log-bucket","TargetPrefix":"s3-access/"}}'

  default_encryption:
    purpose: "Encrypt at rest"
    how: |
      aws s3api put-bucket-encryption \
        --bucket my-bucket \
        --server-side-encryption-configuration \
        '{"Rules":[{"ApplyServerSideEncryptionByDefault":{"SSEAlgorithm":"aws:kms","KMSMasterKeyID":"alias/s3-key"}}]}'

  lifecycle_policy:
    purpose: "Manage object lifecycle"
    example: "Transition to Glacier after 90 days, delete after 365"
yaml
security_checklist:
  block_public_access:
    setting: "阻止所有公共访问"
    how: |
      aws s3api put-public-access-block \
        --bucket my-bucket \
        --public-access-block-configuration \
        "BlockPublicAcls=true,IgnorePublicAcls=true,BlockPublicPolicy=true,RestrictPublicBuckets=true"

  enable_versioning:
    purpose: "防止意外删除"
    how: |
      aws s3api put-bucket-versioning \
        --bucket my-bucket \
        --versioning-configuration Status=Enabled

  enable_logging:
    purpose: "审计访问记录"
    how: |
      aws s3api put-bucket-logging \
        --bucket my-bucket \
        --bucket-logging-status '{"LoggingEnabled":{"TargetBucket":"log-bucket","TargetPrefix":"s3-access/"}}'

  default_encryption:
    purpose: "静态加密"
    how: |
      aws s3api put-bucket-encryption \
        --bucket my-bucket \
        --server-side-encryption-configuration \
        '{"Rules":[{"ApplyServerSideEncryptionByDefault":{"SSEAlgorithm":"aws:kms","KMSMasterKeyID":"alias/s3-key"}}]}'

  lifecycle_policy:
    purpose: "管理对象生命周期"
    example: "90天后转换到Glacier存储,365天后删除"

Troubleshooting

故障排查

yaml
common_issues:
  access_denied:
    symptoms: "403 AccessDenied error"
    checks:
      - "Verify IAM user/role permissions"
      - "Check bucket policy allows action"
      - "Verify resource ARN is correct"
      - "Check for explicit Deny statements"
      - "Verify bucket block public access settings"
    debug: |
      # Check effective policy
      aws s3api get-bucket-policy --bucket my-bucket

      # Test access
      aws s3api head-object --bucket my-bucket --key test.txt

  policy_too_large:
    limit: "20 KB maximum"
    solutions:
      - "Use IAM policies instead"
      - "Consolidate statements"
      - "Use conditions instead of listing principals"
      - "Reference IAM roles instead of users"

  invalid_principal:
    symptoms: "MalformedPolicy error"
    common_causes:
      - "Account ID doesn't exist"
      - "Role/user doesn't exist"
      - "Typo in ARN format"
    format: "arn:aws:iam::ACCOUNT-ID:root/role/user"

  condition_not_working:
    checks:
      - "Verify condition key spelling"
      - "Check operator type matches value type"
      - "Ensure condition applies to correct action"
yaml
common_issues:
  access_denied:
    symptoms: "403 AccessDenied错误"
    checks:
      - "验证IAM用户/角色权限"
      - "检查存储桶策略是否允许该操作"
      - "验证资源ARN是否正确"
      - "检查是否存在显式拒绝语句"
      - "验证存储桶阻止公共访问设置"
    debug: |
      # 检查有效策略
      aws s3api get-bucket-policy --bucket my-bucket

      # 测试访问权限
      aws s3api head-object --bucket my-bucket --key test.txt

  policy_too_large:
    limit: "最大20 KB"
    solutions:
      - "改用IAM策略"
      - "合并语句"
      - "使用条件而非列出所有主体"
      - "引用IAM角色而非用户"

  invalid_principal:
    symptoms: "MalformedPolicy错误"
    common_causes:
      - "账户ID不存在"
      - "角色/用户不存在"
      - "ARN格式输入错误"
    format: "arn:aws:iam::ACCOUNT-ID:root/role/user"

  condition_not_working:
    checks:
      - "验证条件键拼写"
      - "检查运算符类型与值类型匹配"
      - "确保条件应用于正确的操作"

Policy Validation

策略验证

bash
undefined
bash
undefined

Validate policy syntax

验证策略语法

aws iam simulate-custom-policy
--policy-input-list file://policy.json
--action-names s3:GetObject
--resource-arns arn:aws:s3:::my-bucket/test.txt
aws iam simulate-custom-policy
--policy-input-list file://policy.json
--action-names s3:GetObject
--resource-arns arn:aws:s3:::my-bucket/test.txt

Test policy with IAM Policy Simulator

使用IAM策略模拟器测试

Check for public access

检查公共访问状态

aws s3api get-bucket-policy-status --bucket my-bucket
aws s3api get-bucket-policy-status --bucket my-bucket

List bucket policies

列出存储桶策略

aws s3api get-bucket-policy --bucket my-bucket --output text
undefined
aws s3api get-bucket-policy --bucket my-bucket --output text
undefined

Terraform Example

Terraform示例

hcl
resource "aws_s3_bucket" "example" {
  bucket = "my-secure-bucket"
}

resource "aws_s3_bucket_public_access_block" "example" {
  bucket = aws_s3_bucket.example.id

  block_public_acls       = true
  block_public_policy     = true
  ignore_public_acls      = true
  restrict_public_buckets = true
}

resource "aws_s3_bucket_policy" "example" {
  bucket = aws_s3_bucket.example.id
  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Sid       = "EnforceSSL"
        Effect    = "Deny"
        Principal = "*"
        Action    = "s3:*"
        Resource = [
          aws_s3_bucket.example.arn,
          "${aws_s3_bucket.example.arn}/*"
        ]
        Condition = {
          Bool = {
            "aws:SecureTransport" = "false"
          }
        }
      }
    ]
  })
}
hcl
resource "aws_s3_bucket" "example" {
  bucket = "my-secure-bucket"
}

resource "aws_s3_bucket_public_access_block" "example" {
  bucket = aws_s3_bucket.example.id

  block_public_acls       = true
  block_public_policy     = true
  ignore_public_acls      = true
  restrict_public_buckets = true
}

resource "aws_s3_bucket_policy" "example" {
  bucket = aws_s3_bucket.example.id
  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Sid       = "EnforceSSL"
        Effect    = "Deny"
        Principal = "*"
        Action    = "s3:*"
        Resource = [
          aws_s3_bucket.example.arn,
          "${aws_s3_bucket.example.arn}/*"
        ]
        Condition = {
          Bool = {
            "aws:SecureTransport" = "false"
          }
        }
      }
    ]
  })
}

Лучшие практики

最佳实践

  1. Least privilege — минимальные необходимые права
  2. Block public access — блокируй публичный доступ по умолчанию
  3. Use conditions — добавляй условия для дополнительной защиты
  4. Enable logging — логируй все обращения к bucket
  5. Version control — храни политики в git
  6. Regular audits — проверяй политики регулярно
  1. 最小权限原则——仅授予必要的最小权限
  2. 阻止公共访问——默认情况下禁止公共访问
  3. 使用条件规则——添加条件以增强安全性
  4. 启用日志记录——记录所有对存储桶的访问请求
  5. 版本控制——将策略存储在Git中
  6. 定期审计——定期检查策略