diff --git a/.gitignore b/.gitignore index 5dfe310..65bfb30 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ .terraform* terraform.tfstate* +.env \ No newline at end of file diff --git a/example/main.tf b/example/main.tf new file mode 100644 index 0000000..2d2fc0b --- /dev/null +++ b/example/main.tf @@ -0,0 +1,10 @@ +module "security_groups" { + source = "../security-group" + + for_each = var.security_groups + + project_id = var.project_id + name = each.value.name + description = each.value.description + rules = each.value.rules +} \ No newline at end of file diff --git a/example/providers.tf b/example/providers.tf new file mode 100644 index 0000000..e5cfc8d --- /dev/null +++ b/example/providers.tf @@ -0,0 +1,15 @@ +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 + 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..584af52 --- /dev/null +++ b/example/terraform.tfvars @@ -0,0 +1,59 @@ +region = "eu01" +service_account_token = "" +project_id = "" + +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 = 22 + } + }, + ] + }, + + 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 + } + }, + ] + }, + +} \ No newline at end of file diff --git a/example/variables.tf b/example/variables.tf new file mode 100644 index 0000000..918e44e --- /dev/null +++ b/example/variables.tf @@ -0,0 +1,43 @@ +variable "region" { + description = "Region for the STACKIT Cloud" + type = string + default = "eu01" +} + +variable "project_id" { + description = "STACKIT Cloud project ID" + type = string +} + +variable "service_account_token" { + description = "Service account token for authentication" + sensitive = true + type = string +} + + +variable "security_groups" { + type = map(object({ + name = optional(string) + description = optional(string) + rules = list(object({ + direction = string + description = optional(string) + ether_type = optional(string) + icmp_parameters = optional(object({ + type = optional(number) + code = optional(number) + })) + ip_range = optional(string) + port_range = optional(object({ + min = number + max = number + })) + protocol = optional(object({ + name = optional(string) + number = optional(number) + })) + remote_security_group_id = optional(string) + })) + })) +} diff --git a/security-group/main.tf b/security-group/main.tf new file mode 100644 index 0000000..3098cf0 --- /dev/null +++ b/security-group/main.tf @@ -0,0 +1,25 @@ +locals { + rule_count = length(var.rules) +} + +resource "stackit_security_group" "this" { + project_id = var.project_id + name = var.name + description = var.description +} + +resource "stackit_security_group_rule" "rule" { + count = local.rule_count + + direction = var.rules[count.index].direction + project_id = var.project_id + security_group_id = stackit_security_group.this.security_group_id + + description = var.rules[count.index].description + ether_type = var.rules[count.index].ether_type + icmp_parameters = var.rules[count.index].icmp_parameters + ip_range = var.rules[count.index].ip_range + port_range = var.rules[count.index].port_range + protocol = var.rules[count.index].protocol + remote_security_group_id = var.rules[count.index].remote_security_group_id +} diff --git a/security-group/output.tf b/security-group/output.tf new file mode 100644 index 0000000..bf320d2 --- /dev/null +++ b/security-group/output.tf @@ -0,0 +1,8 @@ +output "security_group_id" { + value = stackit_security_group.this.security_group_id + description = "ID of the security group" +} + +output "rule_ids" { + value = stackit_security_group_rule.rule[*].id +} \ No newline at end of file diff --git a/security-group/providers.tf b/security-group/providers.tf new file mode 100644 index 0000000..6e038c3 --- /dev/null +++ b/security-group/providers.tf @@ -0,0 +1,9 @@ +terraform { + required_version = ">= 1.9.0" + required_providers { + stackit = { + source = "stackitcloud/stackit" + version = "0.56.0" + } + } +} diff --git a/security-group/variables.tf b/security-group/variables.tf new file mode 100644 index 0000000..5ccff74 --- /dev/null +++ b/security-group/variables.tf @@ -0,0 +1,45 @@ +variable "project_id" { + type = string + description = "The ID of the project where the security group will be created." +} + +variable "name" { + type = string + description = "Name of the security group." +} + +variable "description" { + type = string + default = "" + description = "Description of the security group. If not provided, it defaults to an empty string." +} + +variable "rules" { + description = "List of rules to attach to this security-group" + type = list(object({ + direction = string + description = optional(string) + ether_type = optional(string) + icmp_parameters = optional(object({ + type = optional(number) + code = optional(number) + })) + ip_range = optional(string) + port_range = optional(object({ + min = number + max = number + })) + protocol = optional(object({ + name = optional(string) + })) + remote_security_group_id = optional(string) + })) + default = [] + validation { + condition = alltrue([ + for rule in var.rules : contains(["ingress", "egress"], rule.direction) + # ... need more validations + ]) + error_message = "Direction must be either \"ingress\" or \"egress\"." + } +}