diff --git a/common/README.md b/common/README.md index e3e1098..16f8b4c 100644 --- a/common/README.md +++ b/common/README.md @@ -45,7 +45,7 @@ No modules. | [ingress\_security\_groups](#input\_ingress\_security\_groups) | List of ingress security groups for all ports | `list(string)` | `[]` | no | | [ingress\_self\_port\_list](#input\_ingress\_self\_port\_list) | Ingress port list of 4-tuple: from, to, proto, description | `list` | `[]` | no | | [ingress\_self\_port\_map](#input\_ingress\_self\_port\_map) | Ingress self access port list of objects: from, to, proto, description |
list(object({
from = number
to = number
proto = any
description = string
}))
| `[]` | no | -| [tags](#input\_tags) | Extra security group tags | `map` | `{}` | no | +| [tags](#input\_tags) | Extra security group tags | `map(any)` | `{}` | 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 | diff --git a/common/variables.common.tf b/common/variables.common.tf index 1464ab7..53222d8 100644 --- a/common/variables.common.tf +++ b/common/variables.common.tf @@ -36,7 +36,7 @@ variable "egress_security_groups" { variable "tags" { description = "Extra security group tags" - type = map + type = map(any) default = {} } diff --git a/custom/README.md b/custom/README.md index 8989373..81737ed 100644 --- a/custom/README.md +++ b/custom/README.md @@ -104,13 +104,14 @@ module "sg_test" { | Name | Version | |------|---------| -| [terraform](#requirement\_terraform) | >= 0.12 | +| [terraform](#requirement\_terraform) | >= 1.0.0 | +| [aws](#requirement\_aws) | >= 5.0 | ## Providers | Name | Version | |------|---------| -| [aws](#provider\_aws) | n/a | +| [aws](#provider\_aws) | >= 5.0 | ## Modules @@ -123,6 +124,8 @@ No modules. | [aws_security_group.this_security_group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group) | 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_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 | @@ -133,19 +136,23 @@ No modules. | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| | [description](#input\_description) | Security Group Description | `string` | `""` | no | -| [egress\_networks](#input\_egress\_networks) | List of egress networks (with all pre-defined egress ports) (default: any) | `list(string)` |
[
"0.0.0.0/0"
]
| no | +| [egress\_networks](#input\_egress\_networks) | List of egress networks (with all pre-defined egress ports) (default: any) | `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\_prefix\_list\_ports](#input\_egress\_prefix\_list\_ports) | List of port objects (from,to,proto,label) for egress prefix lists |
list(object({
from = number
to = number
proto = optional(string, "tcp")
label = optional(string)
}))
|
[
{
"from": 0,
"label": "all",
"proto": -1,
"to": 0
}
]
| no | | [egress\_security\_groups](#input\_egress\_security\_groups) | List of egress security groups (all ports) | `list(string)` | `[]` | no | | [enable\_default\_egress](#input\_enable\_default\_egress) | Enable\|Disable default egress of ALL | `bool` | `true` | no | | [enable\_self](#input\_enable\_self) | Enable\|Disable self full access | `bool` | `false` | no | | [ingress\_networks](#input\_ingress\_networks) | List of ingress networks for access (with all pre-defined ingress ports) | `list(string)` | `[]` | no | | [ingress\_port\_list](#input\_ingress\_port\_list) | Ingress port list of 5-tuple: from, to, proto, description, and cidr(list) | `list` | `[]` | no | -| [ingress\_port\_map](#input\_ingress\_port\_map) | Ingress port list of objects: from, to, proto, description and cidr(list) |
list(object({
from = number
to = number
proto = any
description = string
cidr = list(string)
}))
| `[]` | no | +| [ingress\_port\_map](#input\_ingress\_port\_map) | Ingress port list of objects: from, to, proto, description and cidr(list) |
list(object({
from = number
to = number
proto = any
description = string
cidr = list(string)
}))
| `[]` | no | +| [ingress\_prefix\_list\_names](#input\_ingress\_prefix\_list\_names) | List of prefix list names for ingress access | `list(string)` | `[]` | no | +| [ingress\_prefix\_list\_ports](#input\_ingress\_prefix\_list\_ports) | List of port objects (from,to,proto,label) for ingress prefix lists |
list(object({
from = number
to = number
proto = optional(string, "tcp")
label = optional(string)
}))
| `[]` | no | | [ingress\_security\_groups](#input\_ingress\_security\_groups) | List of ingress security groups for all ports | `list(string)` | `[]` | no | | [ingress\_self\_port\_list](#input\_ingress\_self\_port\_list) | Ingress port list of 4-tuple: from, to, proto, description | `list` | `[]` | no | -| [ingress\_self\_port\_map](#input\_ingress\_self\_port\_map) | Ingress self access port list of objects: from, to, proto, description |
list(object({
from = number
to = number
proto = any
description = string
}))
| `[]` | no | +| [ingress\_self\_port\_map](#input\_ingress\_self\_port\_map) | Ingress self access port list of objects: from, to, proto, description |
list(object({
from = number
to = number
proto = any
description = string
}))
| `[]` | no | | [name](#input\_name) | Security Group Name (required) | `string` | n/a | yes | | [short\_description](#input\_short\_description) | Security Group Short Description | `string` | `""` | no | -| [tags](#input\_tags) | Extra security group tags | `map` | `{}` | no | +| [tags](#input\_tags) | Extra security group tags | `map(any)` | `{}` | 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 | diff --git a/custom/custom.tf b/custom/custom.tf new file mode 100644 index 0000000..1eed1d4 --- /dev/null +++ b/custom/custom.tf @@ -0,0 +1,185 @@ +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 ? local.self_ports : [] +} + +resource "aws_security_group" "this_security_group" { + name = local.name + description = var.description + vpc_id = var.vpc_id + + #--- + # ingress + #--- + # 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 ? distinct(flatten(compact(concat(local.external_ingress_networks, var.ingress_networks)))) : distinct(flatten(compact(concat(p.value["cidr"], var.ingress_networks)))) + } + } + + # ingress module-defined ports + dynamic "ingress" { + for_each = local.port_map["module_ports"] + 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 ? distinct(flatten(compact(concat(local.external_ingress_networks, var.ingress_networks)))) : distinct(flatten(compact(concat(p.value["cidr"], var.ingress_networks)))) + } + } + + # ingress_ports + dynamic "ingress" { + for_each = local.port_map["ingress_ports"] + 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 ? distinct(flatten(compact(concat(local.external_ingress_networks, var.ingress_networks)))) : distinct(flatten(compact(concat(p.value["cidr"], var.ingress_networks)))) + } + } + + # ingress map + dynamic "ingress" { + for_each = local.port_map["ingress_map"] + 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 ? distinct(flatten(compact(concat(local.external_ingress_networks, var.ingress_networks)))) : distinct(flatten(compact(concat(p.value["cidr"], var.ingress_networks)))) + } + } + + # 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] + } + } + + #--- + # ingress self + #--- + # ingress self port list + dynamic "ingress" { + for_each = var.enable_self ? local.self_port_map["ingress_ports"] : [] + iterator = sg + content { + description = "${local.short_description}: self ${sg.value["description"]}" + from_port = sg.value["from"] + to_port = sg.value["to"] + protocol = sg.value["proto"] + self = true + } + } + + # ingress self port map + dynamic "ingress" { + for_each = var.enable_self ? local.self_port_map["ingress_map"] : [] + iterator = sg + content { + description = "${local.short_description}: self ${sg.value["description"]}" + from_port = sg.value["from"] + to_port = sg.value["to"] + protocol = sg.value["proto"] + self = true + } + } + + # ingress self port default + dynamic "ingress" { + for_each = var.enable_self ? local.self_port_map["default"] : [] + iterator = sg + content { + description = "${local.short_description}: self ${sg.value["description"]}" + from_port = sg.value["from"] + to_port = sg.value["to"] + protocol = sg.value["proto"] + self = true + } + } + + # inress with prefix lists + dynamic "ingress" { + for_each = length(var.ingress_prefix_list_names) && length(var.ingress_prefix_list_ports) > 0 ? toset(var.ingress_prefix_list_ports) : toset([]) + iterator = p + content { + description = try(p.value.label, local.short_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.inress : pl.id] + } + } + + # egress all (with flag enable_default_egress) + dynamic "egress" { + for_each = var.enable_default_egress ? [1] : [] + iterator = sg + content { + description = "${local.short_description}: All" + from_port = 0 + to_port = 0 + protocol = -1 + cidr_blocks = distinct(flatten(compact(concat(local.egress_networks, var.egress_networks)))) + } + } + + # 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] + } + } + + # egress with prefix lists + dynamic "egress" { + for_each = length(var.egress_prefix_list_names) && length(var.egress_prefix_list_ports) > 0 ? toset(var.egress_prefix_list_ports) : toset([]) + iterator = p + content { + description = try(p.value.label, local.short_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.egress : pl.id] + } + } + + tags = merge( + 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])) + } + ) +} diff --git a/custom/data.prefix_lists.tf b/custom/data.prefix_lists.tf new file mode 120000 index 0000000..08df656 --- /dev/null +++ b/custom/data.prefix_lists.tf @@ -0,0 +1 @@ +../common/data.prefix_lists.tf \ No newline at end of file diff --git a/custom/resources.tf b/custom/resources.tf deleted file mode 120000 index 6dd8c84..0000000 --- a/custom/resources.tf +++ /dev/null @@ -1 +0,0 @@ -../common/resources.tf \ No newline at end of file diff --git a/custom/settings.tf b/custom/settings.tf index ffe1549..f8f933b 100644 --- a/custom/settings.tf +++ b/custom/settings.tf @@ -1,7 +1,7 @@ locals { name = var.name != "" ? var.name : local._defaults["name"] is_modular = var.name == "" || length(regexall("^m-", var.name)) > 0 - enable_self = var.enable_self ? ! local.is_modular : false + enable_self = var.enable_self ? !local.is_modular : false description = var.description != "" ? var.description : local._defaults["description"] short_description = var.short_description != "" ? var.short_description : local._defaults["short_description"] } diff --git a/custom/variables.prefix_lists.tf b/custom/variables.prefix_lists.tf new file mode 120000 index 0000000..86cbd3c --- /dev/null +++ b/custom/variables.prefix_lists.tf @@ -0,0 +1 @@ +../common/variables.prefix_lists.tf \ No newline at end of file diff --git a/custom/variables.prefix_lists_ports.tf b/custom/variables.prefix_lists_ports.tf new file mode 100644 index 0000000..b3063dc --- /dev/null +++ b/custom/variables.prefix_lists_ports.tf @@ -0,0 +1,22 @@ +variable "ingress_prefix_list_ports" { + description = "List of port objects (from,to,proto,label) for ingress prefix lists" + type = list(object({ + from = number + to = number + proto = optional(string, "tcp") + label = optional(string) + })) + default = [] +} + +variable "egress_prefix_list_ports" { + description = "List of port objects (from,to,proto,label) for egress prefix lists" + type = list(object({ + from = number + to = number + proto = optional(string, "tcp") + label = optional(string) + })) + default = [{ from = 0, to = 0, proto = -1, label = "all" }] +} +