diff --git a/CHANGELOG.md b/CHANGELOG.md index b4a9417..f3bafbe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,15 @@ - custom - create custom submodule, requires port list passed +* v2.2.1 -- 20211022 + - custom + - add ingress_self_* option + +* v2.2.2 -- 20211025 + - custom + - make ingress_self stuff work + - fix missing default egress + # OLDER ## web diff --git a/common/README.md b/common/README.md index 6c851f6..5520593 100644 --- a/common/README.md +++ b/common/README.md @@ -30,11 +30,15 @@ No modules. | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| -| [egress\_networks](#input\_egress\_networks) | List of egress networks (with all pre-defined egress ports) | `list(string)` | `[]` | no | +| [egress\_networks](#input\_egress\_networks) | List of egress networks (with all pre-defined egress ports) (default: any) | `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 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` |
"0.0.0.0/0"
]
[| 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\_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 |
| [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 |
diff --git a/common/ports.tf b/common/ports.tf
index ebb8931..18d9795 100644
--- a/common/ports.tf
+++ b/common/ports.tf
@@ -1,37 +1,64 @@
-# ports = list of list of
-# from_port
-# to_port
-# proto
-# description
-# cidr_block
-# list of: all, external (more added as needed)
-
-# example only. Use your own values as appropraite
-
locals {
- 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"]
+ ports = []
- ports = [
- [80, 80, "tcp", "http", local.n_census, ["external"]],
- [443, 443, "tcp", "https", local.n_census, ["external"]],
- [8080, 8080, "tcp", "Tomcat-http", local.n_census, ["external"]],
- [8443, 8443, "tcp", "Tomcat-https", local.n_census, ["external"]],
- ]
+ ingress_networks = var.ingress_networks
+ egress_networks = var.egress_networks
- # ingress_networks = var.ingress_networks
- ingress_networks = []
- # egress_networks = var.egress_networks
- egress_networks = local.n_all
-
- # 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)]
+ # ports
+ p_fields = ["from", "to", "proto", "description", "cidr"]
+ p_list1 = length(local.ports) > 0 ? [for p in local.ports : zipmap(local.p_fields, p)] : []
+ p_list2 = length(var.ingress_port_list) > 0 ? [for p in var.ingress_port_list : zipmap(local.p_fields, p)] : []
+ p_list3 = length(var.ingress_port_map) > 0 ? var.ingress_port_map : []
+
+ port_map = {
+ "external" = []
+ "module_ports" = local.p_list1
+ "ingress_ports" = local.p_list2
+ "ingress_map" = local.p_list3
+ }
+
+ # self ports
+ p_self_fields = ["from", "to", "proto", "description"]
+ sp_list1 = length(var.ingress_self_port_list) > 0 ? [for p in var.ingress_self_port_list : zipmap(local.p_self_fields, p)] : []
+ sp_list2 = length(var.ingress_self_port_map) > 0 ? var.ingress_self_port_map : []
+ sp_list3 = length(var.ingress_self_port_list) == 0 && length(var.ingress_self_port_map) == 0 ? local._defaults["self_port_list"] : []
+
+ self_port_map = {
+ "ingress_ports" = local.sp_list1
+ "ingress_map" = local.sp_list2
+ "default" = local.sp_list3
}
}
+
+# locals {
+# 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"]
+#
+# ports = [
+# [80, 80, "tcp", "http", local.n_census, ["external"]],
+# [443, 443, "tcp", "https", local.n_census, ["external"]],
+# [8080, 8080, "tcp", "Tomcat-http", local.n_census, ["external"]],
+# [8443, 8443, "tcp", "Tomcat-https", local.n_census, ["external"]],
+# ]
+#
+# # ingress_networks = var.ingress_networks
+# ingress_networks = []
+# # egress_networks = var.egress_networks
+# egress_networks = local.n_all
+#
+# # 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/common/resources.tf b/common/resources.tf
index 41d3adb..d6ac551 100644
--- a/common/resources.tf
+++ b/common/resources.tf
@@ -3,7 +3,7 @@ locals {
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] : []
+ # self = var.enable_self ? local.self_ports : []
}
resource "aws_security_group" "this_security_group" {
@@ -11,6 +11,9 @@ resource "aws_security_group" "this_security_group" {
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"]
@@ -20,7 +23,46 @@ resource "aws_security_group" "this_security_group" {
from_port = p.value["from"]
to_port = p.value["to"]
protocol = p.value["proto"]
- cidr_blocks = length(p.value["cidr"]) == 0 ? flatten(compact(concat(local.external_ingress_networks, var.ingress_networks))) : flatten(compact(concat(p.value["cidr"], var.ingress_networks)))
+ 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_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))))
}
}
@@ -37,26 +79,58 @@ resource "aws_security_group" "this_security_group" {
}
}
- # ingress self (list with one or zero items)
+ #---
+ # 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 = local.self
+ for_each = var.enable_self ? local.self_port_map["default"] : []
iterator = sg
content {
- description = "${local.short_description}: from self"
- from_port = 0
- to_port = 0
- protocol = -1
+ description = "${local.short_description}: self ${sg.value["description"]}"
+ from_port = sg.value["from"]
+ to_port = sg.value["to"]
+ protocol = sg.value["proto"]
self = true
}
}
+ #---
+ # egress
+ #---
# egress all
egress {
description = "${local.short_description}: All"
from_port = 0
to_port = 0
protocol = -1
- cidr_blocks = flatten(compact(concat(local.egress_networks, var.egress_networks)))
+ cidr_blocks = distinct(flatten(compact(concat(local.egress_networks, var.egress_networks))))
}
# egress security group ids (all)
diff --git a/common/variables.common.tf b/common/variables.common.tf
index d001a04..f77bdcd 100644
--- a/common/variables.common.tf
+++ b/common/variables.common.tf
@@ -17,9 +17,9 @@ variable "ingress_networks" {
}
variable "egress_networks" {
- description = "List of egress networks (with all pre-defined egress ports)"
+ description = "List of egress networks (with all pre-defined egress ports) (default: any)"
type = list(string)
- default = []
+ default = ["0.0.0.0/0"]
}
variable "ingress_security_groups" {
diff --git a/common/variables.port_list.tf b/common/variables.port_list.tf
new file mode 100644
index 0000000..25b9d58
--- /dev/null
+++ b/common/variables.port_list.tf
@@ -0,0 +1,35 @@
+variable "ingress_port_list" {
+ description = "Ingress port list of 5-tuple: from, to, proto, description, and cidr(list)"
+ # type = list(tuple([number, number, any, string, list]))
+ default = [[]]
+}
+
+variable "ingress_port_map" {
+ description = "Ingress port list of objects: from, to, proto, description and cidr(list)"
+ type = list(object({
+ from = number
+ to = number
+ proto = any
+ description = string
+ cidr = list(string)
+ }))
+ default = []
+}
+
+variable "ingress_self_port_list" {
+ description = "Ingress port list of 4-tuple: from, to, proto, description"
+ # type = list(tuple([number, number, any, string]))
+ default = [[]]
+}
+
+variable "ingress_self_port_map" {
+ description = "Ingress self access port list of objects: from, to, proto, description"
+ type = list(object({
+ from = number
+ to = number
+ proto = any
+ description = string
+ }))
+ default = []
+}
+
diff --git a/common/version.tf b/common/version.tf
index d3e2658..548c682 100644
--- a/common/version.tf
+++ b/common/version.tf
@@ -1,3 +1,3 @@
locals {
- _module_version = "2.2.0"
+ _module_version = "2.2.2"
}
diff --git a/custom/README.md b/custom/README.md
index 5fb675f..14241a5 100644
--- a/custom/README.md
+++ b/custom/README.md
@@ -4,7 +4,10 @@ This describes how to use the aws-common-security-groups submodule for custom.
for the common security groups to a set of ports of your own doing.
You will need to provide a `ingress_port_list` list of the details, or a `ingress_port_map` which allows for a cleaner structure.
-This creates an egress rule permitting all outbound access.
+This creates an egress rule permitting all outbound access. If you provide both, it will combine the lists.
+
+You may also provide `ingress_self_port_list` and/or `ingress_self_port_map`, which contains the same fields
+as the `ingress_port_list` excluding the final `cidr` field. Again, if both are provided, they will be combined.
# Usage
## Port list
@@ -94,13 +97,15 @@ 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) | `list(string)` | `[]` | no |
+| [egress\_networks](#input\_egress\_networks) | List of egress networks (with all pre-defined egress ports) (default: any) | `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 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\_list](#input\_ingress\_port\_list) | Ingress port list of 5-tuple: from, to, proto, description, and cidr(list) | `list` |
"0.0.0.0/0"
]
[| 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\_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 |
| [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 |
diff --git a/custom/defaults.tf b/custom/defaults.tf
index d314d14..3488bba 100644
--- a/custom/defaults.tf
+++ b/custom/defaults.tf
@@ -3,5 +3,6 @@ locals {
name = "{{ name }}"
description = "Security group for application"
short_description = "SG"
+ self_port_list = [{ from = 0, to = 0, proto = -1, description = "all" }]
}
}
diff --git a/custom/main.tf b/custom/main.tf
index 751a270..e682c31 100644
--- a/custom/main.tf
+++ b/custom/main.tf
@@ -5,7 +5,10 @@
* for the common security groups to a set of ports of your own doing.
*
* You will need to provide a `ingress_port_list` list of the details, or a `ingress_port_map` which allows for a cleaner structure.
-* This creates an egress rule permitting all outbound access.
+* This creates an egress rule permitting all outbound access. If you provide both, it will combine the lists.
+*
+* You may also provide `ingress_self_port_list` and/or `ingress_self_port_map`, which contains the same fields
+* as the `ingress_port_list` excluding the final `cidr` field. Again, if both are provided, they will be combined.
*
* # Usage
* ## Port list
diff --git a/custom/ports.tf b/custom/ports.tf
index 554dbd1..06a2067 100644
--- a/custom/ports.tf
+++ b/custom/ports.tf
@@ -1,14 +1,34 @@
locals {
- ports = var.ingress_port_list
+ ports = []
ingress_networks = var.ingress_networks
egress_networks = var.egress_networks
- # these are ignored
ingress_sg = var.ingress_security_groups
egress_sg = var.egress_security_groups
+ # ports
p_fields = ["from", "to", "proto", "description", "cidr"]
- p_map = length(var.ingress_port_list) > 0 ? [for p in local.ports : zipmap(local.p_fields, p)] : var.ingress_port_map
- port_map = { "external" = local.p_map }
+ p_list1 = length(local.ports) > 0 ? [for p in local.ports : zipmap(local.p_fields, p)] : []
+ p_list2 = length(var.ingress_port_list) > 0 ? [for p in var.ingress_port_list : zipmap(local.p_fields, p)] : []
+ p_list3 = length(var.ingress_port_map) > 0 ? var.ingress_port_map : []
+
+ port_map = {
+ "external" = []
+ "module_ports" = local.p_list1
+ "ingress_ports" = local.p_list2
+ "ingress_map" = local.p_list3
+ }
+
+ # self ports
+ p_self_fields = ["from", "to", "proto", "description"]
+ sp_list1 = length(var.ingress_self_port_list) > 0 ? [for p in var.ingress_self_port_list : zipmap(local.p_self_fields, p)] : []
+ sp_list2 = length(var.ingress_self_port_map) > 0 ? var.ingress_self_port_map : []
+ sp_list3 = length(var.ingress_self_port_list) == 0 && length(var.ingress_self_port_map) == 0 ? local._defaults["self_port_list"] : []
+
+ self_port_map = {
+ "ingress_ports" = local.sp_list1
+ "ingress_map" = local.sp_list2
+ "default" = local.sp_list3
+ }
}
diff --git a/custom/variables.port_list.tf b/custom/variables.port_list.tf
new file mode 120000
index 0000000..d95b5f4
--- /dev/null
+++ b/custom/variables.port_list.tf
@@ -0,0 +1 @@
+../common/variables.port_list.tf
\ No newline at end of file
diff --git a/custom/variables.tf b/custom/variables.tf
index 4297e14..408b982 100644
--- a/custom/variables.tf
+++ b/custom/variables.tf
@@ -14,23 +14,3 @@ variable "short_description" {
type = string
default = ""
}
-
-
-variable "ingress_port_list" {
- description = "Ingress port list of 5-tuple: from, to, proto, description, and cidr(list)"
- # type = list(tuple([number, number, any, string, list]))
- default = []
-}
-
-variable "ingress_port_map" {
- description = "Ingress port list of objects: from, to, proto, description and cidr(list)"
- type = list(object({
- from = number
- to = number
- proto = any
- description = string
- cidr = list(string)
- }))
- default = []
-}
-
diff --git a/sas/README.md b/sas/README.md
index 6881ff9..5f237db 100644
--- a/sas/README.md
+++ b/sas/README.md
@@ -100,11 +100,15 @@ 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) | `list(string)` | `[]` | no |
+| [egress\_networks](#input\_egress\_networks) | List of egress networks (with all pre-defined egress ports) (default: any) | `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 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` |
"0.0.0.0/0"
]
[| 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\_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 |
| [name](#input\_name) | Security Group Name | `string` | `""` | no |
| [short\_description](#input\_short\_description) | Security Group Short Description | `string` | `""` | no |
| [tags](#input\_tags) | Extra security group tags | `map` | `{}` | no |
diff --git a/sas/ports.tf b/sas/ports.tf
index 9dd888d..a554cbf 100644
--- a/sas/ports.tf
+++ b/sas/ports.tf
@@ -36,13 +36,31 @@ locals {
ingress_networks = var.ingress_networks
egress_networks = 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)]
+ # ports
+ p_fields = ["from", "to", "proto", "description", "cidr"]
+ p_list1 = length(local.ports) > 0 ? [for p in local.ports : zipmap(local.p_fields, p)] : []
+ p_list2 = length(var.ingress_port_list) > 0 ? [for p in var.ingress_port_list : zipmap(local.p_fields, p)] : []
+ p_list3 = length(var.ingress_port_map) > 0 ? var.ingress_port_map : []
+
+ port_map = {
+ "external" = []
+ "module_ports" = local.p_list1
+ "ingress_ports" = local.p_list2
+ "ingress_map" = local.p_list3
+ }
+
+ # self ports
+ p_self_fields = ["from", "to", "proto", "description"]
+ sp_list1 = length(var.ingress_self_port_list) > 0 ? [for p in var.ingress_self_port_list : zipmap(local.p_self_fields, p)] : []
+ sp_list2 = length(var.ingress_self_port_map) > 0 ? var.ingress_self_port_map : []
+ sp_list3 = length(var.ingress_self_port_list) == 0 && length(var.ingress_self_port_map) == 0 ? local._defaults["self_port_list"] : []
+
+ self_port_map = {
+ "ingress_ports" = local.sp_list1
+ "ingress_map" = local.sp_list2
+ "default" = local.sp_list3
}
}
diff --git a/sas/variables.port_list.tf b/sas/variables.port_list.tf
new file mode 120000
index 0000000..d95b5f4
--- /dev/null
+++ b/sas/variables.port_list.tf
@@ -0,0 +1 @@
+../common/variables.port_list.tf
\ No newline at end of file