From 3c687ae0458df11ccf16dc63145eb7b96d50592b Mon Sep 17 00:00:00 2001 From: Maximilian Schlenz Date: Mon, 14 Jul 2025 15:31:31 +0200 Subject: [PATCH] sec group nested in network --- example/main.tf | 18 +++ example/providers.tf | 16 +++ example/terraform.tfvars | 188 ++++++++++++++++++++++++++ example/variables.tf | 147 ++++++++++++++++++++ project/main.tf | 105 ++++++++++---- project/output.tf | 0 project/{provider.tf => providers.tf} | 5 +- project/sna.tf | 27 ---- project/variables.tf | 162 +++++++++++++++++++++- 9 files changed, 604 insertions(+), 64 deletions(-) create mode 100644 example/main.tf create mode 100644 example/providers.tf create mode 100644 example/terraform.tfvars create mode 100644 example/variables.tf create mode 100644 project/output.tf rename project/{provider.tf => providers.tf} (58%) delete mode 100644 project/sna.tf diff --git a/example/main.tf b/example/main.tf new file mode 100644 index 0000000..a0920b5 --- /dev/null +++ b/example/main.tf @@ -0,0 +1,18 @@ +module "project" { + source = "../project" + for_each = var.projects + + organization_id = each.value.organization_id + name = each.value.name + + description = each.value.description != null ? each.value.description : null + labels = each.value.labels != {} ? each.value.labels : {} + + owner_email = each.value.owner_email + + # security_groups = each.value.security_groups + networks = each.value.networks + postgres_instances = each.value.postgres_instances + ske_clusters = each.value.ske_clusters + observability_instances = each.value.observability_instances +} diff --git a/example/providers.tf b/example/providers.tf new file mode 100644 index 0000000..5eb9d92 --- /dev/null +++ b/example/providers.tf @@ -0,0 +1,16 @@ +terraform { + required_version = ">= 1.9.0" + required_providers { + stackit = { + source = "stackitcloud/stackit" + version = "0.56.0" + } + } +} + +provider "stackit" { + default_region = var.region + service_account_token = var.service_account_token != "" ? var.service_account_token : null + service_account_key_path = var.service_account_key_path != "" ? var.service_account_key_path : null + enable_beta_resources = true +} \ No newline at end of file diff --git a/example/terraform.tfvars b/example/terraform.tfvars new file mode 100644 index 0000000..7531146 --- /dev/null +++ b/example/terraform.tfvars @@ -0,0 +1,188 @@ +region = "eu01" +service_account_key_path = "/Users/schlenz/sa-key-dd5fa2c9-1651-4da7-8404-9ac4fe9bc3d5.json" + +projects = { + project_1 = { + name = "project-1" + organization_id = "03a34540-3c1a-4794-b2c6-7111ecf824ef" + owner_email = "maximilian.schlenz@stackit.cloud" + + # postgres_instances = { + # dev = { + # name = "pg-test-instance" + # version = 17 + # flavor = { + # cpu = 2, + # ram = 4 + # } + # storage = { + # class = "premium-perf6-stackit", + # size = 20 + # } + # replicas = 1 + # acl = ["0.0.0.0/0"] + # backup_schedule = "00 00 * * *" + + # users = [ + # { username = "adm-usr", + # roles = ["login", "createdb"] + # }, + # { username = "testusr", + # roles = ["login"] + # } + # ] + + # databases = [ + # { + # name = "test-db", + # owner = "admin" + # } + # ] + # } + # } + + networks = { + tiny = { + name = "tiny-net" + ipv4_prefix_length = 28 + labels = { + purpose = "test" + } + security_groups = { + ssh_ingress_group = { + name = "ssh-ingress-group" + description = "ALLOW SSH ingress" + rules = [ + { description = "SSH RULE 1" + direction = "ingress" + ether_type = "IPv4" + ip_range = "0.0.0.0/0" + protocol = { + name = "tcp" + } + port_range = { + min = 22 + max = 23 + } + }, + ] + }, + + web_traffic_group = { + name = "web-traffic-group" + description = "ALLOW WEB TRAFFIC ingress" + rules = [ + { description = "ALLOW ALL 80" + direction = "ingress" + ether_type = "IPv4" + ip_range = "0.0.0.0/0" + protocol = { + name = "tcp" + } + port_range = { + min = 80 + max = 80 + } + }, + { description = "ALLOW ALL 443" + direction = "ingress" + ether_type = "IPv4" + ip_range = "0.0.0.0/0" + protocol = { + name = "tcp" + } + port_range = { + min = 443 + max = 443 + } + }, + ] + }, + } + } + # network_static = { + # } + + # custom_static = { + # name = "static-net" + # routed = true + # ipv4_prefix = "10.99.0.0/24" + # ipv4_gateway = "10.99.0.1" + + # nic_ipv4 = "10.99.0.10" + # nic_name = "static-nic" + # nic_security_group_ids = [""] + # } + # } + # } + + # ske_clusters = { + # dev = { + # name = "dev" + # kubernetes_version_min = "1.31" + # node_pools = [ + # { name = "default" + # machine_type = "c2.1" + # availability_zones = ["eu01-1", "eu01-2"] + # volume_size = 40 + # minimum = 1 + # maximum = 3 + # } + # ] + # } + + # prod = { + # name = "prod" + # kubernetes_version_min = "1.31" + # node_pools = [ + # { name = "general" + # machine_type = "c2.2" + # availability_zones = ["eu03-1", "eu03-2"] + # volume_size = 80 + # minimum = 2 + # maximum = 4 + # } + # ] + # } + # } + + # observability_instances = { + # starter = { + # name = "Observability-1" + # plan_name = "Observability-Starter-EU01" + # } + + # prod = { + # name = "Observability-2" + # plan_name = "Observability-Large-EU01" + # } + # } + + }, + # project_2 = { + # name = "project-2" + # organization_id = "03a34540-3c1a-4794-b2c6-7111ecf824ef" + # owner_email = "maximilian.schlenz@stackit.cloud" + # networks = { + # tiny = { + # name = "tiny-net" + # ipv4_prefix_length = 28 + # labels = { + # purpose = "test" + # } + # } + + # custom_static = { + # name = "static-net" + # routed = false + # ipv4_prefix = "10.99.0.0/24" + # ipv4_gateway = "10.99.0.1" + + # nic_ipv4 = "10.99.0.10" + # nic_name = "static-nic" + # nic_security_group_ids = [""] + # } + # } + # } + } +} \ No newline at end of file diff --git a/example/variables.tf b/example/variables.tf new file mode 100644 index 0000000..389d617 --- /dev/null +++ b/example/variables.tf @@ -0,0 +1,147 @@ +variable "region" { + description = "Region for the STACKIT Cloud" + type = string + default = "eu01" +} + +variable "service_account_token" { + description = "Service account token for authentication" + sensitive = true + type = string + default = "" +} + +variable "service_account_key_path" { + type = string + default = "" +} + +variable "projects" { + type = map(object({ + + organization_id = string + name = string + description = optional(string) + labels = optional(map(string)) + project_id = optional(string) + owner_email = optional(string) + + # security_groups = optional(map(object({ + # name = string + # description = optional(string) + # labels = optional(map(string)) + # stateful = optional(bool) + # rules = list(object({ + # description = optional(string) + # direction = string + # ether_type = optional(string) + # ip_range = optional(string) + # protocol = optional(object({ + # name = optional(string) + # number = optional(number) + # })) + # port_range = optional(object({ + # min = number + # max = number + # })) + # remote_security_group_id = optional(string) + # })) + # })), {}) + + networks = optional(map(object({ + name = string + ipv4_gateway = optional(string) + ipv4_nameservers = optional(list(string)) + ipv4_prefix = optional(string) + ipv4_prefix_length = optional(number) + ipv6_gateway = optional(string) + ipv6_nameservers = optional(list(string)) + ipv6_prefix = optional(string) + ipv6_prefix_length = optional(number) + labels = optional(map(string)) + no_ipv4_gateway = optional(bool) + no_ipv6_gateway = optional(bool) + routed = optional(bool) + security_groups = optional(map(object({ + name = string + description = optional(string) + labels = optional(map(string)) + stateful = optional(bool) + rules = list(object({ + description = optional(string) + direction = string + ether_type = optional(string) + ip_range = optional(string) + protocol = optional(object({ + name = optional(string) + number = optional(number) + })) + port_range = optional(object({ + min = number + max = number + })) + remote_security_group_id = optional(string) + })) + })), {}) + + nic_ipv4 = optional(string) + nic_name = optional(string) + nic_allowed_addresses = optional(list(string)) + nic_labels = optional(map(string)) + nic_security = optional(bool) + nic_security_group_ids = optional(list(string)) + })), {}) + + postgres_instances = optional(map(object({ + acl = list(string) + backup_schedule = string + + flavor = object({ + cpu = number + ram = number + }) + + name = string + replicas = number + storage = object({ + class = string + size = number + }) + version = string + region = optional(string) + + databases = optional(list(object({ + instance_id = optional(string) + name = string + owner = string + region = optional(string) + + }))) + + users = optional(list(object({ + instance_id = optional(string) + roles = set(string) + username = string + region = optional(string) + }))) + })), {}) + + ske_clusters = optional(map(object({ + name = string + kubernetes_version_min = string + node_pools = list(object({ + name = string + machine_type = string + availability_zones = list(string) + volume_size = number + minimum = number + maximum = number + })) + })), {}) + + observability_instances = optional(map(object({ + name = string + plan_name = string + })), {}) + })) +} diff --git a/project/main.tf b/project/main.tf index 58176f0..62332c9 100644 --- a/project/main.tf +++ b/project/main.tf @@ -1,34 +1,81 @@ -variable "projects" { - type = map(object({ - name = string - owner_email = string - })) - default = { - project1 = { - name = "project-alpha" - owner_email = "michael.sodan@stackit.cloud" - } - project2 = { - name = "project-beta" - owner_email = "michael.sodan@stackit.cloud" - } - } +resource "stackit_resourcemanager_project" "this" { + parent_container_id = var.organization_id + name = var.name + labels = var.labels + owner_email = var.owner_email } -resource "stackit_resourcemanager_project" "projects" { - for_each = var.projects - parent_container_id = var.organization_id # Nutzt jetzt die übergebene Variable - name = each.value.name - owner_email = each.value.owner_email - # labels = { ... } # Vorerst entfernt, da stackit_network_area nicht definiert war +# module "sg" { +# source = "../security-group" +# for_each = var.security_groups + +# project_id = stackit_resourcemanager_project.this.project_id +# name = each.value.name +# description = each.value.description +# rules = each.value.rules +# } + +module "net" { + source = "../network" + for_each = var.networks + + project_id = stackit_resourcemanager_project.this.project_id + name = each.value.name + + ipv4_gateway = each.value.ipv4_gateway != null ? each.value.ipv4_gateway : null + ipv4_nameservers = each.value.ipv4_nameservers != [] ? each.value.ipv4_nameservers : [] + ipv4_prefix = each.value.ipv4_prefix != null ? each.value.ipv4_prefix : null + ipv4_prefix_length = each.value.ipv4_prefix_length != null ? each.value.ipv4_prefix_length : null + ipv6_gateway = each.value.ipv6_gateway != null ? each.value.ipv6_gateway : null + ipv6_nameservers = each.value.ipv6_nameservers != [] ? each.value.ipv6_nameservers : [] + ipv6_prefix = each.value.ipv6_prefix != null ? each.value.ipv6_prefix : null + ipv6_prefix_length = each.value.ipv6_prefix_length != null ? each.value.ipv6_prefix_length : null + labels = each.value.labels != {} ? each.value.labels : {} + no_ipv4_gateway = each.value.no_ipv4_gateway + no_ipv6_gateway = each.value.no_ipv6_gateway + routed = each.value.routed != null ? each.value.routed : true + + security_groups = each.value.security_groups + + nic_ipv4 = each.value.nic_ipv4 + nic_name = each.value.nic_name != null ? each.value.nic_name : null + nic_allowed_addresses = each.value.nic_allowed_addresses + nic_labels = each.value.nic_labels != {} ? each.value.nic_labels : {} + nic_security = each.value.nic_security + nic_security_group_ids = each.value.nic_security_group_ids } -output "project_info" { - value = { - for k, project in stackit_resourcemanager_project.projects : k => { - project_id = project.project_id - container_id = project.container_id - } - } -} +# module "pg" { +# source = "../postgres" +# for_each = var.postgres_instances +# project_id = stackit_resourcemanager_project.this.project_id +# name = each.value.name +# ver = each.value.version +# flavor = each.value.flavor +# storage = each.value.storage +# replicas = each.value.replicas +# acl = each.value.acl +# backup_schedule = each.value.backup_schedule +# users = each.value.users +# databases = each.value.databases +# } + +# module "ske" { +# source = "../ske" +# for_each = var.ske_clusters + +# project_id = stackit_resourcemanager_project.this.project_id +# name = each.value.name +# kubernetes_version_min = each.value.kubernetes_version_min +# node_pools = each.value.node_pools +# } + +# module "obs" { +# source = "../observability" +# for_each = var.observability_instances + +# project_id = stackit_resourcemanager_project.this.project_id +# name = each.value.name +# plan_name = each.value.plan_name +# } diff --git a/project/output.tf b/project/output.tf new file mode 100644 index 0000000..e69de29 diff --git a/project/provider.tf b/project/providers.tf similarity index 58% rename from project/provider.tf rename to project/providers.tf index a89dd02..6e038c3 100644 --- a/project/provider.tf +++ b/project/providers.tf @@ -1,10 +1,9 @@ - terraform { + required_version = ">= 1.9.0" required_providers { stackit = { source = "stackitcloud/stackit" - version = ">= 0.54.0" # Diese Version passt zu Ihrer Anforderung + version = "0.56.0" } } } - diff --git a/project/sna.tf b/project/sna.tf deleted file mode 100644 index 711c80d..0000000 --- a/project/sna.tf +++ /dev/null @@ -1,27 +0,0 @@ -/* resource "time_sleep" "wait_before_destroy" { - destroy_duration = "60s" -} -*/ - -resource "stackit_network_area" "sna" { - organization_id = var.organization_id - name = "bego_sna" - network_ranges = [ - { - prefix = "10.220.0.0/16" - } - ] - transfer_network = "var.sna_net" - //depends_on = [time_sleep.wait_before_destroy] -} - -/* resource "stackit_network_area_route" "sna_route1" { - organization_id = var.organization_id - network_area_id = stackit_network_area.sna.network_area_id - prefix = "10.220.99.0/24" - next_hop = "10.220.0.0" - labels = { - "key" = "value" - } -} -*/ diff --git a/project/variables.tf b/project/variables.tf index 6a8400f..9085c0b 100644 --- a/project/variables.tf +++ b/project/variables.tf @@ -1,10 +1,162 @@ variable "organization_id" { - description = "Empfängt die Container-ID der Organisation vom Root-Modul." - type = string + type = string } -variable "sna_net" { - description = "SNA Transfer Network" - type = string +variable "name" { + type = string } +variable "description" { + type = string + default = null +} + +variable "labels" { + type = map(string) + default = {} +} + +variable "project_id" { + type = string + default = null +} + +variable "owner_email" { + type = string + default = null +} + +variable "security_groups" { + type = map(object({ + name = string + description = optional(string) + labels = optional(map(string)) + stateful = optional(bool) + rules = list(object({ + description = optional(string) + direction = string + ether_type = optional(string) + ip_range = optional(string) + protocol = optional(object({ + name = optional(string) + number = optional(number) + })) + port_range = optional(object({ + min = number + max = number + })) + remote_security_group_id = optional(string) + })) + })) + default = {} +} + +variable "networks" { + type = map(object({ + name = string + ipv4_gateway = optional(string) + ipv4_nameservers = optional(list(string)) + ipv4_prefix = optional(string) + ipv4_prefix_length = optional(number) + ipv6_gateway = optional(string) + ipv6_nameservers = optional(list(string)) + ipv6_prefix = optional(string) + ipv6_prefix_length = optional(number) + labels = optional(map(string)) + no_ipv4_gateway = optional(bool) + no_ipv6_gateway = optional(bool) + routed = optional(bool) + + security_groups = optional(map(object({ + name = string + description = optional(string) + labels = optional(map(string)) + stateful = optional(bool) + rules = list(object({ + description = optional(string) + direction = string + ether_type = optional(string) + ip_range = optional(string) + protocol = optional(object({ + name = optional(string) + number = optional(number) + })) + port_range = optional(object({ + min = number + max = number + })) + remote_security_group_id = optional(string) + })) + })), {}) + + nic_ipv4 = optional(string) + nic_name = optional(string) + nic_allowed_addresses = optional(list(string)) + nic_labels = optional(map(string)) + nic_security = optional(bool) + nic_security_group_ids = optional(list(string)) + })) + default = {} +} + +variable "postgres_instances" { + type = map(object({ + acl = list(string) + backup_schedule = string + + flavor = object({ + cpu = number + ram = number + }) + + name = string + replicas = number + + storage = object({ + class = string + size = number + }) + + version = string + region = optional(string) + + databases = optional(list(object({ + instance_id = optional(string) + name = string + owner = string + region = optional(string) + }))) + + users = optional(list(object({ + instance_id = optional(string) + roles = set(string) + username = string + region = optional(string) + }))) + })) + default = {} +} + +variable "ske_clusters" { + type = map(object({ + name = string + kubernetes_version_min = string + node_pools = list(object({ + name = string + machine_type = string + availability_zones = list(string) + volume_size = number + minimum = number + maximum = number + })) + })) + default = {} +} + +variable "observability_instances" { + type = map(object({ + name = string + plan_name = string + })) + default = {} +}