Skip to content

refactor/base #35

Merged
merged 2 commits into from
Mar 19, 2026
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,3 +101,5 @@
* 2.10.0 -- 2026-03-03
- rds-mysql: add prefix list capability

* 2.11.0 -- 2026-03-19
- it-windows-base: refactor to use prefix lists and a YAML file
2 changes: 1 addition & 1 deletion common/version.tf
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
locals {
_module_version = "2.10.0"
_module_version = "2.11.0"
}
40 changes: 15 additions & 25 deletions it-windows-base/README.md
Original file line number Diff line number Diff line change
@@ -1,35 +1,15 @@
# About it-windows-base

This describes how to use the aws-common-security-groups submodule for it-windows-base.

Commonly used ports and services are set up here, including ICMP, AD, RDP, NTP, DNS, SNMP,
monit, munin, iperf, netperf, NetBackup and Opsware.

## Usage

```hcl
module "it-windows-base" {
source = "git@github.e.it.census.gov:terraform-modules/aws-common-security-groups.git//it-windows-base"
# name = "it-windows-base"
vpc_id = var.vpc_id
# Name, CostAllocation, and Environment are pre-set, but they can be overriden
# tags = { }
}
```

## Requirements

| Name | Version |
|------|---------|
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.0.0 |
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 5.0 |
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.10.0 |
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 6.0 |

## Providers

| Name | Version |
|------|---------|
| <a name="provider_aws"></a> [aws](#provider\_aws) | >= 5.0 |
| <a name="provider_aws"></a> [aws](#provider\_aws) | >= 6.0 |

## Modules

Expand All @@ -43,8 +23,16 @@ module "it-windows-base" {
| Name | Type |
|------|------|
| [aws_security_group.this_security_group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group) | resource |
| [aws_security_group.egress_security_groups](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/security_group) | data source |
| [aws_security_group.ingress_security_groups](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/security_group) | data source |
| [aws_vpc_security_group_egress_rule.all](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc_security_group_egress_rule) | resource |
| [aws_vpc_security_group_ingress_rule.cidr_block](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc_security_group_ingress_rule) | resource |
| [aws_vpc_security_group_ingress_rule.prefix_lists](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc_security_group_ingress_rule) | resource |
| [aws_vpc_security_group_ingress_rule.security_group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc_security_group_ingress_rule) | resource |
| [aws_vpc_security_group_ingress_rule.self](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc_security_group_ingress_rule) | resource |
| [aws_arn.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/arn) | data source |
| [aws_caller_identity.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source |
| [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_region.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/region) | data source |
| [aws_vpc.selected](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/vpc) | data source |
| [aws_vpc.this_vpc](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/vpc) | data source |

Expand All @@ -54,9 +42,11 @@ module "it-windows-base" {
|------|-------------|------|---------|:--------:|
| <a name="input_description"></a> [description](#input\_description) | Security Group Description | `string` | `"Windows Common Base Security Group"` | no |
| <a name="input_egress_networks"></a> [egress\_networks](#input\_egress\_networks) | List of egress networks (all ports) | `list(string)` | <pre>[<br/> "0.0.0.0/0"<br/>]</pre> | no |
| <a name="input_egress_prefix_list_names"></a> [egress\_prefix\_list\_names](#input\_egress\_prefix\_list\_names) | List of prefix list names for eggress access | `list(string)` | `[]` | no |
| <a name="input_egress_security_groups"></a> [egress\_security\_groups](#input\_egress\_security\_groups) | List of egress security groups (all ports) | `list(string)` | `[]` | no |
| <a name="input_enable_self"></a> [enable\_self](#input\_enable\_self) | Enable\|Disable self full access | `bool` | `false` | no |
| <a name="input_ingress_networks"></a> [ingress\_networks](#input\_ingress\_networks) | List of ingress networks for external access (not all ports) | `list(string)` | <pre>[<br/> "0.0.0.0/0"<br/>]</pre> | no |
| <a name="input_ingress_prefix_list_names"></a> [ingress\_prefix\_list\_names](#input\_ingress\_prefix\_list\_names) | List of prefix list names for ingress access | `list(string)` | `[]` | no |
| <a name="input_ingress_security_groups"></a> [ingress\_security\_groups](#input\_ingress\_security\_groups) | List of ingress security groups for all ports | `list(string)` | `[]` | no |
| <a name="input_name"></a> [name](#input\_name) | Security Group Name | `string` | `"it-windows-base"` | no |
| <a name="input_short_description"></a> [short\_description](#input\_short\_description) | Security Group Short Description | `string` | `"Windows"` | no |
Expand Down
1 change: 1 addition & 0 deletions it-windows-base/data.tf
219 changes: 118 additions & 101 deletions it-windows-base/main.tf
Original file line number Diff line number Diff line change
@@ -1,123 +1,140 @@
/**
* # About it-windows-base
*
* This describes how to use the aws-common-security-groups submodule for it-windows-base.
*
* Commonly used ports and services are set up here, including ICMP, AD, RDP, NTP, DNS, SNMP,
* monit, munin, iperf, netperf, NetBackup and Opsware.
*
* ## Usage
*
* ```hcl
* module "it-windows-base" {
* source = "git@github.e.it.census.gov:terraform-modules/aws-common-security-groups.git//it-windows-base"
*
* # name = "it-windows-base"
* vpc_id = var.vpc_id
* # Name, CostAllocation, and Environment are pre-set, but they can be overriden
* # tags = { }
* }
* ```
*/

data "aws_vpc" "this_vpc" {
count = var.use_vpc_cidr ? 1 : 0
id = var.vpc_id
id = var.vpc_id
}

data "aws_security_group" "ingress_security_groups" {
count = length(var.ingress_security_groups)
id = element(var.ingress_security_groups, count.index)
}
locals {
n_all = ["0.0.0.0/0"]

data "aws_security_group" "egress_security_groups" {
count = length(var.egress_security_groups)
id = element(var.egress_security_groups, count.index)
ingress_networks = var.ingress_networks == null ? [] : var.ingress_networks
egress_networks = var.egress_networks == null ? [] : var.egress_networks
}

locals {
vpc_networks = var.use_vpc_cidr ? [data.aws_vpc.this_vpc[0].cidr_block] : []
vpc_networks = var.use_vpc_cidr ? [data.aws_vpc.this_vpc.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
# 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)
}

resource "aws_security_group" "this_security_group" {
name = local.name
description = var.description
vpc_id = var.vpc_id
# vpc_id = "${data.aws_vpc.selected.id}"

# ingresss external port list (list + vpc if enabaled)
dynamic "ingress" {
for_each = local.port_map["external"]
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(p.value["cidr"]) == 0 ? local.external_ingress_networks : p.value["cidr"]
locals {
_sg = yamldecode(file("${path.module}/ports.yml"))
sg = merge(local._sg, { ingress_networks = flatten(distinct(compact(concat(local.ingress_networks, var.use_vpc_cidr ? [data.aws_vpc.this_vpc.cidr_block] : [])))) })
sg_ingress_prefix_lists = distinct(compact([for sgr in local.sg.ingress : try(sgr.prefix_list, null)]))
sg_egress_prefix_lists = try(distinct(compact([for sgr in local.sg.egress : try(sgr.prefix_list, null)])), [])
sg_c1 = flatten([for i in local.sg.ingress : merge(i, {
key = local.sg.name,
# label = format("%v:%v:%v", local.sg.name, i.from, i.proto)
label = format("%v:%v:%v", i.from, i.to, i.proto)
# cidr_blocks = try(i.cidr_blocks, null) == "%%INCOMING%%" ? local.ingress_networks : []
cidr_blocks = try(i.cidr_blocks, [])
}
}

# ingress security group ids (all)
dynamic "ingress" {
for_each = local.ingress_sg
iterator = sg
content {
description = "${local.short_description}: ${local.ingress_sg_names[sg.value]}"
from_port = 0
to_port = 0
protocol = -1
security_groups = [sg.value]
)])
sg_cidr = flatten([for sg in local.sg_c1 : [for c in sg.cidr_blocks : merge(sg, {
cidr_label = format("%v:%v", sg.label, c)
cidr_block = c
}
}

# ingress self (list with one or zero items)
dynamic "ingress" {
for_each = local.self
iterator = sg
content {
description = "${local.short_description}: from self"
from_port = 0
to_port = 0
protocol = -1
self = true
)]])
sg_sg = flatten([for i in try(local.sg.ingress_security_groups, []) : merge(local.sg, {
key = local.sg.name,
# label = format("%v:%v", local.sg.name, i)
label = i
security_group_name = i
}
}
)])
sg_pl = flatten([for sg in local.sg_c1 : [for plk, plv in data.aws_ec2_managed_prefix_list.ingress : merge(sg, {
prefix_list_label = format("%v:%v", sg.label, plk)
prefix_list_id = plv.id
}) if try(sg.prefix_list, null) == plk
]])
}
# egress all
egress {
description = "${local.short_description}: All"
from_port = 0
to_port = 0
protocol = -1
cidr_blocks = local.egress_networks
data "aws_ec2_managed_prefix_list" "ingress" {
for_each = toset(local.sg_ingress_prefix_lists)
filter {
name = "prefix-list-name"
values = [each.key]
}
}

# egress security group ids (all)
dynamic "egress" {
for_each = local.egress_sg
iterator = sg
content {
description = "${local.short_description}: ${local.egress_sg_names[sg]}"
from_port = 0
to_port = 0
protocol = -1
security_groups = [sg]
}
data "aws_ec2_managed_prefix_list" "egress" {
for_each = toset(local.sg_egress_prefix_lists)
filter {
name = "prefix-list-name"
values = [each.key]
}
}

# create group with just egress. Add all ingress via secondary resource
#resource "aws_security_group" "sg" {
resource "aws_security_group" "this_security_group" {
# for_each = { for sg in local.sg: sg.name => sg }
# name = format("%v-%v", var.name_prefix, each.key)
name = local.sg.name
# description = trimspace(format("%v %v", var.description_prefix, each.value.description))
description = trimspace(local.sg.description)
vpc_id = var.vpc_id

tags = merge(
# local.base_tags,
var.tags,
{
"Name" = "sg-${local.name}"
"boc:created_by" = "terraform"
"boc:tf_module_version" = local._module_version
"boc:vpc:info" = join(" ", compact([var.vpc_id, var.vpc_full_name]))
}
# { "Name" = format("sg-%v-%v", var.name_prefix, each.key) }
{ "Name" = format("sg-%v", local.sg.name) }
)
}

# egress: all
resource "aws_vpc_security_group_egress_rule" "all" {
# for_each = { for k, v in local.sg : k => aws_security_group.this_security_group[k].id }
# for_each = { for k, v in local.sg : k => aws_security_group.this_security_group.id }

security_group_id = aws_security_group.this_security_group.id
description = "ALL"
ip_protocol = -1
# cidr_block = local.egress_networks
cidr_ipv4 = local.n_all[0]
}


# ingress: self
resource "aws_vpc_security_group_ingress_rule" "self" {
for_each = try(local.sg.self, false) ? { (local.sg.name) = aws_security_group.this_security_group.id } : {}

security_group_id = each.value
description = "self"
ip_protocol = -1
referenced_security_group_id = each.value
}

# ingress: by security_group
resource "aws_vpc_security_group_ingress_rule" "security_group" {
for_each = { for x in local.sg_sg : x.label => x }

security_group_id = aws_security_group.this_security_group.id
description = "self"
ip_protocol = -1
referenced_security_group_id = aws_security_group.this_security_group.id
}

# ingress: by cidr_block
resource "aws_vpc_security_group_ingress_rule" "cidr_block" {
for_each = { for x in local.sg_cidr : x.cidr_label => x }

security_group_id = aws_security_group.this_security_group.id
description = each.value.short
from_port = each.value.from
to_port = each.value.to
ip_protocol = each.value.proto
cidr_ipv4 = each.value.cidr_block
}

# ingress: by prefix_list
resource "aws_vpc_security_group_ingress_rule" "prefix_lists" {
for_each = { for x in local.sg_pl : x.prefix_list_label => x }

security_group_id = aws_security_group.this_security_group.id
description = each.value.short
from_port = each.value.from
to_port = each.value.to
ip_protocol = each.value.proto
prefix_list_id = each.value.prefix_list_id
}
Loading