# 🤖 The two state buckets. Same posture for both: versioned, keep the last # 5 noncurrent versions (1-day linger is a lifecycle floor, not a cap), and # Block Public Access — the plan's "design as if public, configure as private" # line. Contents are client-side ciphertext either way. locals { buckets = { # Litestream replication targets, one prefix per instance host. instances = "eleven-dev-instances-${local.account_id}" # home's vault store (the s3Store backend, #550 Part 1). home = "eleven-dev-home-${local.account_id}" } } resource "aws_s3_bucket" "state" { for_each = local.buckets bucket = each.value } resource "aws_s3_bucket_versioning" "state" { for_each = local.buckets bucket = aws_s3_bucket.state[each.key].id versioning_configuration { status = "Enabled" } } resource "aws_s3_bucket_lifecycle_configuration" "state" { for_each = local.buckets bucket = aws_s3_bucket.state[each.key].id rule { id = "keep-last-5-noncurrent" status = "Enabled" filter {} noncurrent_version_expiration { noncurrent_days = 1 newer_noncurrent_versions = 5 } } } resource "aws_s3_bucket_public_access_block" "state" { for_each = local.buckets bucket = aws_s3_bucket.state[each.key].id block_public_acls = true block_public_policy = true ignore_public_acls = true restrict_public_buckets = true } # TLS-only: deny any request arriving over plain HTTP. Every client of these # buckets (Litestream, the AWS SDKs/CLI) already speaks HTTPS — this turns # that assumption into policy. A deny-only statement grants nothing public, # so it attaches fine under the full public-access block above. data "aws_iam_policy_document" "state_tls_only" { for_each = local.buckets statement { sid = "DenyInsecureTransport" effect = "Deny" actions = ["s3:*"] resources = [ aws_s3_bucket.state[each.key].arn, "${aws_s3_bucket.state[each.key].arn}/*", ] principals { type = "*" identifiers = ["*"] } condition { test = "Bool" variable = "aws:SecureTransport" values = ["false"] } } } resource "aws_s3_bucket_policy" "state_tls_only" { for_each = local.buckets bucket = aws_s3_bucket.state[each.key].id policy = data.aws_iam_policy_document.state_tls_only[each.key].json }