infra/region-remote-host: data bucket gets versioning, SSE, prevent_destroy
Matches the deployment-buckets convention documented in infra/modules/README.md for this bucket class; review finding fix.
2 files changed,
+31
−0
infra/modules/region-remote-host/README.md+13 −0infra/modules/region-remote-host/main.tf+18 −0
diff --git a/infra/modules/region-remote-host/README.md b/infra/modules/region-remote-host/README.md| index eeee954e8..4f07c0abc 100644 |
| --- a/infra/modules/region-remote-host/README.md |
| +++ b/infra/modules/region-remote-host/README.md |
| @@ -19,3 +19,16 @@ actions (`GetObject`/`PutObject`/`DeleteObject`) scoped to the object ARNs, |
| and bucket-level actions (`ListBucket`/`GetBucketLocation`) scoped to the |
| bucket ARNs. If region-host's action list changes, this module's should |
| change with it. |
| + |
| +The data bucket follows the same convention `deployment-buckets` uses for |
| +this class of bucket (see `infra/modules/README.md`): versioning, AES256 |
| +SSE, a full public-access block, and `prevent_destroy`, hard-coded the same |
| +way `deployment-buckets` hard-codes it (tofu can't take a variable in a |
| +`lifecycle` block). Boxes are disposable; this bucket is not — parked |
| +instance state has no other recovery story. A demo region like `pi` that |
| +needs to go away entirely is not a `tofu destroy`: empty the bucket first |
| +(S3 refuses to delete a non-empty bucket regardless of `prevent_destroy`), |
| +then either comment out the `prevent_destroy` line for that one apply or |
| +`tofu state rm` the bucket before removing the module instance — the same |
| +manual override `deployment-buckets` requires, not a mechanism specific to |
| +this module. |
diff --git a/infra/modules/region-remote-host/main.tf b/infra/modules/region-remote-host/main.tf| index 4e85d35e4..90b74d912 100644 |
| --- a/infra/modules/region-remote-host/main.tf |
| +++ b/infra/modules/region-remote-host/main.tf |
| @@ -6,6 +6,11 @@ |
| # the deployment bucket plus ITS OWN region's data bucket and nothing else. |
| # A wrong-region host fails loudly at the IAM layer, same property as every |
| # cloud host. |
| +# |
| +# The data bucket follows the deployment-buckets convention for this class |
| +# of bucket (infra/modules/README.md, infra/modules/deployment-buckets/ |
| +# main.tf): boxes are disposable, this bucket is not, hence versioning, |
| +# AES256 SSE, a full public-access block, and prevent_destroy. |
| terraform { |
| required_version = ">= 1.10" |
| @@ -19,6 +24,12 @@ terraform { |
| resource "aws_s3_bucket" "data" { |
| bucket = var.data_bucket_name |
| + lifecycle { prevent_destroy = true } |
| +} |
| + |
| +resource "aws_s3_bucket_versioning" "data" { |
| + bucket = aws_s3_bucket.data.id |
| + versioning_configuration { status = "Enabled" } |
| } |
| resource "aws_s3_bucket_public_access_block" "data" { |
| @@ -29,6 +40,13 @@ resource "aws_s3_bucket_public_access_block" "data" { |
| restrict_public_buckets = true |
| } |
| +resource "aws_s3_bucket_server_side_encryption_configuration" "data" { |
| + bucket = aws_s3_bucket.data.id |
| + rule { |
| + apply_server_side_encryption_by_default { sse_algorithm = "AES256" } |
| + } |
| +} |
| + |
| # The off-cloud host principal. No instance profile exists off EC2; this |
| # user + access key is the C6 decision-6 shape (IAM Roles Anywhere is the |
| # later hardening — the policy below is what either principal would carry). |