diff --git a/nacl-rules/test/defaults.tf b/nacl-rules/test/defaults.tf new file mode 100644 index 0000000..9f6ec12 --- /dev/null +++ b/nacl-rules/test/defaults.tf @@ -0,0 +1,47 @@ +# for the accesss logs for load balancers +# https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-access-logs.html#access-logging-bucket-permissions + +locals { + _defaults = { + "load-balancer" = { + "gov" = ["190560391635", "048591011584"] + "us-gov-east-1" = "190560391635" + "us-gov-west-1" = "048591011584" + + "ew" = ["127311923021", "033677994240", "027434742980", "797873946194"] + "us-east-1" = "127311923021" + "us-east-2" = "033677994240" + "us-west-1" = "027434742980" + "us-west-2" = "797873946194" + } + "ses" = { + "event_types" = ["bounce", "delivery", "complaint"] + } + #--- + # description = "Map of all rules where each entry is a tuple of: [from_port, to_port, egress, protocol, action, description]" + # type = map(tuple([number, number, bool, string, string, string])) + #--- + "nacl_all_rules" = { + # basic outbounds + ephemeral_outbound = [1024, 65535, true, "tcp", "allow", "ephemeral-outbound"] + all_outbound = [0, 0, true, "all", "allow", "all-outbound"] + + # basic inbounds + all_inbound = [0, 0, false, "all", "allow", "all-inbound"] + http_inbound = [80, 80, false, "tcp", "allow", "http-inbound"] + https_inbound = [443, 443, false, "tcp", "allow", "https-inbound"] + ssh_inbound = [22, 22, false, "tcp", "allow", "https-inbound"] + } + #--- + # vpc varies by specific VPC cidr block, this will be merged with the actual vpc CIDR + #--- + "nacl_all_cidr_blocks" = { + "all" = ["0.0.0.0/0"] + "enterprise" = ["148.129.0.0/16", "172.16.0.0/12", "192.168.0.0/16"] + "vpc" = [] + "endpoints" = [] + "additional" = [] + "peers" = [] + } + } +} diff --git a/nacl-rules/test/main.tf b/nacl-rules/test/main.tf new file mode 100644 index 0000000..5995c77 --- /dev/null +++ b/nacl-rules/test/main.tf @@ -0,0 +1,236 @@ +/* +* # About aws-vpc-setup :: nacl-rules +* +* This submodule creates network access control lists rules (nacls). The submodule nacls sets up the network +* acl and should be called first. +* +* # Usage +* +* ```hcl +* module "nacl-rules" { +* source = "git@github.e.it.census.gov:terraform-modules/aws-vpc-setup.git//nacl-rules" +* network_acl_id = module.nacls.private_network_acl +* +* rule_description = "Enterprise plus VPC" +* rule_definitions = {} +* named_cidr_blocks = [ "enterprise", "vpc", "other" ] +* merge_cidr_blocks = { +* "vpc" = var.vpc_cidr +* "other" = [] +* } +* rules = [ "all_inbound", "all_outbound" ] +* rule_number = 1000 +* rule_increment = 10 +* +* tags = {} = +* } +*/ + +locals { + # account_id = var.account_id != "" ? var.account_id : data.aws_caller_identity.current.account_id + # account_environment = data.aws_arn.current.partition == "aws-us-gov" ? "gov" : "ew" + + # base_tags = { + # "boc:tf_module_version" = local._module_version + # "boc:created_by" = "terraform" + # } + + # availability_zones = length(var.availability_zones) != 0 ? var.availability_zones : data.aws_availability_zones.zones.names + # az_count = length(local.availability_zones) + # az_count_list = range(local.az_count) + # az_list = toset(local.availability_zones) + # empty = toset([]) +} + +## locals { +## private_all = compact(concat(var.network_census, var.network_peers, list(var.vpc_cidr_block))) +## private_all_start = 1000 +## # endpoint = ["52.216.0.0/15", "54.231.0.0/17"] +## endpoint = [] +## endpoint_start = 2000 +## public_nat = "0.0.0.0/0" +## public_nat_start = 3000 +## public_nat_ports = [80, 443] +## } +## +## # IN +## resource "aws_network_acl_rule" "in_private_all" { +## count = length(local.private_all) +## network_acl_id = aws_network_acl.private.id +## rule_number = local.private_all_start + count.index * 10 +## egress = false +## protocol = "all" +## rule_action = "allow" +## from_port = 0 +## to_port = 0 +## cidr_block = local.private_all[count.index] +## } +## +## resource "aws_network_acl_rule" "in_endpoint" { +## count = length(local.endpoint) +## network_acl_id = aws_network_acl.private.id +## rule_number = local.endpoint_start + count.index * 10 +## egress = false +## protocol = "tcp" +## rule_action = "allow" +## from_port = 1024 +## to_port = 65535 +## cidr_block = local.endpoint[count.index] +## } +## +## resource "aws_network_acl_rule" "in_private_nat" { +## network_acl_id = aws_network_acl.private.id +## rule_number = local.public_nat_start +## egress = false +## protocol = "tcp" +## rule_action = "allow" +## from_port = 1024 +## to_port = 65535 +## cidr_block = local.public_nat +## } +## +## # OUT +## resource "aws_network_acl_rule" "out_private_all" { +## count = length(local.private_all) +## network_acl_id = aws_network_acl.private.id +## rule_number = local.private_all_start + count.index * 10 +## egress = true +## protocol = "all" +## rule_action = "allow" +## from_port = 0 +## to_port = 0 +## cidr_block = local.private_all[count.index] +## } +## +## resource "aws_network_acl_rule" "out_endpoint" { +## count = length(local.endpoint) +## network_acl_id = aws_network_acl.private.id +## rule_number = local.endpoint_start + count.index * 10 +## egress = true +## protocol = "tcp" +## rule_action = "allow" +## from_port = 443 +## to_port = 443 +## cidr_block = local.endpoint[count.index] +## } +## +## resource "aws_network_acl_rule" "out_private_nat" { +## count = length(local.public_nat_ports) +## network_acl_id = aws_network_acl.private.id +## rule_number = local.public_nat_start + count.index * 10 +## egress = true +## protocol = "tcp" +## rule_action = "allow" +## from_port = local.public_nat_ports[count.index] +## to_port = local.public_nat_ports[count.index] +## cidr_block = local.public_nat +## } + +## resource "aws_network_acl_rule" "in_nat" { +## network_acl_id = aws_network_acl.public.id +## rule_number = local.public_nat_start +## egress = false +## protocol = "tcp" +## rule_action = "allow" +## from_port = 1024 +## to_port = 65535 +## cidr_block = local.public_nat +## } +## +## resource "aws_network_acl_rule" "in_nat_vpc" { +## count = length(local.public_nat_ports) +## network_acl_id = aws_network_acl.public.id +## rule_number = aws_network_acl_rule.in_nat.rule_number + 10 + count.index * 10 +## egress = false +## protocol = "tcp" +## rule_action = "allow" +## from_port = local.public_nat_ports[count.index] +## to_port = local.public_nat_ports[count.index] +## cidr_block = var.vpc_cidr_block +## depends_on = [aws_network_acl_rule.in_nat] +## } +## +## resource "aws_network_acl_rule" "out_nat" { +## count = length(local.public_nat_ports) +## network_acl_id = aws_network_acl.public.id +## rule_number = local.public_nat_start + count.index * 10 +## egress = true +## protocol = "tcp" +## rule_action = "allow" +## from_port = local.public_nat_ports[count.index] +## to_port = local.public_nat_ports[count.index] +## cidr_block = local.public_nat +## } +## +## resource "aws_network_acl_rule" "out_nat_vpc" { +## count = 1 +## network_acl_id = aws_network_acl.public.id +## rule_number = local.public_nat_start + 100 + count.index * 10 +## egress = true +## protocol = "tcp" +## rule_action = "allow" +## from_port = 1024 +## to_port = 65535 +## cidr_block = var.vpc_cidr_block +## } +## +## + + +# # main.tf +# module "clients-acl-rule" { +# source = "modules/acl" +# +# network_acl_id = "${aws_network_acl.public-acl.id}" +# +# all_acl_rules = "${var.acl_rules}" +# cidrs = "${var.cidr_blocks["clients"]}" +# rules = ["http_inbound", "https_inbound", "ephemeral_outbound"] +# rule_number = 20 +# } +# +# setproduct(var.cidrs,var.rules) + +## variable "network_acl_id" { +## variable "rule_definitions" { +## variable "cidr_blocks" { +## variable "rules" { +## variable "rule_number" { +## variable "rule_increment" { + +locals { + cb1 = local._defaults["nacl_all_cidr_blocks"] + cb2 = { for k, v in var.merge_cidr_blocks : k => flatten(concat(lookup(local.cb1, k, []), v)) } + cb3 = merge(local.cb1, local.cb2) + + cidr_blocks = flatten([for c in var.named_cidr_blocks : lookup(local.cb3, c, [])]) + + rules = ["http_inbound", "https_inbound", "all_inbound"] + rule_definitions = local._defaults["nacl_all_rules"] + rule_number = 1000 + rule_increment = var.rule_increment + + r1 = setproduct(local.cidr_blocks, local.rules) + r2 = [for p in local.r1 : { + label = format("%v%%%v", p[0], p[1]) + cidr = p[0] + rule_label = p[1] + description = local.rule_definitions[p[1]][4] + from_port = local.rule_definitions[p[1]][0] + to_port = local.rule_definitions[p[1]][1] + egress = local.rule_definitions[p[1]][2] + protocol = local.rule_definitions[p[1]][3] + action = local.rule_definitions[p[1]][3] + rule_number = local.rule_number } + ] + r3 = [for i in range(length(local.r2)) : + merge( + local.r2[i], + tomap({ rule_number = local.r2[i].rule_number + i * local.rule_increment }), + ) + ] + r4 = [for v in local.r3 : v.rule_number] + r5 = length(local.r4) > 0 ? max(local.r4...) : null +} + + diff --git a/nacl-rules/test/outputs.tf b/nacl-rules/test/outputs.tf new file mode 100644 index 0000000..b9f20f4 --- /dev/null +++ b/nacl-rules/test/outputs.tf @@ -0,0 +1,12 @@ +output "nacl_rules_info" { + description = "Information about NACL Rules" + value = { + description = var.description + rule_count = length(local.r4) + last_rule_number = local.r5 + first_rule_number = local.rule_number + rule_increment = local.rule_increment + cidrs = local.cidr_blocks + rules = local.rules + } +} diff --git a/nacl-rules/test/variables.tf b/nacl-rules/test/variables.tf new file mode 100644 index 0000000..52357fb --- /dev/null +++ b/nacl-rules/test/variables.tf @@ -0,0 +1,82 @@ +# # main.tf +# module "clients-acl-rule" { +# source = "modules/acl" +# +# network_acl_id = "${aws_network_acl.public-acl.id}" +# +# all_acl_rules = "${var.acl_rules}" +# cidrs = "${var.cidr_blocks["clients"]}" +# rules = ["http_inbound", "https_inbound", "ephemeral_outbound"] +# rule_number = 20 +# } +# +# setproduct(var.cidrs,var.rules) + +variable "network_acl_id" { + description = "Network ACL ID to which to apply the rules" + type = string +} + +variable "vpc_cidr_block" { + description = "VPC CIDR Block" + type = string + default = "" +} + +variable "rule_description" { + description = "Text describing purpose of rule set" + type = string + default = "" +} + +/* +* from_port = number (0 for all) +* to_port = number (0 for all) +* egress = true | false +* protocol = "all" | "tcp" | "udp" | "icmp" +* action = "allow" | "deny" +* description = text-string +* +* example: http_inbound = [80,80,false,"tcp","allow","http-inbound"] +*/ +variable "rule_definitions" { + description = "Map of rule port/proto definitions (default uses built-in all_rules)" + type = map(tuple([number, number, bool, string, string, string])) + default = {} +} + +variable "cidr_blocks" { + description = "List of CIDR blocks for selected rules" + type = list(string) + default = [] +} + +variable "named_cidr_blocks" { + description = "List of CIDR block names from defaults for selected rules: (all, enterprise, vpc, ...)" + type = list(string) + default = [] +} + +variable "merge_cidr_blocks" { + description = "Map of names to list of CIDR blocks" + type = map(list(string)) + default = {} +} + +variable "rules" { + description = "Selected rule definitions from rule_definitions or all_rules (default: null)" + type = list(string) + default = [] +} + +variable "rule_number" { + description = "Starting rule number within the rule" + type = number + default = null +} + +variable "rule_increment" { + description = "Rule number increment per new CIDR block" + type = number + default = 10 +} diff --git a/nacl-rules/test/x b/nacl-rules/test/x new file mode 100644 index 0000000..c566ee6 --- /dev/null +++ b/nacl-rules/test/x @@ -0,0 +1,264 @@ +local.r1 +[ + [ + "148.129.0.0/16", + "http_inbound", + ], + [ + "148.129.0.0/16", + "https_inbound", + ], + [ + "148.129.0.0/16", + "all_inbound", + ], + [ + "172.16.0.0/12", + "http_inbound", + ], + [ + "172.16.0.0/12", + "https_inbound", + ], + [ + "172.16.0.0/12", + "all_inbound", + ], + [ + "192.168.0.0/16", + "http_inbound", + ], + [ + "192.168.0.0/16", + "https_inbound", + ], + [ + "192.168.0.0/16", + "all_inbound", + ], +] + +local.r2 +[ + { + "action" = "tcp" + "cidr" = "148.129.0.0/16" + "description" = "allow" + "egress" = false + "from_port" = 80 + "label" = "148.129.0.0/16%http_inbound" + "protocol" = "tcp" + "rule_label" = "http_inbound" + "rule_number" = 1000 + "to_port" = 80 + }, + { + "action" = "tcp" + "cidr" = "148.129.0.0/16" + "description" = "allow" + "egress" = false + "from_port" = 443 + "label" = "148.129.0.0/16%https_inbound" + "protocol" = "tcp" + "rule_label" = "https_inbound" + "rule_number" = 1000 + "to_port" = 443 + }, + { + "action" = "all" + "cidr" = "148.129.0.0/16" + "description" = "allow" + "egress" = false + "from_port" = 0 + "label" = "148.129.0.0/16%all_inbound" + "protocol" = "all" + "rule_label" = "all_inbound" + "rule_number" = 1000 + "to_port" = 0 + }, + { + "action" = "tcp" + "cidr" = "172.16.0.0/12" + "description" = "allow" + "egress" = false + "from_port" = 80 + "label" = "172.16.0.0/12%http_inbound" + "protocol" = "tcp" + "rule_label" = "http_inbound" + "rule_number" = 1000 + "to_port" = 80 + }, + { + "action" = "tcp" + "cidr" = "172.16.0.0/12" + "description" = "allow" + "egress" = false + "from_port" = 443 + "label" = "172.16.0.0/12%https_inbound" + "protocol" = "tcp" + "rule_label" = "https_inbound" + "rule_number" = 1000 + "to_port" = 443 + }, + { + "action" = "all" + "cidr" = "172.16.0.0/12" + "description" = "allow" + "egress" = false + "from_port" = 0 + "label" = "172.16.0.0/12%all_inbound" + "protocol" = "all" + "rule_label" = "all_inbound" + "rule_number" = 1000 + "to_port" = 0 + }, + { + "action" = "tcp" + "cidr" = "192.168.0.0/16" + "description" = "allow" + "egress" = false + "from_port" = 80 + "label" = "192.168.0.0/16%http_inbound" + "protocol" = "tcp" + "rule_label" = "http_inbound" + "rule_number" = 1000 + "to_port" = 80 + }, + { + "action" = "tcp" + "cidr" = "192.168.0.0/16" + "description" = "allow" + "egress" = false + "from_port" = 443 + "label" = "192.168.0.0/16%https_inbound" + "protocol" = "tcp" + "rule_label" = "https_inbound" + "rule_number" = 1000 + "to_port" = 443 + }, + { + "action" = "all" + "cidr" = "192.168.0.0/16" + "description" = "allow" + "egress" = false + "from_port" = 0 + "label" = "192.168.0.0/16%all_inbound" + "protocol" = "all" + "rule_label" = "all_inbound" + "rule_number" = 1000 + "to_port" = 0 + }, +] + +local.r3 +[ + { + "action" = "tcp" + "cidr" = "148.129.0.0/16" + "description" = "allow" + "egress" = false + "from_port" = 80 + "label" = "148.129.0.0/16%http_inbound" + "protocol" = "tcp" + "rule_label" = "http_inbound" + "rule_number" = 1000 + "to_port" = 80 + }, + { + "action" = "tcp" + "cidr" = "148.129.0.0/16" + "description" = "allow" + "egress" = false + "from_port" = 443 + "label" = "148.129.0.0/16%https_inbound" + "protocol" = "tcp" + "rule_label" = "https_inbound" + "rule_number" = 1010 + "to_port" = 443 + }, + { + "action" = "all" + "cidr" = "148.129.0.0/16" + "description" = "allow" + "egress" = false + "from_port" = 0 + "label" = "148.129.0.0/16%all_inbound" + "protocol" = "all" + "rule_label" = "all_inbound" + "rule_number" = 1020 + "to_port" = 0 + }, + { + "action" = "tcp" + "cidr" = "172.16.0.0/12" + "description" = "allow" + "egress" = false + "from_port" = 80 + "label" = "172.16.0.0/12%http_inbound" + "protocol" = "tcp" + "rule_label" = "http_inbound" + "rule_number" = 1030 + "to_port" = 80 + }, + { + "action" = "tcp" + "cidr" = "172.16.0.0/12" + "description" = "allow" + "egress" = false + "from_port" = 443 + "label" = "172.16.0.0/12%https_inbound" + "protocol" = "tcp" + "rule_label" = "https_inbound" + "rule_number" = 1040 + "to_port" = 443 + }, + { + "action" = "all" + "cidr" = "172.16.0.0/12" + "description" = "allow" + "egress" = false + "from_port" = 0 + "label" = "172.16.0.0/12%all_inbound" + "protocol" = "all" + "rule_label" = "all_inbound" + "rule_number" = 1050 + "to_port" = 0 + }, + { + "action" = "tcp" + "cidr" = "192.168.0.0/16" + "description" = "allow" + "egress" = false + "from_port" = 80 + "label" = "192.168.0.0/16%http_inbound" + "protocol" = "tcp" + "rule_label" = "http_inbound" + "rule_number" = 1060 + "to_port" = 80 + }, + { + "action" = "tcp" + "cidr" = "192.168.0.0/16" + "description" = "allow" + "egress" = false + "from_port" = 443 + "label" = "192.168.0.0/16%https_inbound" + "protocol" = "tcp" + "rule_label" = "https_inbound" + "rule_number" = 1070 + "to_port" = 443 + }, + { + "action" = "all" + "cidr" = "192.168.0.0/16" + "description" = "allow" + "egress" = false + "from_port" = 0 + "label" = "192.168.0.0/16%all_inbound" + "protocol" = "all" + "rule_label" = "all_inbound" + "rule_number" = 1080 + "to_port" = 0 + }, +] +