carlos / platform Public

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.
Paul Campbell ee760150de6e3722061724f6975b8f8b295b6e9d parent e7b40fb
2 files changed, +31 −0
  • infra/modules/region-remote-host/README.md +13 −0
  • infra/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).