carlos / platform Public

infra/region-host: optional extra_ingress rules (keymail MX needs tcp/25)

The host SG uses in-line ingress rules, so a root cannot add a standalone
rule resource without it being stripped on the next SG apply. extra_ingress
(default []) lets a deployment root open additional ports — first consumer
is the keymail migration's inbound MX on tcp/25 (plan K1).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude 324617bf1f75d2e764ccdb97bb39e4ba3a4dd73c parent 17bcc6a
2 files changed, +22 −0
  • infra/modules/region-host/main.tf +10 −0
  • infra/modules/region-host/variables.tf +12 −0
diff --git a/infra/modules/region-host/main.tf b/infra/modules/region-host/main.tf
index a56f32447..712fa8bc2 100644
--- a/infra/modules/region-host/main.tf
+++ b/infra/modules/region-host/main.tf
@@ -37,6 +37,16 @@ resource "aws_security_group" "host" {
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
+ dynamic "ingress" {
+ for_each = var.extra_ingress
+ content {
+ description = ingress.value.description
+ from_port = ingress.value.from_port
+ to_port = ingress.value.to_port
+ protocol = ingress.value.protocol
+ cidr_blocks = ingress.value.cidr_blocks
+ }
+ }
# No SSH ingress: admin access is SSM Session Manager only, and the
# carlos binary arrives from the deployment bucket, not over scp.
egress {
diff --git a/infra/modules/region-host/variables.tf b/infra/modules/region-host/variables.tf
index 830fccfa8..2156aff47 100644
--- a/infra/modules/region-host/variables.tf
+++ b/infra/modules/region-host/variables.tf
@@ -43,6 +43,18 @@ variable "ssm_parameter_arn" {
type = string
}
+variable "extra_ingress" {
+ description = "Additional ingress rules beyond the standard 80/443 (e.g. tcp/25 for a host running an inbound MX). The SG uses in-line rules, so extra rules MUST come through here — a standalone aws_vpc_security_group_ingress_rule in the root would fight the in-line set and be stripped on every apply."
+ type = list(object({
+ description = string
+ from_port = number
+ to_port = number
+ protocol = string
+ cidr_blocks = list(string)
+ }))
+ default = []
+}
+
variable "ami_name_pattern" {
description = "AMI name filter for the host image."
type = string