diff --git a/CHANGELOG.md b/CHANGELOG.md index 6b777f3..18e40b8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -88,3 +88,6 @@ * 2.8.0 -- 2025-10-02 - web: add prefix list capability + +* 2.8.1 -- 2025-10-02 + - https: add module diff --git a/common/version.tf b/common/version.tf index 4baf91e..bf2205b 100644 --- a/common/version.tf +++ b/common/version.tf @@ -1,3 +1,3 @@ locals { - _module_version = "2.8.0" + _module_version = "2.8.1" } diff --git a/https/README.md b/https/README.md new file mode 100644 index 0000000..c3d2b2d --- /dev/null +++ b/https/README.md @@ -0,0 +1,90 @@ +# About https + +This describes how to use the aws-common-security-groups submodule for https + +Default port of 443 is enabled. + +## Usage + +```hcl +module "web" { + source = "git@github.e.it.census.gov:terraform-modules/aws-common-security-groups.git//https?ref=tf-ugprade" + + vpc_id = var.vpc_id + ## optional + # ingress_networks = null # use this to only set based on other fields like prefix lists + # ingress_prefix_list_names = [ "onprem-networks.core" ] + # egress_prefix_list_names = [ ] + + ## tags for Name, CostAllocation, and Environment are pre-set, but they can be overriden + # tags = { } +} +``` + +## ingress\_networks +This is the list of network CIDR blocks for inbound access to the ports defined for https. +There is a default set of CIDR blocks provided if this field is not populated. This is comprised of the +Census networks: +* 148.129.0.0/16: Census class B +* 172.16.0.0/12: Census private class B +* 192.168.0.0/16: Census private class C +* 10.0.0.0/8: Census private class A + +Passing a null or empty list to this field will ignore the ingress setting on these networks. + +## ingress\_prefix\_list\_names +In order to use a managed prefix list, you may pass a list of names in this field. The prefix lists +will be looked up and the resultant IDs used in the security group for inbound port access to RDS +Postgres. This will fail if the prefix list does not exist. + +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 1.0.0 | +| [aws](#requirement\_aws) | >= 5.0 | + +## Providers + +| Name | Version | +|------|---------| +| [aws](#provider\_aws) | >= 5.0 | + +## Modules + +No modules. + +## Resources + +| Name | Type | +|------|------| +| [aws_security_group.this_security_group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group) | resource | +| [aws_ec2_managed_prefix_list.egress](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ec2_managed_prefix_list) | data source | +| [aws_ec2_managed_prefix_list.ingress](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ec2_managed_prefix_list) | data source | +| [aws_vpc.this_vpc](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/vpc) | data source | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [description](#input\_description) | Security Group Description | `string` | `"HTTPS Security Group"` | no | +| [egress\_networks](#input\_egress\_networks) | List of egress networks (all ports) | `list(string)` |
[
"0.0.0.0/0"
]
| no | +| [egress\_prefix\_list\_names](#input\_egress\_prefix\_list\_names) | List of prefix list names for eggress access | `list(string)` | `[]` | no | +| [egress\_security\_groups](#input\_egress\_security\_groups) | List of egress security groups (all ports) | `list(string)` | `[]` | no | +| [enable\_self](#input\_enable\_self) | Enable\|Disable self full access | `bool` | `false` | no | +| [ingress\_networks](#input\_ingress\_networks) | List of ingress networks for external access (not all ports). Use null to disable built-in settings | `list(string)` |
[
"0.0.0.0/0"
]
| no | +| [ingress\_prefix\_list\_names](#input\_ingress\_prefix\_list\_names) | List of prefix list names for ingress access | `list(string)` | `[]` | no | +| [ingress\_security\_groups](#input\_ingress\_security\_groups) | List of ingress security groups for all ports | `list(string)` | `[]` | no | +| [name](#input\_name) | Security Group Name | `string` | `"m-postgres-db"` | no | +| [short\_description](#input\_short\_description) | Security Group Short Description | `string` | `"HTTPS"` | no | +| [tags](#input\_tags) | Extra security group tags | `map(any)` |
{
"CostAllocation": "csvd:infrastructure",
"Environment": "csvd-infrastructure"
}
| no | +| [use\_vpc\_cidr](#input\_use\_vpc\_cidr) | Enable\|Disable use of VPC CIDR block in the ingress\_networks | `bool` | `false` | no | +| [vpc\_full\_name](#input\_vpc\_full\_name) | VPC Name | `string` | `""` | no | +| [vpc\_id](#input\_vpc\_id) | VPC ID Number | `string` | n/a | yes | + +## Outputs + +| Name | Description | +|------|-------------| +| [this\_security\_group\_arn](#output\_this\_security\_group\_arn) | Created security group ARN | +| [this\_security\_group\_id](#output\_this\_security\_group\_id) | Created security group ID | diff --git a/https/data.prefix_lists.tf b/https/data.prefix_lists.tf new file mode 120000 index 0000000..08df656 --- /dev/null +++ b/https/data.prefix_lists.tf @@ -0,0 +1 @@ +../common/data.prefix_lists.tf \ No newline at end of file diff --git a/https/local.tf b/https/local.tf new file mode 100644 index 0000000..424f587 --- /dev/null +++ b/https/local.tf @@ -0,0 +1,3 @@ +locals { + _module_name = "aws-common-security-groups/https" +} diff --git a/https/main.tf b/https/main.tf new file mode 100644 index 0000000..bc5fd73 --- /dev/null +++ b/https/main.tf @@ -0,0 +1,163 @@ +/** +* # About https +* +* This describes how to use the aws-common-security-groups submodule for https +* +* Default port of 443 is enabled. +* +* ## Usage +* +* ```hcl +* module "web" { +* source = "git@github.e.it.census.gov:terraform-modules/aws-common-security-groups.git//https?ref=tf-ugprade" +* +* vpc_id = var.vpc_id +* ## optional +* # ingress_networks = null # use this to only set based on other fields like prefix lists +* # ingress_prefix_list_names = [ "onprem-networks.core" ] +* # egress_prefix_list_names = [ ] +* +* ## tags for Name, CostAllocation, and Environment are pre-set, but they can be overriden +* # tags = { } +* } +* ``` +* +* ## ingress_networks +* This is the list of network CIDR blocks for inbound access to the ports defined for https. +* There is a default set of CIDR blocks provided if this field is not populated. This is comprised of the +* Census networks: +* * 148.129.0.0/16: Census class B +* * 172.16.0.0/12: Census private class B +* * 192.168.0.0/16: Census private class C +* * 10.0.0.0/8: Census private class A +* +* Passing a null or empty list to this field will ignore the ingress setting on these networks. +* +* ## ingress_prefix_list_names +* In order to use a managed prefix list, you may pass a list of names in this field. The prefix lists +* will be looked up and the resultant IDs used in the security group for inbound port access to RDS +* Postgres. This will fail if the prefix list does not exist. +*/ + +data "aws_vpc" "this_vpc" { + count = var.use_vpc_cidr ? 1 : 0 + id = var.vpc_id +} + +locals { + vpc_networks = var.use_vpc_cidr ? [data.aws_vpc.this_vpc[0].cidr_block] : [] + external_ingress_networks = compact(concat(local.vpc_networks, local.ingress_networks)) + ## ingress_sg_names = zipmap(var.ingress_security_groups, data.aws_security_group.ingress_security_groups[*].name) + ## egress_sg_names = zipmap(var.egress_security_groups, data.aws_security_group.egress_security_groups[*].name) + ## self = var.enable_self ? [1] : [] + short_description = var.short_description == "" ? var.description : var.short_description +} + +resource "aws_security_group" "this_security_group" { + name = local.name + description = var.description + vpc_id = var.vpc_id + + # ingresss external port list (list + vpc if enabaled) + dynamic "ingress" { + for_each = (var.ingress_networks != null && length(local.ingress_networks) > 0) ? local.port_map["external"] : toset([]) + iterator = p + content { + description = "${local.short_description}: ${p.value["description"]}" + from_port = p.value["from"] + to_port = p.value["to"] + protocol = p.value["proto"] + cidr_blocks = length(local.external_ingress_networks) > 0 ? local.external_ingress_networks : p.value["cidr"] + } + } + + + # ingress with prefix lists + dynamic "ingress" { + for_each = length(var.ingress_prefix_list_names) > 0 ? local.port_map["external"] : toset([]) + iterator = p + content { + description = "${local.short_description}: ${p.value["description"]}" + from_port = p.value["from"] + to_port = p.value["to"] + protocol = p.value["proto"] + prefix_list_ids = [for pl in data.aws_ec2_managed_prefix_list.ingress : pl.id] + } + } + + + # ingress security group ids (just defined ports) + dynamic "ingress" { + for_each = length(local.ingress_sg) > 0 ? local.port_map["external"] : toset([]) + iterator = p + content { + description = "${local.short_description}: ${p.value["description"]}" + from_port = p.value["from"] + to_port = p.value["to"] + protocol = p.value["proto"] + security_groups = local.ingress_sg + } + } + + + # ingress self (list with one or zero items) + dynamic "ingress" { + for_each = var.enable_self ? local.port_map["external"] : toset([]) + iterator = p + content { + description = "${local.short_description}: ${p.value["description"]}" + from_port = p.value["from"] + to_port = p.value["to"] + protocol = p.value["proto"] + self = true + } + } + + + # egress all + # for_each = (var.egress_networks != null && length(local.egress_networks) > 0) ? local.port_map["external"] : toset([]) + egress { + description = "${local.short_description}: All" + from_port = 0 + to_port = 0 + protocol = -1 + cidr_blocks = local.egress_networks + } + + # egress security group ids (all) + dynamic "egress" { + for_each = length(local.egress_sg) > 0 ? { 1 = 1 } : {} + iterator = sg + content { + description = local.short_description + from_port = 0 + to_port = 0 + protocol = -1 + security_groups = local.egress_sg + } + } + + # egress with prefix lists + dynamic "egress" { + for_each = length(var.egress_prefix_list_names) > 0 ? { 1 = 1 } : {} + iterator = p + content { + description = local.short_description + from_port = 0 + to_port = 0 + protocol = -1 + prefix_list_ids = [for pl in data.aws_ec2_managed_prefix_list.egress : pl.id] + } + } + + tags = merge( + var.tags, + { + "Name" = "sg-${local.name}" + "boc:created_by" = "terraform" + "boc:tf_module_version" = local._module_version + "boc:tf_module_name" = local._module_name + "boc:vpc:info" = join(" ", compact([var.vpc_id, var.vpc_full_name])) + } + ) +} diff --git a/https/output.tf b/https/output.tf new file mode 100644 index 0000000..fbdd35a --- /dev/null +++ b/https/output.tf @@ -0,0 +1,9 @@ +output "this_security_group_id" { + description = "Created security group ID" + value = aws_security_group.this_security_group.id +} + +output "this_security_group_arn" { + description = "Created security group ARN" + value = aws_security_group.this_security_group.arn +} diff --git a/https/ports.tf b/https/ports.tf new file mode 100644 index 0000000..dea09fb --- /dev/null +++ b/https/ports.tf @@ -0,0 +1,33 @@ +# ports = list of list of +# from_port +# to_port +# proto +# description +# cidr_block +# list of: all, external (more added as needed) + +locals { + description = "HTTPS" + n_all = ["0.0.0.0/0"] + n_census = ["148.129.0.0/16", "192.168.0.0/16", "172.16.0.0/12", "10.0.0.0/8"] + source_groups = ["all", "external"] + + name = var.name + ports = [ + [443, 443, "tcp", "https", local.n_census, ["external"]], + ] + + # these are ignored + ingress_networks = var.ingress_networks == null ? [] : var.ingress_networks + egress_networks = var.egress_networks == null ? [] : var.egress_networks + + # these are ignored + ingress_sg = var.ingress_security_groups + egress_sg = var.egress_security_groups + + p_fields = ["from", "to", "proto", "description", "cidr", "source_group"] + p_map = [for p in local.ports : zipmap(local.p_fields, p)] + port_map = { for s in local.source_groups : + s => [for p in local.p_map : p if contains(p["source_group"], s)] + } +} diff --git a/https/variables.prefix_lists.tf b/https/variables.prefix_lists.tf new file mode 120000 index 0000000..86cbd3c --- /dev/null +++ b/https/variables.prefix_lists.tf @@ -0,0 +1 @@ +../common/variables.prefix_lists.tf \ No newline at end of file diff --git a/https/variables.tf b/https/variables.tf new file mode 100644 index 0000000..5c905e0 --- /dev/null +++ b/https/variables.tf @@ -0,0 +1,79 @@ +#--- +# change between different modules as needed +#--- +variable "name" { + description = "Security Group Name" + type = string + default = "m-postgres-db" +} + +variable "description" { + description = "Security Group Description" + type = string + default = "HTTPS Security Group" +} + +variable "short_description" { + description = "Security Group Short Description" + type = string + default = "HTTPS" +} + +variable "enable_self" { + description = "Enable|Disable self full access" + type = bool + default = false +} + +variable "use_vpc_cidr" { + description = "Enable|Disable use of VPC CIDR block in the ingress_networks" + type = bool + default = false +} + +#--- +# others with defaults +#--- +variable "vpc_id" { + description = "VPC ID Number" + type = string +} + +variable "vpc_full_name" { + description = "VPC Name" + type = string + default = "" +} + +variable "ingress_networks" { + description = "List of ingress networks for external access (not all ports). Use null to disable built-in settings" + type = list(string) + default = ["0.0.0.0/0"] +} + +variable "egress_networks" { + description = "List of egress networks (all ports)" + type = list(string) + default = ["0.0.0.0/0"] +} + +variable "ingress_security_groups" { + description = "List of ingress security groups for all ports" + type = list(string) + default = [] +} + +variable "egress_security_groups" { + description = "List of egress security groups (all ports)" + type = list(string) + default = [] +} + +variable "tags" { + description = "Extra security group tags" + type = map(any) + default = { + "CostAllocation" = "csvd:infrastructure" + "Environment" = "csvd-infrastructure" + } +} diff --git a/https/version.tf b/https/version.tf new file mode 120000 index 0000000..b83c5b7 --- /dev/null +++ b/https/version.tf @@ -0,0 +1 @@ +../common/version.tf \ No newline at end of file diff --git a/https/versions.tf b/https/versions.tf new file mode 120000 index 0000000..41bb22f --- /dev/null +++ b/https/versions.tf @@ -0,0 +1 @@ +../common/versions.tf \ No newline at end of file