From e22d4e61a8ff5341fdaf8c9d3588689836bbe81a Mon Sep 17 00:00:00 2001 From: Andrea Dell'Amico Date: Tue, 11 Aug 2026 18:35:46 +0200 Subject: [PATCH] Instances for the keycloak upgrade. --- modules/keycloak/keycloak.tf | 202 +++++++++++++++++++++++++ modules/keycloak/outputs.tf | 39 +++++ modules/keycloak/terraform-provider.tf | 10 ++ modules/keycloak/variables-keycloak.tf | 117 ++++++++++++++ s2i2s/keycloak/README.md | 59 ++++++++ s2i2s/keycloak/keycloak.plan | Bin 0 -> 21770 bytes s2i2s/keycloak/main.tf | 107 +++++++++++++ s2i2s/keycloak/outputs.tf | 42 +++++ s2i2s/keycloak/provider.tf | 14 ++ s2i2s/keycloak/terraform.tfstate | 1 + 10 files changed, 591 insertions(+) create mode 100644 modules/keycloak/keycloak.tf create mode 100644 modules/keycloak/outputs.tf create mode 100644 modules/keycloak/terraform-provider.tf create mode 100644 modules/keycloak/variables-keycloak.tf create mode 100644 s2i2s/keycloak/README.md create mode 100644 s2i2s/keycloak/keycloak.plan create mode 100644 s2i2s/keycloak/main.tf create mode 100644 s2i2s/keycloak/outputs.tf create mode 100644 s2i2s/keycloak/provider.tf create mode 100644 s2i2s/keycloak/terraform.tfstate diff --git a/modules/keycloak/keycloak.tf b/modules/keycloak/keycloak.tf new file mode 100644 index 0000000..ffb729e --- /dev/null +++ b/modules/keycloak/keycloak.tf @@ -0,0 +1,202 @@ +locals { + # Addresses actually used, one per instance + keycloak_ip = slice(var.keycloak_ip, 0, var.keycloak_data.vm_count) +} + +# +# Traffic between the cluster nodes (Infinispan/JGroups discovery and +# replication). The addresses are static, so no rule depends on the instances +# +resource "openstack_networking_secgroup_v2" "keycloak_cluster_traffic" { + name = "keycloak_cluster_traffic" + delete_default_rules = "true" + description = "Traffic between the nodes of the keycloak cluster" +} + +resource "openstack_networking_secgroup_rule_v2" "cluster_tcp" { + for_each = toset(local.keycloak_ip) + security_group_id = openstack_networking_secgroup_v2.keycloak_cluster_traffic.id + description = "TCP traffic from the keycloak node ${each.value}" + direction = "ingress" + ethertype = "IPv4" + protocol = "tcp" + remote_ip_prefix = "${each.value}/32" +} + +resource "openstack_networking_secgroup_rule_v2" "cluster_udp" { + for_each = toset(local.keycloak_ip) + security_group_id = openstack_networking_secgroup_v2.keycloak_cluster_traffic.id + description = "UDP traffic from the keycloak node ${each.value}" + direction = "ingress" + ethertype = "IPv4" + protocol = "udp" + remote_ip_prefix = "${each.value}/32" +} + +resource "openstack_networking_secgroup_rule_v2" "cluster_egress" { + for_each = toset(local.keycloak_ip) + security_group_id = openstack_networking_secgroup_v2.keycloak_cluster_traffic.id + description = "Traffic to the keycloak node ${each.value}" + direction = "egress" + ethertype = "IPv4" + remote_ip_prefix = "${each.value}/32" +} + +# JGroups can use multicast for the discovery +resource "openstack_networking_secgroup_rule_v2" "cluster_igmp_ingress" { + security_group_id = openstack_networking_secgroup_v2.keycloak_cluster_traffic.id + description = "Ingress IGMP traffic between the keycloak nodes" + direction = "ingress" + ethertype = "IPv4" + protocol = "igmp" + remote_ip_prefix = "0.0.0.0/0" +} + +resource "openstack_networking_secgroup_rule_v2" "cluster_igmp_egress" { + security_group_id = openstack_networking_secgroup_v2.keycloak_cluster_traffic.id + description = "Egress IGMP traffic between the keycloak nodes" + direction = "egress" + ethertype = "IPv4" + protocol = "igmp" + remote_ip_prefix = "0.0.0.0/0" +} + +# +# Traffic from the main L7 load balancers and from Prometheus +# +resource "openstack_networking_secgroup_v2" "traffic_to_keycloak" { + name = "traffic_to_keycloak_from_the_main_load_balancers" + delete_default_rules = "true" + description = "Traffic from the main L7 HAPROXY load balancers to keycloak" +} + +resource "openstack_networking_secgroup_rule_v2" "haproxy_to_keycloak_https" { + for_each = toset(var.haproxy_l7_ip) + security_group_id = openstack_networking_secgroup_v2.traffic_to_keycloak.id + description = "HTTPS traffic from the HAPROXY L7 ${each.value}" + direction = "ingress" + ethertype = "IPv4" + protocol = "tcp" + port_range_min = var.keycloak_data.https_port + port_range_max = var.keycloak_data.https_port + remote_ip_prefix = "${each.value}/32" +} + +resource "openstack_networking_secgroup_rule_v2" "haproxy_to_keycloak_management" { + for_each = toset(var.haproxy_l7_ip) + security_group_id = openstack_networking_secgroup_v2.traffic_to_keycloak.id + description = "Traffic from the HAPROXY L7 ${each.value} to the management port" + direction = "ingress" + ethertype = "IPv4" + protocol = "tcp" + port_range_min = var.keycloak_data.management_port + port_range_max = var.keycloak_data.management_port + remote_ip_prefix = "${each.value}/32" +} + +resource "openstack_networking_secgroup_rule_v2" "prometheus_to_keycloak_metrics" { + security_group_id = openstack_networking_secgroup_v2.traffic_to_keycloak.id + description = "Requests from Prometheus to the management port, that serves the metrics" + direction = "ingress" + ethertype = "IPv4" + protocol = "tcp" + port_range_min = var.keycloak_data.management_port + port_range_max = var.keycloak_data.management_port + remote_ip_prefix = var.prometheus_cidr +} + +# +# Hard anti affinity: the two instances never share a hypervisor +# +resource "openstack_compute_servergroup_v2" "keycloak" { + name = var.keycloak_data.srv_name + policies = [var.keycloak_data.affinity_policy] +} + +# +# Ports. One on the main private network, one on the dedicated network of the +# database: keycloak reaches PostgreSQL only through the latter +# +resource "openstack_networking_port_v2" "keycloak_main_port" { + count = var.keycloak_data.vm_count + name = format("%s-%02d-main-port", var.keycloak_data.srv_name, count.index + 1) + description = "Port of the keycloak instance on the main private network" + admin_state_up = true + network_id = var.main_private_network_id + security_group_ids = [ + var.default_security_group_id, + openstack_networking_secgroup_v2.keycloak_cluster_traffic.id, + openstack_networking_secgroup_v2.traffic_to_keycloak.id, + ] + fixed_ip { + subnet_id = var.main_private_subnet_id + ip_address = local.keycloak_ip[count.index] + } +} + +resource "openstack_networking_port_v2" "keycloak_postgresql_port" { + count = var.keycloak_data.vm_count + name = format("%s-%02d-postgresql-port", var.keycloak_data.srv_name, count.index + 1) + description = "Port of the keycloak instance on the dedicated network of the database" + admin_state_up = true + network_id = var.postgresql_network_id + security_group_ids = [var.postgresql_client_security_group_id] + # The address comes from the allocation pool of the dedicated subnet + fixed_ip { + subnet_id = var.postgresql_subnet_id + } +} + +# +# Instances +# +resource "openstack_compute_instance_v2" "keycloak" { + count = var.keycloak_data.vm_count + name = format("%s-%02d", var.keycloak_data.srv_name, count.index + 1) + availability_zone_hints = var.availability_zone + flavor_name = var.keycloak_data.flavor + key_pair = var.ssh_key_name + + scheduler_hints { + group = openstack_compute_servergroup_v2.keycloak.id + } + + block_device { + uuid = var.image.uuid + source_type = "image" + volume_size = var.keycloak_data.boot_vol_size + boot_index = 0 + destination_type = "volume" + delete_on_termination = false + } + + network { + port = openstack_networking_port_v2.keycloak_main_port[count.index].id + } + + network { + port = openstack_networking_port_v2.keycloak_postgresql_port[count.index].id + } + + user_data = file(var.image.user_data_file) + + # Do not replace the instance when the ssh key or the user data change + lifecycle { + ignore_changes = [ + key_pair, user_data, network + ] + } +} + +# +# Optional CNAMEs, pointing to the load balancer that publishes the service +# +resource "openstack_dns_recordset_v2" "keycloak_recordset" { + for_each = var.keycloak_recordsets + zone_id = var.dns_zone_id + name = each.value.name + description = each.value.description + ttl = 8600 + type = "CNAME" + records = [var.keycloak_cname_target] +} diff --git a/modules/keycloak/outputs.tf b/modules/keycloak/outputs.tf new file mode 100644 index 0000000..55f41f5 --- /dev/null +++ b/modules/keycloak/outputs.tf @@ -0,0 +1,39 @@ +output "keycloak_data" { + description = "The input data, re-exported for the dependent workspaces" + value = var.keycloak_data +} + +output "keycloak_instance_ids" { + value = openstack_compute_instance_v2.keycloak[*].id +} + +output "keycloak_instance_names" { + value = openstack_compute_instance_v2.keycloak[*].name +} + +output "keycloak_ip" { + description = "Addresses of the instances on the main private network" + value = local.keycloak_ip +} + +output "keycloak_postgresql_ip" { + description = "Addresses of the instances on the dedicated network of the database" + value = openstack_networking_port_v2.keycloak_postgresql_port[*].all_fixed_ips +} + +output "keycloak_server_group_id" { + value = openstack_compute_servergroup_v2.keycloak.id +} + +output "keycloak_cluster_security_group_id" { + value = openstack_networking_secgroup_v2.keycloak_cluster_traffic.id +} + +output "traffic_to_keycloak_security_group_id" { + description = "Security group that allows the traffic from the load balancers, to be added to the ports of new clients" + value = openstack_networking_secgroup_v2.traffic_to_keycloak.id +} + +output "keycloak_recordsets" { + value = var.keycloak_recordsets +} diff --git a/modules/keycloak/terraform-provider.tf b/modules/keycloak/terraform-provider.tf new file mode 100644 index 0000000..31f07e2 --- /dev/null +++ b/modules/keycloak/terraform-provider.tf @@ -0,0 +1,10 @@ +# Define required providers +terraform { + required_version = ">= 0.14.0" + required_providers { + openstack = { + source = "terraform-provider-openstack/openstack" + version = ">= 2.0.0" + } + } +} diff --git a/modules/keycloak/variables-keycloak.tf b/modules/keycloak/variables-keycloak.tf new file mode 100644 index 0000000..0f086c9 --- /dev/null +++ b/modules/keycloak/variables-keycloak.tf @@ -0,0 +1,117 @@ +# +# Keycloak cluster. +# +# Derived from the d4science 'keycloak' module, rewritten for this repository: +# the ports are separate resources, the security groups go on the ports, and +# nothing is read from another state inside the module. The addresses of the +# instances are known in advance (keycloak_ip), so the rules of the cluster +# security group do not depend on the instances being created first. +# + +variable "keycloak_data" { + description = "Instances of the keycloak cluster. m1.medium is RAM 4 - VCPUs 2" + type = object({ + srv_name = optional(string, "keycloak") + vm_count = optional(number, 2) + flavor = optional(string, "m1.medium") + boot_vol_size = optional(number, 30) + # 'anti-affinity' is hard: the scheduler fails instead of co-locating the + # instances. 'soft-anti-affinity' only expresses a preference + affinity_policy = optional(string, "anti-affinity") + # Ports the service listens on + https_port = optional(number, 9443) + management_port = optional(number, 9000) + }) + default = {} +} + +variable "keycloak_ip" { + type = list(string) + description = "Addresses of the instances on the main private network, one per instance" + validation { + condition = length(var.keycloak_ip) >= var.keycloak_data.vm_count + error_message = "keycloak_ip must contain at least vm_count addresses." + } +} + +# Data that comes from the network/DNS and project setup workspaces +variable "main_private_network_id" { + type = string + description = "ID of the main private network of the project" +} + +variable "main_private_subnet_id" { + type = string + description = "ID of the main private subnet of the project" +} + +variable "default_security_group_id" { + type = string + description = "ID of the 'default_for_all' security group of the project" +} + +variable "haproxy_l7_ip" { + type = list(string) + description = "Addresses of the L7 HAPROXY load balancers, allowed to reach the service" +} + +variable "prometheus_cidr" { + type = string + description = "Address of the Prometheus server, allowed to scrape the management port" +} + +# Data that comes from the postgresql workspace +variable "postgresql_network_id" { + type = string + description = "ID of the dedicated network of the PostgreSQL service" +} + +variable "postgresql_subnet_id" { + type = string + description = "ID of the dedicated subnet of the PostgreSQL service" +} + +variable "postgresql_client_security_group_id" { + type = string + description = "Security group that allows the connections to the PostgreSQL service" +} + +variable "availability_zone" { + type = string + description = "Availability zone hint of the instances" +} + +variable "image" { + description = "Image of the instances: uuid and cloud-init user data file" + type = object({ + uuid = string + user_data_file = string + }) +} + +variable "ssh_key_name" { + type = string + description = "Name of the SSH key pair injected by cloud-init" +} + +# Optional CNAMEs pointing to the load balancer that publishes the service +variable "dns_zone_id" { + type = string + default = "" + description = "ID of the DNS zone. Required when keycloak_recordsets is not empty" +} + +variable "keycloak_cname_target" { + type = string + default = "" + description = "Target of the CNAMEs, usually the name of the main load balancer, with the trailing dot" +} + +variable "keycloak_recordsets" { + description = "CNAMEs that publish the service through the load balancer" + type = map(object({ + name = string + description = string + })) + default = {} +} diff --git a/s2i2s/keycloak/README.md b/s2i2s/keycloak/README.md new file mode 100644 index 0000000..ed053d3 --- /dev/null +++ b/s2i2s/keycloak/README.md @@ -0,0 +1,59 @@ +# Keycloak cluster of the S2I2S project + +Two VMs, `m1.medium` (RAM 4 - VCPUs 2), Ubuntu 24.04, 30 GB of root disk, no +data volume, in a server group with the **hard** anti affinity policy +(`anti-affinity`: the scheduler fails instead of putting the two instances on +the same hypervisor). + +Each instance has **two interfaces**: + +| Interface | Address | Use | +|---|---|---| +| main private network | `10.10.0.163`, `10.10.0.164` | traffic from the L7 HAPROXY load balancers and from Prometheus, administration | +| `postgresql-srv-net` | from the DHCP pool | the only way to the database | + +Security groups: + +* `keycloak_cluster_traffic` — TCP, UDP and IGMP between the two nodes + (Infinispan/JGroups). The rules use the static addresses of the instances, so + they do not depend on the instances being created first; +* `traffic_to_keycloak_from_the_main_load_balancers` — ingress on 9443 from each + HAPROXY L7, and on 9000 (management and metrics) from the load balancers and + from Prometheus; +* `vm_access_to_the_postgresql_service` — taken from the `postgresql` workspace, + on the port in the dedicated network of the database. + +A CNAME `accounts.s2i2s.cloud.isti.cnr.it` pointing to the main load balancer is +created; the service itself is published by the HAPROXY L7 configuration (see +`docs/main_load_balancer.md` in `infrastructure-playbooks`, variable +`haproxy_l7_services`). + +The resources and the sizing are in +[`../../modules/keycloak`](../../modules/keycloak), as defaults of +`keycloak_data`: override them in the module call to change them. The addresses +of the instances come from the address plan in [`../variables`](../variables) +(`basic_services_ip.keycloak_1` and `_2`, exported as the `keycloak_ip` list). + +## Order of the applies + +``` +main_net_dns_router -> project-setup -> postgresql -> keycloak +``` + +This workspace reads the state of all three: the network and the DNS zone, the +default security group and the addresses of the load balancers and of +Prometheus, and the dedicated network of the database with its client security +group. + +```bash +tofu init +tofu plan -out=keycloak.plan +tofu apply keycloak.plan +``` + +After the apply, regenerate the ansible inventory in +`infrastructure-playbooks`, which reads this state: + +```bash +ansible-playbook tofu-inventory.yml --diff +``` diff --git a/s2i2s/keycloak/keycloak.plan b/s2i2s/keycloak/keycloak.plan new file mode 100644 index 0000000000000000000000000000000000000000..b461e5a28952a25e1509be5ec385c7274aa19d5a GIT binary patch literal 21770 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 literal 0 HcmV?d00001 diff --git a/s2i2s/keycloak/main.tf b/s2i2s/keycloak/main.tf new file mode 100644 index 0000000..b5ced98 --- /dev/null +++ b/s2i2s/keycloak/main.tf @@ -0,0 +1,107 @@ +# Keycloak cluster of the S2I2S OpenStack project. +# +# Two VMs in hard anti affinity ('anti-affinity' server group policy: the +# scheduler fails instead of putting them on the same hypervisor), 30 GB of root +# disk, m1.medium (RAM 4 - VCPUs 2), no data volume. +# +# Each instance has two interfaces: +# - the main private network (10.10.0.163, 10.10.0.164), where the L7 HAPROXY +# load balancers and Prometheus reach it; +# - the dedicated network of the database, the only way to PostgreSQL. The +# address comes from the allocation pool of that subnet. +# +# Apply order: main_net_dns_router -> project-setup -> postgresql -> this one. + +data "terraform_remote_state" "privnet_dns_router" { + backend = "local" + config = { + path = "../main_net_dns_router/terraform.tfstate" + } +} + +data "terraform_remote_state" "project_setup" { + backend = "local" + config = { + path = "../project-setup/terraform.tfstate" + } +} + +# Dedicated network and client security group of the database +data "terraform_remote_state" "postgresql" { + backend = "local" + config = { + path = "../postgresql/terraform.tfstate" + } +} + +module "labs_common_variables" { + source = "../../modules/labs_common_variables" +} + +module "project_variables" { + source = "../variables" +} + +module "ssh_settings" { + source = "../../modules/ssh-key-ref" +} + +locals { + # From the network/DNS state + dns_zone = data.terraform_remote_state.privnet_dns_router.outputs.dns_zone + dns_zone_id = data.terraform_remote_state.privnet_dns_router.outputs.dns_zone_id + main_private_network_id = data.terraform_remote_state.privnet_dns_router.outputs.main_private_network_id + main_private_subnet_id = data.terraform_remote_state.privnet_dns_router.outputs.main_subnet_network_id + + # From the project setup state + default_security_group_id = data.terraform_remote_state.project_setup.outputs.default_security_group_id + basic_services_ip = data.terraform_remote_state.project_setup.outputs.basic_services_ip + main_haproxy_l7_ip = data.terraform_remote_state.project_setup.outputs.main_haproxy_l7_ip + main_loadbalancer_name = data.terraform_remote_state.project_setup.outputs.main_loadbalancer_hostname + + # From the postgresql state + postgresql_network_id = data.terraform_remote_state.postgresql.outputs.postgresql_network_id + postgresql_subnet_id = data.terraform_remote_state.postgresql.outputs.postgresql_subnet_id + postgresql_client_security_group_id = data.terraform_remote_state.postgresql.outputs.postgresql_client_access_security_group_id + + # From the common and project variables + availability_zone = module.labs_common_variables.availability_zones_names.availability_zone_no_gpu + ubuntu_2404 = module.labs_common_variables.ubuntu_2404 + ubuntu2404_data_file = module.labs_common_variables.ubuntu2404_data_file + keycloak_ip = module.project_variables.keycloak_ip +} + +module "keycloak" { + source = "../../modules/keycloak" + + # Address plan of the project. The sizing comes from the module defaults + keycloak_ip = local.keycloak_ip + + main_private_network_id = local.main_private_network_id + main_private_subnet_id = local.main_private_subnet_id + default_security_group_id = local.default_security_group_id + haproxy_l7_ip = local.main_haproxy_l7_ip + prometheus_cidr = local.basic_services_ip.prometheus_cidr + + postgresql_network_id = local.postgresql_network_id + postgresql_subnet_id = local.postgresql_subnet_id + postgresql_client_security_group_id = local.postgresql_client_security_group_id + + availability_zone = local.availability_zone + image = { + uuid = local.ubuntu_2404.uuid + user_data_file = local.ubuntu2404_data_file + } + ssh_key_name = module.ssh_settings.ssh_key_name + + # The service is published by the main load balancer, so the public name is a + # CNAME to it + dns_zone_id = local.dns_zone_id + keycloak_cname_target = local.main_loadbalancer_name + keycloak_recordsets = { + accounts = { + name = "accounts.${local.dns_zone.name}" + description = "Keycloak of the S2I2S project, published by the main load balancer" + } + } +} diff --git a/s2i2s/keycloak/outputs.tf b/s2i2s/keycloak/outputs.tf new file mode 100644 index 0000000..2278e5e --- /dev/null +++ b/s2i2s/keycloak/outputs.tf @@ -0,0 +1,42 @@ +output "keycloak_instance_ids" { + value = module.keycloak.keycloak_instance_ids +} + +output "keycloak_instance_names" { + value = module.keycloak.keycloak_instance_names +} + +output "keycloak_data" { + value = module.keycloak.keycloak_data +} + +output "keycloak_ip" { + description = "Addresses on the main private network. Used by the ansible inventory" + value = module.keycloak.keycloak_ip +} + +output "keycloak_postgresql_ip" { + description = "Addresses on the dedicated network of the database" + value = module.keycloak.keycloak_postgresql_ip +} + +output "keycloak_server_group_id" { + value = module.keycloak.keycloak_server_group_id +} + +output "keycloak_cluster_security_group_id" { + value = module.keycloak.keycloak_cluster_security_group_id +} + +output "traffic_to_keycloak_security_group_id" { + value = module.keycloak.traffic_to_keycloak_security_group_id +} + +output "keycloak_recordsets" { + value = module.keycloak.keycloak_recordsets +} + +# Re-exported for the ansible inventory generator +output "dns_zone" { + value = local.dns_zone +} diff --git a/s2i2s/keycloak/provider.tf b/s2i2s/keycloak/provider.tf new file mode 100644 index 0000000..a890a41 --- /dev/null +++ b/s2i2s/keycloak/provider.tf @@ -0,0 +1,14 @@ +# Define required providers +terraform { + required_version = ">= 0.14.0" + required_providers { + openstack = { + source = "terraform-provider-openstack/openstack" + version = ">= 2.0.0" + } + } +} + +provider "openstack" { + cloud = "s2i2s" +} diff --git a/s2i2s/keycloak/terraform.tfstate b/s2i2s/keycloak/terraform.tfstate new file mode 100644 index 0000000..fa5a5e9 --- /dev/null +++ b/s2i2s/keycloak/terraform.tfstate @@ -0,0 +1 @@ +{"version":4,"terraform_version":"1.11.6","serial":4,"lineage":"61dd07fa-7dc6-1c49-cb67-1d9e38743f84","outputs":{"dns_zone":{"value":{"attributes":{},"description":"DNS primary zone for the S2I2S project","disable_status_check":false,"email":"postmaster@isti.cnr.it","id":"e826e777-0196-4f63-b2a9-df07f70e618f","masters":[],"name":"s2i2s.cloud.isti.cnr.it.","project_id":"d0dcc2b7f3004c9a81b87ab60ec3c0d3","region":"isti_area_pi_1","timeouts":null,"ttl":8600,"type":"PRIMARY","value_specs":null},"type":["object",{"attributes":["map","string"],"description":"string","disable_status_check":"bool","email":"string","id":"string","masters":["set","string"],"name":"string","project_id":"string","region":"string","timeouts":["object",{"create":"string","delete":"string","update":"string"}],"ttl":"number","type":"string","value_specs":["map","string"]}]},"keycloak_cluster_security_group_id":{"value":"84c010c6-64c3-4f7a-91f6-e274b5fb1c67","type":"string"},"keycloak_data":{"value":{"affinity_policy":"anti-affinity","boot_vol_size":30,"flavor":"m1.medium","https_port":9443,"management_port":9000,"srv_name":"keycloak","vm_count":2},"type":["object",{"affinity_policy":"string","boot_vol_size":"number","flavor":"string","https_port":"number","management_port":"number","srv_name":"string","vm_count":"number"}]},"keycloak_instance_ids":{"value":["6b8ccc76-08f8-476c-b769-618f70925ba6","399aeff4-f6a7-4cd1-a73c-91722191afe4"],"type":["tuple",["string","string"]]},"keycloak_instance_names":{"value":["keycloak-01","keycloak-02"],"type":["tuple",["string","string"]]},"keycloak_ip":{"value":["10.10.0.163","10.10.0.164"],"type":["list","string"]},"keycloak_postgresql_ip":{"value":[["192.168.1.83"],["192.168.3.83"]],"type":["tuple",[["list","string"],["list","string"]]]},"keycloak_recordsets":{"value":{"accounts":{"description":"Keycloak of the S2I2S project, published by the main load balancer","name":"accounts.s2i2s.cloud.isti.cnr.it."}},"type":["map",["object",{"description":"string","name":"string"}]]},"keycloak_server_group_id":{"value":"9c9cdfbb-50ee-4503-8143-363fddb755f6","type":"string"},"traffic_to_keycloak_security_group_id":{"value":"f5b3b6d6-a0ca-4cb8-81f2-eaaa3052cfcb","type":"string"}},"resources":[{"mode":"data","type":"terraform_remote_state","name":"postgresql","provider":"provider[\"terraform.io/builtin/terraform\"]","instances":[{"schema_version":0,"attributes":{"backend":"local","config":{"value":{"path":"../postgresql/terraform.tfstate"},"type":["object",{"path":"string"}]},"defaults":null,"outputs":{"value":{"dns_zone":{"attributes":{},"description":"DNS primary zone for the S2I2S project","disable_status_check":false,"email":"postmaster@isti.cnr.it","id":"e826e777-0196-4f63-b2a9-df07f70e618f","masters":[],"name":"s2i2s.cloud.isti.cnr.it.","project_id":"d0dcc2b7f3004c9a81b87ab60ec3c0d3","region":"isti_area_pi_1","timeouts":null,"ttl":8600,"type":"PRIMARY","value_specs":null},"postgresql_access_security_group_id":"d23b5c1b-ec2f-4dd3-9f1d-b4936d4e45b8","postgresql_client_access_security_group_id":"09df1cb3-0654-47a0-be50-55bb79b011c9","postgresql_client_access_security_group_name":"vm_access_to_the_postgresql_service","postgresql_main_ip":"10.10.0.162","postgresql_network":{"admin_state_up":true,"all_tags":[],"availability_zone_hints":[],"description":"Network used to communicate with the postgresql service","dns_domain":"s2i2s.cloud.isti.cnr.it.","external":false,"id":"2b4f3653-5016-427f-9ae2-31144f691a93","mtu":8942,"name":"postgresql-srv-net","port_security_enabled":true,"qos_policy_id":"","region":"isti_area_pi_1","segments":[],"shared":false,"tags":null,"tenant_id":"d0dcc2b7f3004c9a81b87ab60ec3c0d3","timeouts":null,"transparent_vlan":false,"value_specs":null},"postgresql_network_id":"2b4f3653-5016-427f-9ae2-31144f691a93","postgresql_port":5432,"postgresql_server_data":{"allocation_pool_end":"192.168.3.254","allocation_pool_start":"192.168.0.100","boot_vol_size":20,"description":"PostgreSQL server","flavor":"m1.large","name":"postgresql","network_cidr":"192.168.0.0/22","network_description":"Network used to communicate with the postgresql service","network_name":"postgresql-srv-net","port":5432,"server_cidr":"192.168.0.5/32","server_ip":"192.168.0.5","subnet_description":"Subnet used to connect to the postgresql service","subnet_name":"postgresql-srv-subnet","vol_data_device":"/dev/vdb","vol_data_name":"postgresql-data","vol_data_size":100,"vol_wal_device":"/dev/vdc","vol_wal_name":"postgresql-wal","vol_wal_size":100,"volume_type":"CephSSD"},"postgresql_server_id":"1078fcff-0eee-48a7-b061-a2ceaedc844c","postgresql_server_ip":"192.168.0.5","postgresql_server_name":"postgresql","postgresql_subnet":{"all_tags":[],"allocation_pool":[{"end":"192.168.3.254","start":"192.168.0.100"}],"cidr":"192.168.0.0/22","description":"Subnet used to connect to the postgresql service","dns_nameservers":["146.48.29.97","146.48.29.98","146.48.29.99"],"dns_publish_fixed_ip":false,"enable_dhcp":true,"gateway_ip":"","id":"228da08f-2b49-4d76-bec4-abab0510f275","ip_version":4,"ipv6_address_mode":"","ipv6_ra_mode":"","name":"postgresql-srv-subnet","network_id":"2b4f3653-5016-427f-9ae2-31144f691a93","no_gateway":true,"prefix_length":null,"region":"isti_area_pi_1","segment_id":"","service_types":[],"subnetpool_id":"","tags":null,"tenant_id":"d0dcc2b7f3004c9a81b87ab60ec3c0d3","timeouts":null,"value_specs":null},"postgresql_subnet_id":"228da08f-2b49-4d76-bec4-abab0510f275"},"type":["object",{"dns_zone":["object",{"attributes":["map","string"],"description":"string","disable_status_check":"bool","email":"string","id":"string","masters":["set","string"],"name":"string","project_id":"string","region":"string","timeouts":["object",{"create":"string","delete":"string","update":"string"}],"ttl":"number","type":"string","value_specs":["map","string"]}],"postgresql_access_security_group_id":"string","postgresql_client_access_security_group_id":"string","postgresql_client_access_security_group_name":"string","postgresql_main_ip":"string","postgresql_network":["object",{"admin_state_up":"bool","all_tags":["set","string"],"availability_zone_hints":["set","string"],"description":"string","dns_domain":"string","external":"bool","id":"string","mtu":"number","name":"string","port_security_enabled":"bool","qos_policy_id":"string","region":"string","segments":["set",["object",{"network_type":"string","physical_network":"string","segmentation_id":"number"}]],"shared":"bool","tags":["set","string"],"tenant_id":"string","timeouts":["object",{"create":"string","delete":"string"}],"transparent_vlan":"bool","value_specs":["map","string"]}],"postgresql_network_id":"string","postgresql_port":"number","postgresql_server_data":["object",{"allocation_pool_end":"string","allocation_pool_start":"string","boot_vol_size":"number","description":"string","flavor":"string","name":"string","network_cidr":"string","network_description":"string","network_name":"string","port":"number","server_cidr":"string","server_ip":"string","subnet_description":"string","subnet_name":"string","vol_data_device":"string","vol_data_name":"string","vol_data_size":"number","vol_wal_device":"string","vol_wal_name":"string","vol_wal_size":"number","volume_type":"string"}],"postgresql_server_id":"string","postgresql_server_ip":"string","postgresql_server_name":"string","postgresql_subnet":["object",{"all_tags":["set","string"],"allocation_pool":["set",["object",{"end":"string","start":"string"}]],"cidr":"string","description":"string","dns_nameservers":["list","string"],"dns_publish_fixed_ip":"bool","enable_dhcp":"bool","gateway_ip":"string","id":"string","ip_version":"number","ipv6_address_mode":"string","ipv6_ra_mode":"string","name":"string","network_id":"string","no_gateway":"bool","prefix_length":"number","region":"string","segment_id":"string","service_types":["list","string"],"subnetpool_id":"string","tags":["set","string"],"tenant_id":"string","timeouts":["object",{"create":"string","delete":"string"}],"value_specs":["map","string"]}],"postgresql_subnet_id":"string"}]},"workspace":null},"sensitive_attributes":[]}]},{"mode":"data","type":"terraform_remote_state","name":"privnet_dns_router","provider":"provider[\"terraform.io/builtin/terraform\"]","instances":[{"schema_version":0,"attributes":{"backend":"local","config":{"value":{"path":"../main_net_dns_router/terraform.tfstate"},"type":["object",{"path":"string"}]},"defaults":null,"outputs":{"value":{"almalinux_9":{"name":"AlmaLinux-9.8 20260526","user_data_file":"../../s2i2s_openstack_vm_data_scripts/almalinux9.sh","uuid":"172f1c52-fa06-4d7d-9db7-0735ab6ef403"},"availability_zone_no_gpu_name":"cnr-isti-nova-a","availability_zone_with_gpu_name":"cnr-isti-nova-gpu-a","availability_zones_names":{"availability_zone_no_gpu":"cnr-isti-nova-a","availability_zone_with_gpu":"cnr-isti-nova-gpu-a"},"centos_7":{"name":"CentOS-7","user_data_file":"../../s2i2s_openstack_vm_data_scripts/el.sh","uuid":"f0187a99-64f6-462a-ab5f-ef52fe62f2ca"},"default_security_group_name":"default_for_all","dns_zone":{"attributes":{},"description":"DNS primary zone for the S2I2S project","disable_status_check":false,"email":"postmaster@isti.cnr.it","id":"e826e777-0196-4f63-b2a9-df07f70e618f","masters":[],"name":"s2i2s.cloud.isti.cnr.it.","project_id":"d0dcc2b7f3004c9a81b87ab60ec3c0d3","region":"isti_area_pi_1","timeouts":null,"ttl":8600,"type":"PRIMARY","value_specs":null},"dns_zone_id":"e826e777-0196-4f63-b2a9-df07f70e618f","el7_data_file":"../../s2i2s_openstack_vm_data_scripts/el.sh","external_gateway_ip":[{"ip_address":"146.48.30.6","subnet_id":"57f87509-4016-46fb-b8c3-25fca7f72ccb"}],"external_network":{"id":"1d2ff137-6ff7-4017-be2b-0d6c4af2353b","name":"external-network"},"external_network_id":"1d2ff137-6ff7-4017-be2b-0d6c4af2353b","flavor_list":{"c1_large":"c1.large","c1_medium":"c1.medium","c1_small":"c1.small","c2_large":"c2.large","m1_large":"m1.large","m1_medium":"m1.medium","m1_xlarge":"m1.xlarge","m1_xxl":"m1.xxl","m2_large":"m2.large","m2_medium":"m2.medium","m2_small":"m2.small","m3_large":"m3.large"},"floating_ip_pools":{"main_public_ip_pool":"external-network"},"main_private_network":{"admin_state_up":true,"all_tags":[],"availability_zone_hints":[],"description":"S2I2S private network (use this as the main network)","dns_domain":"s2i2s.cloud.isti.cnr.it.","external":false,"id":"f371c239-6d5d-4ac8-a17e-af607752d82c","mtu":8942,"name":"s2i2s-proj-main","port_security_enabled":true,"qos_policy_id":"","region":"isti_area_pi_1","segments":[{"network_type":"geneve","physical_network":"","segmentation_id":47850}],"shared":false,"tags":[],"tenant_id":"d0dcc2b7f3004c9a81b87ab60ec3c0d3","timeouts":null,"transparent_vlan":false,"value_specs":null},"main_private_network_id":"f371c239-6d5d-4ac8-a17e-af607752d82c","main_region":"isti_area_pi_1","main_subnet_network":{"all_tags":[],"allocation_pool":[{"end":"10.10.7.254","start":"10.10.1.1"}],"cidr":"10.10.0.0/21","description":"S2I2S main private subnet","dns_nameservers":["146.48.29.97","146.48.29.98","146.48.29.99"],"dns_publish_fixed_ip":false,"enable_dhcp":true,"gateway_ip":"10.10.0.1","id":"19c649ee-96ea-438b-ac0c-512afdf5046d","ip_version":4,"ipv6_address_mode":"","ipv6_ra_mode":"","name":"s2i2s-proj-main-subnet","network_id":"f371c239-6d5d-4ac8-a17e-af607752d82c","no_gateway":false,"prefix_length":null,"region":"isti_area_pi_1","segment_id":"","service_types":[],"subnetpool_id":"","tags":[],"tenant_id":"d0dcc2b7f3004c9a81b87ab60ec3c0d3","timeouts":null,"value_specs":null},"main_subnet_network_id":"19c649ee-96ea-438b-ac0c-512afdf5046d","mtu_size":8942,"os_project_data":{"id":"d0dcc2b7f3004c9a81b87ab60ec3c0d3","name":"s2i2s-proj-cloud"},"policy_list":{"affinity":"affinity","anti_affinity":"anti-affinity","soft_affinity":"soft-affinity","soft_anti_affinity":"soft-anti-affinity"},"resolvers_ip":["146.48.29.97","146.48.29.98","146.48.29.99"],"ssh_sources":{"d4s_vpn_1_cidr":"146.48.122.27/32","d4s_vpn_2_cidr":"146.48.122.49/32","infrascience_net_cidr":"146.48.122.0/23","isti_net_cidr":"146.48.80.0/21","isti_vpn_gw1":"146.48.80.101/32","isti_vpn_gw2":"146.48.80.102/32","isti_vpn_gw3":"146.48.80.103/32","s2i2s_net_cidr":"146.48.28.0/22","s2i2s_vpn_1_cidr":"146.48.28.10/32","s2i2s_vpn_2_cidr":"146.48.28.11/32","shell_d4s_cidr":"146.48.122.95/32"},"ubuntu2204_data_file":"../../s2i2s_openstack_vm_data_scripts/ubuntu2204.sh","ubuntu_2204":{"name":"Ubuntu-Jammy-22.04","user_data_file":"../../s2i2s_openstack_vm_data_scripts/ubuntu2204.sh","uuid":"54768889-8556-4be4-a2eb-82a4d9b34627"}},"type":["object",{"almalinux_9":["map","string"],"availability_zone_no_gpu_name":"string","availability_zone_with_gpu_name":"string","availability_zones_names":["map","string"],"centos_7":["map","string"],"default_security_group_name":"string","dns_zone":["object",{"attributes":["map","string"],"description":"string","disable_status_check":"bool","email":"string","id":"string","masters":["set","string"],"name":"string","project_id":"string","region":"string","timeouts":["object",{"create":"string","delete":"string","update":"string"}],"ttl":"number","type":"string","value_specs":["map","string"]}],"dns_zone_id":"string","el7_data_file":"string","external_gateway_ip":["list",["object",{"ip_address":"string","subnet_id":"string"}]],"external_network":["map","string"],"external_network_id":"string","flavor_list":["map","string"],"floating_ip_pools":["map","string"],"main_private_network":["object",{"admin_state_up":"bool","all_tags":["set","string"],"availability_zone_hints":["set","string"],"description":"string","dns_domain":"string","external":"bool","id":"string","mtu":"number","name":"string","port_security_enabled":"bool","qos_policy_id":"string","region":"string","segments":["set",["object",{"network_type":"string","physical_network":"string","segmentation_id":"number"}]],"shared":"bool","tags":["set","string"],"tenant_id":"string","timeouts":["object",{"create":"string","delete":"string"}],"transparent_vlan":"bool","value_specs":["map","string"]}],"main_private_network_id":"string","main_region":"string","main_subnet_network":["object",{"all_tags":["set","string"],"allocation_pool":["set",["object",{"end":"string","start":"string"}]],"cidr":"string","description":"string","dns_nameservers":["list","string"],"dns_publish_fixed_ip":"bool","enable_dhcp":"bool","gateway_ip":"string","id":"string","ip_version":"number","ipv6_address_mode":"string","ipv6_ra_mode":"string","name":"string","network_id":"string","no_gateway":"bool","prefix_length":"number","region":"string","segment_id":"string","service_types":["list","string"],"subnetpool_id":"string","tags":["set","string"],"tenant_id":"string","timeouts":["object",{"create":"string","delete":"string"}],"value_specs":["map","string"]}],"main_subnet_network_id":"string","mtu_size":"number","os_project_data":["map","string"],"policy_list":["map","string"],"resolvers_ip":["list","string"],"ssh_sources":["map","string"],"ubuntu2204_data_file":"string","ubuntu_2204":["map","string"]}]},"workspace":null},"sensitive_attributes":[]}]},{"mode":"data","type":"terraform_remote_state","name":"project_setup","provider":"provider[\"terraform.io/builtin/terraform\"]","instances":[{"schema_version":0,"attributes":{"backend":"local","config":{"value":{"path":"../project-setup/terraform.tfstate"},"type":["object",{"path":"string"}]},"defaults":null,"outputs":{"value":{"access_to_the_jump_proxy":{"all_tags":[],"delete_default_rules":true,"description":"Security group that allows SSH access to the jump node from a limited set of sources","id":"4c6b6683-77fa-4d1a-8ba2-41acf10a12ba","name":"ssh_access_to_the_jump_node","region":"isti_area_pi_1","stateful":false,"tags":[],"tenant_id":"d0dcc2b7f3004c9a81b87ab60ec3c0d3","timeouts":null},"acme_challenge_hostname":"_acme-challenge.s2i2s.cloud.isti.cnr.it.","availability_zones_names":{"availability_zone_no_gpu":"cnr-isti-nova-a","availability_zone_with_gpu":"cnr-isti-nova-gpu-a"},"basic_services_ip":{"ca":"10.10.0.4","ca_cidr":"10.10.0.4/32","forgejo":"10.10.0.165","forgejo_cidr":"10.10.0.165/32","haproxy_l7_1":"10.10.0.11","haproxy_l7_1_cidr":"10.10.0.11/32","haproxy_l7_2":"10.10.0.12","haproxy_l7_2_cidr":"10.10.0.12/32","keycloak_1":"10.10.0.163","keycloak_1_cidr":"10.10.0.163/32","keycloak_2":"10.10.0.164","keycloak_2_cidr":"10.10.0.164/32","octavia_main":"10.10.0.20","octavia_main_cidr":"10.10.0.20/32","postgresql":"10.10.0.162","postgresql_cidr":"10.10.0.162/32","prometheus":"10.10.0.10","prometheus_cidr":"10.10.0.10/32","ssh_jump":"10.10.0.5","ssh_jump_cidr":"10.10.0.5/32"},"debugging":{"all_tags":[],"delete_default_rules":true,"description":"Security group that allows web app debugging via tunnel from the ssh jump node","id":"6c21f51b-9cad-4051-99b6-221bed658a83","name":"debugging_from_jump_node","region":"isti_area_pi_1","stateful":false,"tags":[],"tenant_id":"d0dcc2b7f3004c9a81b87ab60ec3c0d3","timeouts":null},"default_security_group":{"all_tags":[],"delete_default_rules":true,"description":"Default security group with rules for ssh access via jump proxy, prometheus scraping","id":"1ec8a419-f9cf-473f-a022-6499d67d57b8","name":"default_for_all","region":"isti_area_pi_1","stateful":false,"tags":[],"tenant_id":"d0dcc2b7f3004c9a81b87ab60ec3c0d3","timeouts":null},"default_security_group_id":"1ec8a419-f9cf-473f-a022-6499d67d57b8","default_security_group_name":"default_for_all","dns_zone":{"attributes":{},"description":"DNS primary zone for the S2I2S project","disable_status_check":false,"email":"postmaster@isti.cnr.it","id":"e826e777-0196-4f63-b2a9-df07f70e618f","masters":[],"name":"s2i2s.cloud.isti.cnr.it.","project_id":"d0dcc2b7f3004c9a81b87ab60ec3c0d3","region":"isti_area_pi_1","timeouts":null,"ttl":8600,"type":"PRIMARY","value_specs":null},"dns_zone_id":"e826e777-0196-4f63-b2a9-df07f70e618f","floating_ip_pools":{"main_public_ip_pool":"external-network"},"haproxy_l7_data":{"flavor":"m1.medium","name":"main-haproxy-l7","vm_count":"2"},"internal_ca_data":{"flavor":"m1.small","name":"ca"},"internal_ca_id":"286b7a4d-33c6-451f-9019-d9fd79265181","main_haproxy_l7_ids":["b42a0e99-6172-4a5d-886c-c0fb016da60e","b770644a-5c39-4db2-8811-fb62751bd789"],"main_haproxy_l7_ip":["10.10.0.11","10.10.0.12"],"main_lb_to_haproxy_l7_security_group":{"all_tags":[],"delete_default_rules":true,"description":"Traffic coming from the main L4 lb (OVN provider, client IP is preserved) directed to the haproxy l7 servers","id":"613cacac-ac46-46ab-ba7a-d66f61cce84d","name":"traffic_from_main_lb_to_haproxy_l7","region":"isti_area_pi_1","stateful":false,"tags":[],"tenant_id":"d0dcc2b7f3004c9a81b87ab60ec3c0d3","timeouts":null},"main_loadbalancer_hostname":"main-lb.s2i2s.cloud.isti.cnr.it.","main_loadbalancer_id":"44dbe548-a436-4816-927a-2912f443b50f","main_loadbalancer_ip":"10.10.0.20","main_loadbalancer_public_ip":"146.48.30.30","main_private_network":{"admin_state_up":true,"all_tags":[],"availability_zone_hints":[],"description":"S2I2S private network (use this as the main network)","dns_domain":"s2i2s.cloud.isti.cnr.it.","external":false,"id":"f371c239-6d5d-4ac8-a17e-af607752d82c","mtu":8942,"name":"s2i2s-proj-main","port_security_enabled":true,"qos_policy_id":"","region":"isti_area_pi_1","segments":[{"network_type":"geneve","physical_network":"","segmentation_id":47850}],"shared":false,"tags":[],"tenant_id":"d0dcc2b7f3004c9a81b87ab60ec3c0d3","timeouts":null,"transparent_vlan":false,"value_specs":null},"main_private_subnet":{"all_tags":[],"allocation_pool":[{"end":"10.10.7.254","start":"10.10.1.1"}],"cidr":"10.10.0.0/21","description":"S2I2S main private subnet","dns_nameservers":["146.48.29.97","146.48.29.98","146.48.29.99"],"dns_publish_fixed_ip":false,"enable_dhcp":true,"gateway_ip":"10.10.0.1","id":"19c649ee-96ea-438b-ac0c-512afdf5046d","ip_version":4,"ipv6_address_mode":"","ipv6_ra_mode":"","name":"s2i2s-proj-main-subnet","network_id":"f371c239-6d5d-4ac8-a17e-af607752d82c","no_gateway":false,"prefix_length":null,"region":"isti_area_pi_1","segment_id":"","service_types":[],"subnetpool_id":"","tags":[],"tenant_id":"d0dcc2b7f3004c9a81b87ab60ec3c0d3","timeouts":null,"value_specs":null},"main_region":"isti_area_pi_1","main_subnet_network_id":"19c649ee-96ea-438b-ac0c-512afdf5046d","mtu_size":8942,"os_project_data":{"id":"d0dcc2b7f3004c9a81b87ab60ec3c0d3","name":"s2i2s-proj-cloud"},"prometheus_access_from_grafana":{"all_tags":[],"delete_default_rules":true,"description":"The public grafana server must be able to get data from Prometheus","id":"48e9366f-23a8-47df-abcd-66f84d4af395","name":"prometheus_access_from_grafana","region":"isti_area_pi_1","stateful":false,"tags":[],"tenant_id":"d0dcc2b7f3004c9a81b87ab60ec3c0d3","timeouts":null},"prometheus_hostname":"prometheus.s2i2s.cloud.isti.cnr.it.","prometheus_public_ip":"146.48.31.67","prometheus_server_data":{"flavor":"m1.medium","name":"prometheus","public_grafana_server_cidr":"146.48.28.103/32","vol_data_device":"/dev/vdb","vol_data_name":"prometheus-data","vol_data_size":"100"},"prometheus_server_id":"d2a37e7c-3eaa-4929-b70d-cfb55416d8bc","public_web":{"all_tags":[],"delete_default_rules":true,"description":"Security group that allows HTTPS and HTTP from everywhere, for the services that are not behind any load balancer","id":"31140e64-667a-4044-b388-79afcc6bcb69","name":"public_web_service","region":"isti_area_pi_1","stateful":false,"tags":[],"tenant_id":"d0dcc2b7f3004c9a81b87ab60ec3c0d3","timeouts":null},"resolvers_ip":["146.48.29.97","146.48.29.98","146.48.29.99"],"restricted_web":{"all_tags":[],"delete_default_rules":true,"description":"Security group that restricts HTTPS sources to the VPN nodes and shell.d4science.org. HTTP is open to all, because letsencrypt","id":"359d7ae7-cdff-47c2-bf69-7d423860d2d2","name":"restricted_web_service","region":"isti_area_pi_1","stateful":false,"tags":[],"tenant_id":"d0dcc2b7f3004c9a81b87ab60ec3c0d3","timeouts":null},"ssh_jump_proxy":{"flavor":"m2.small","name":"ssh-jump-proxy"},"ssh_jump_proxy_hostname":"ssh-jump-proxy.s2i2s.cloud.isti.cnr.it.","ssh_jump_proxy_id":"6aed1634-ec4e-43b0-a8c6-2da42a27ad25","ssh_jump_proxy_public_ip":"146.48.31.105","ssh_sources":{"d4s_vpn_1_cidr":"146.48.122.27/32","d4s_vpn_2_cidr":"146.48.122.49/32","infrascience_net_cidr":"146.48.122.0/23","isti_net_cidr":"146.48.80.0/21","isti_vpn_gw1":"146.48.80.101/32","isti_vpn_gw2":"146.48.80.102/32","isti_vpn_gw3":"146.48.80.103/32","s2i2s_net_cidr":"146.48.28.0/22","s2i2s_vpn_1_cidr":"146.48.28.10/32","s2i2s_vpn_2_cidr":"146.48.28.11/32","shell_d4s_cidr":"146.48.122.95/32"},"traffic_from_main_haproxy":{"all_tags":[],"delete_default_rules":true,"description":"Allow traffic from the main L7 HAPROXY load balancers","id":"56ba7585-659a-49ac-8d8e-c85ebcb1179f","name":"traffic_from_the_main_load_balancers","region":"isti_area_pi_1","stateful":false,"tags":[],"tenant_id":"d0dcc2b7f3004c9a81b87ab60ec3c0d3","timeouts":null},"ubuntu2204_data_file":"../../s2i2s_openstack_vm_data_scripts/ubuntu2204.sh","ubuntu2404_data_file":"../../s2i2s_openstack_vm_data_scripts/ubuntu2404.sh","ubuntu_2204":{"name":"Ubuntu-Jammy-22.04","user_data_file":"../../s2i2s_openstack_vm_data_scripts/ubuntu2204.sh","uuid":"54768889-8556-4be4-a2eb-82a4d9b34627"},"ubuntu_2404":{"name":"Ubuntu-Noble-24.04.img","user_data_file":"../../s2i2s_openstack_vm_data_scripts/ubuntu2404.sh","uuid":"fc3f705d-3cf5-4866-8ef6-ff6e2cdd4075"}},"type":["object",{"access_to_the_jump_proxy":["object",{"all_tags":["set","string"],"delete_default_rules":"bool","description":"string","id":"string","name":"string","region":"string","stateful":"bool","tags":["set","string"],"tenant_id":"string","timeouts":["object",{"delete":"string"}]}],"acme_challenge_hostname":"string","availability_zones_names":["map","string"],"basic_services_ip":["map","string"],"debugging":["object",{"all_tags":["set","string"],"delete_default_rules":"bool","description":"string","id":"string","name":"string","region":"string","stateful":"bool","tags":["set","string"],"tenant_id":"string","timeouts":["object",{"delete":"string"}]}],"default_security_group":["object",{"all_tags":["set","string"],"delete_default_rules":"bool","description":"string","id":"string","name":"string","region":"string","stateful":"bool","tags":["set","string"],"tenant_id":"string","timeouts":["object",{"delete":"string"}]}],"default_security_group_id":"string","default_security_group_name":"string","dns_zone":["object",{"attributes":["map","string"],"description":"string","disable_status_check":"bool","email":"string","id":"string","masters":["set","string"],"name":"string","project_id":"string","region":"string","timeouts":["object",{"create":"string","delete":"string","update":"string"}],"ttl":"number","type":"string","value_specs":["map","string"]}],"dns_zone_id":"string","floating_ip_pools":["map","string"],"haproxy_l7_data":["map","string"],"internal_ca_data":["map","string"],"internal_ca_id":"string","main_haproxy_l7_ids":["tuple",["string","string"]],"main_haproxy_l7_ip":["list","string"],"main_lb_to_haproxy_l7_security_group":["object",{"all_tags":["set","string"],"delete_default_rules":"bool","description":"string","id":"string","name":"string","region":"string","stateful":"bool","tags":["set","string"],"tenant_id":"string","timeouts":["object",{"delete":"string"}]}],"main_loadbalancer_hostname":"string","main_loadbalancer_id":"string","main_loadbalancer_ip":"string","main_loadbalancer_public_ip":"string","main_private_network":["object",{"admin_state_up":"bool","all_tags":["set","string"],"availability_zone_hints":["set","string"],"description":"string","dns_domain":"string","external":"bool","id":"string","mtu":"number","name":"string","port_security_enabled":"bool","qos_policy_id":"string","region":"string","segments":["set",["object",{"network_type":"string","physical_network":"string","segmentation_id":"number"}]],"shared":"bool","tags":["set","string"],"tenant_id":"string","timeouts":["object",{"create":"string","delete":"string"}],"transparent_vlan":"bool","value_specs":["map","string"]}],"main_private_subnet":["object",{"all_tags":["set","string"],"allocation_pool":["set",["object",{"end":"string","start":"string"}]],"cidr":"string","description":"string","dns_nameservers":["list","string"],"dns_publish_fixed_ip":"bool","enable_dhcp":"bool","gateway_ip":"string","id":"string","ip_version":"number","ipv6_address_mode":"string","ipv6_ra_mode":"string","name":"string","network_id":"string","no_gateway":"bool","prefix_length":"number","region":"string","segment_id":"string","service_types":["list","string"],"subnetpool_id":"string","tags":["set","string"],"tenant_id":"string","timeouts":["object",{"create":"string","delete":"string"}],"value_specs":["map","string"]}],"main_region":"string","main_subnet_network_id":"string","mtu_size":"number","os_project_data":["map","string"],"prometheus_access_from_grafana":["object",{"all_tags":["set","string"],"delete_default_rules":"bool","description":"string","id":"string","name":"string","region":"string","stateful":"bool","tags":["set","string"],"tenant_id":"string","timeouts":["object",{"delete":"string"}]}],"prometheus_hostname":"string","prometheus_public_ip":"string","prometheus_server_data":["map","string"],"prometheus_server_id":"string","public_web":["object",{"all_tags":["set","string"],"delete_default_rules":"bool","description":"string","id":"string","name":"string","region":"string","stateful":"bool","tags":["set","string"],"tenant_id":"string","timeouts":["object",{"delete":"string"}]}],"resolvers_ip":["list","string"],"restricted_web":["object",{"all_tags":["set","string"],"delete_default_rules":"bool","description":"string","id":"string","name":"string","region":"string","stateful":"bool","tags":["set","string"],"tenant_id":"string","timeouts":["object",{"delete":"string"}]}],"ssh_jump_proxy":["map","string"],"ssh_jump_proxy_hostname":"string","ssh_jump_proxy_id":"string","ssh_jump_proxy_public_ip":"string","ssh_sources":["map","string"],"traffic_from_main_haproxy":["object",{"all_tags":["set","string"],"delete_default_rules":"bool","description":"string","id":"string","name":"string","region":"string","stateful":"bool","tags":["set","string"],"tenant_id":"string","timeouts":["object",{"delete":"string"}]}],"ubuntu2204_data_file":"string","ubuntu2404_data_file":"string","ubuntu_2204":["map","string"],"ubuntu_2404":["map","string"]}]},"workspace":null},"sensitive_attributes":[]}]},{"module":"module.keycloak","mode":"managed","type":"openstack_compute_instance_v2","name":"keycloak","provider":"provider[\"registry.opentofu.org/terraform-provider-openstack/openstack\"]","instances":[{"index_key":0,"schema_version":0,"attributes":{"access_ip_v4":"10.10.0.163","access_ip_v6":"","admin_pass":null,"all_metadata":{},"all_tags":[],"availability_zone":"cnr-isti-nova-a","availability_zone_hints":"cnr-isti-nova-a","block_device":[{"boot_index":0,"delete_on_termination":false,"destination_type":"volume","device_type":"","disk_bus":"","guest_format":"","multiattach":false,"source_type":"image","uuid":"fc3f705d-3cf5-4866-8ef6-ff6e2cdd4075","volume_size":30,"volume_type":""}],"config_drive":null,"created":"2026-08-11 16:23:09 +0000 UTC","flavor_id":"4","flavor_name":"m1.medium","force_delete":false,"hypervisor_hostname":"","id":"6b8ccc76-08f8-476c-b769-618f70925ba6","image_id":"Attempt to boot from volume - no image supplied","image_name":null,"key_pair":"adellam","metadata":null,"name":"keycloak-01","network":[{"access_network":false,"fixed_ip_v4":"10.10.0.163","fixed_ip_v6":"","mac":"fa:16:3e:3b:77:97","name":"s2i2s-proj-main","port":"d04f70f3-aa9b-442a-b523-6a4f3c5575b1","uuid":"f371c239-6d5d-4ac8-a17e-af607752d82c"},{"access_network":false,"fixed_ip_v4":"192.168.1.83","fixed_ip_v6":"","mac":"fa:16:3e:9c:ef:f5","name":"postgresql-srv-net","port":"b05b2edf-c23b-4b30-bcaf-01adeb90a418","uuid":"2b4f3653-5016-427f-9ae2-31144f691a93"}],"network_mode":null,"personality":[],"power_state":"active","region":"isti_area_pi_1","scheduler_hints":[{"additional_properties":null,"build_near_host_ip":"","different_cell":[],"different_host":[],"group":"9c9cdfbb-50ee-4503-8143-363fddb755f6","query":[],"same_host":[],"target_cell":""}],"security_groups":["default_for_all","keycloak_cluster_traffic","traffic_to_keycloak_from_the_main_load_balancers","vm_access_to_the_postgresql_service"],"stop_before_destroy":false,"tags":null,"timeouts":null,"updated":"2026-08-11 16:24:24 +0000 UTC","user_data":"164cdf695f3b4a01a2f8b9dc0af2f87629bd89a7","vendor_options":[]},"sensitive_attributes":[[{"type":"get_attr","value":"admin_pass"}]],"private":"eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiY3JlYXRlIjoxODAwMDAwMDAwMDAwLCJkZWxldGUiOjE4MDAwMDAwMDAwMDAsInVwZGF0ZSI6MTgwMDAwMDAwMDAwMH19","dependencies":["data.terraform_remote_state.postgresql","data.terraform_remote_state.privnet_dns_router","data.terraform_remote_state.project_setup","module.keycloak.openstack_compute_servergroup_v2.keycloak","module.keycloak.openstack_networking_port_v2.keycloak_main_port","module.keycloak.openstack_networking_port_v2.keycloak_postgresql_port","module.keycloak.openstack_networking_secgroup_v2.keycloak_cluster_traffic","module.keycloak.openstack_networking_secgroup_v2.traffic_to_keycloak"]},{"index_key":1,"schema_version":0,"attributes":{"access_ip_v4":"10.10.0.164","access_ip_v6":"","admin_pass":null,"all_metadata":{},"all_tags":[],"availability_zone":"cnr-isti-nova-a","availability_zone_hints":"cnr-isti-nova-a","block_device":[{"boot_index":0,"delete_on_termination":false,"destination_type":"volume","device_type":"","disk_bus":"","guest_format":"","multiattach":false,"source_type":"image","uuid":"fc3f705d-3cf5-4866-8ef6-ff6e2cdd4075","volume_size":30,"volume_type":""}],"config_drive":null,"created":"2026-08-11 16:23:09 +0000 UTC","flavor_id":"4","flavor_name":"m1.medium","force_delete":false,"hypervisor_hostname":"","id":"399aeff4-f6a7-4cd1-a73c-91722191afe4","image_id":"Attempt to boot from volume - no image supplied","image_name":null,"key_pair":"adellam","metadata":null,"name":"keycloak-02","network":[{"access_network":false,"fixed_ip_v4":"10.10.0.164","fixed_ip_v6":"","mac":"fa:16:3e:97:69:9a","name":"s2i2s-proj-main","port":"76d1fe64-cb21-4931-a918-ba19fbb555db","uuid":"f371c239-6d5d-4ac8-a17e-af607752d82c"},{"access_network":false,"fixed_ip_v4":"192.168.3.83","fixed_ip_v6":"","mac":"fa:16:3e:d1:3c:26","name":"postgresql-srv-net","port":"1eae7d76-d39f-493b-abc6-44ddfe5a757b","uuid":"2b4f3653-5016-427f-9ae2-31144f691a93"}],"network_mode":null,"personality":[],"power_state":"active","region":"isti_area_pi_1","scheduler_hints":[{"additional_properties":null,"build_near_host_ip":"","different_cell":[],"different_host":[],"group":"9c9cdfbb-50ee-4503-8143-363fddb755f6","query":[],"same_host":[],"target_cell":""}],"security_groups":["default_for_all","keycloak_cluster_traffic","traffic_to_keycloak_from_the_main_load_balancers","vm_access_to_the_postgresql_service"],"stop_before_destroy":false,"tags":null,"timeouts":null,"updated":"2026-08-11 16:24:07 +0000 UTC","user_data":"164cdf695f3b4a01a2f8b9dc0af2f87629bd89a7","vendor_options":[]},"sensitive_attributes":[[{"type":"get_attr","value":"admin_pass"}]],"private":"eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiY3JlYXRlIjoxODAwMDAwMDAwMDAwLCJkZWxldGUiOjE4MDAwMDAwMDAwMDAsInVwZGF0ZSI6MTgwMDAwMDAwMDAwMH19","dependencies":["data.terraform_remote_state.postgresql","data.terraform_remote_state.privnet_dns_router","data.terraform_remote_state.project_setup","module.keycloak.openstack_compute_servergroup_v2.keycloak","module.keycloak.openstack_networking_port_v2.keycloak_main_port","module.keycloak.openstack_networking_port_v2.keycloak_postgresql_port","module.keycloak.openstack_networking_secgroup_v2.keycloak_cluster_traffic","module.keycloak.openstack_networking_secgroup_v2.traffic_to_keycloak"]}]},{"module":"module.keycloak","mode":"managed","type":"openstack_compute_servergroup_v2","name":"keycloak","provider":"provider[\"registry.opentofu.org/terraform-provider-openstack/openstack\"]","instances":[{"schema_version":0,"attributes":{"id":"9c9cdfbb-50ee-4503-8143-363fddb755f6","members":[],"name":"keycloak","policies":["anti-affinity"],"region":"isti_area_pi_1","rules":[{"max_server_per_host":0}],"value_specs":null},"sensitive_attributes":[],"private":"bnVsbA=="}]},{"module":"module.keycloak","mode":"managed","type":"openstack_dns_recordset_v2","name":"keycloak_recordset","provider":"provider[\"registry.opentofu.org/terraform-provider-openstack/openstack\"]","instances":[{"index_key":"accounts","schema_version":0,"attributes":{"description":"Keycloak of the S2I2S project, published by the main load balancer","disable_status_check":false,"id":"e826e777-0196-4f63-b2a9-df07f70e618f/697873fa-caf7-42bf-98ae-cdd3bea7a980","name":"accounts.s2i2s.cloud.isti.cnr.it.","project_id":"d0dcc2b7f3004c9a81b87ab60ec3c0d3","records":["main-lb.s2i2s.cloud.isti.cnr.it."],"region":"isti_area_pi_1","timeouts":null,"ttl":8600,"type":"CNAME","value_specs":null,"zone_id":"e826e777-0196-4f63-b2a9-df07f70e618f"},"sensitive_attributes":[],"private":"eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiY3JlYXRlIjo2MDAwMDAwMDAwMDAsImRlbGV0ZSI6NjAwMDAwMDAwMDAwLCJ1cGRhdGUiOjYwMDAwMDAwMDAwMH19","dependencies":["data.terraform_remote_state.privnet_dns_router","data.terraform_remote_state.project_setup"]}]},{"module":"module.keycloak","mode":"managed","type":"openstack_networking_port_v2","name":"keycloak_main_port","provider":"provider[\"registry.opentofu.org/terraform-provider-openstack/openstack\"]","instances":[{"index_key":0,"schema_version":0,"attributes":{"admin_state_up":true,"all_fixed_ips":["10.10.0.163"],"all_security_group_ids":["1ec8a419-f9cf-473f-a022-6499d67d57b8","84c010c6-64c3-4f7a-91f6-e274b5fb1c67","f5b3b6d6-a0ca-4cb8-81f2-eaaa3052cfcb"],"all_tags":[],"allowed_address_pairs":[],"binding":[{"host_id":"","profile":"","vif_details":{},"vif_type":"","vnic_type":"normal"}],"description":"Port of the keycloak instance on the main private network","device_id":"","device_owner":"","dns_assignment":[{"fqdn":"host-10-10-0-163.internal-cloud.isti.cnr.it.","hostname":"host-10-10-0-163","ip_address":"10.10.0.163"}],"dns_name":"","extra_dhcp_option":[],"fixed_ip":[{"ip_address":"10.10.0.163","subnet_id":"19c649ee-96ea-438b-ac0c-512afdf5046d"}],"id":"d04f70f3-aa9b-442a-b523-6a4f3c5575b1","mac_address":"fa:16:3e:3b:77:97","name":"keycloak-01-main-port","network_id":"f371c239-6d5d-4ac8-a17e-af607752d82c","no_fixed_ip":null,"no_security_groups":null,"port_security_enabled":true,"qos_policy_id":"","region":"isti_area_pi_1","security_group_ids":["1ec8a419-f9cf-473f-a022-6499d67d57b8","84c010c6-64c3-4f7a-91f6-e274b5fb1c67","f5b3b6d6-a0ca-4cb8-81f2-eaaa3052cfcb"],"tags":null,"tenant_id":"d0dcc2b7f3004c9a81b87ab60ec3c0d3","timeouts":null,"value_specs":null},"sensitive_attributes":[],"private":"eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiY3JlYXRlIjo2MDAwMDAwMDAwMDAsImRlbGV0ZSI6NjAwMDAwMDAwMDAwfX0=","dependencies":["data.terraform_remote_state.privnet_dns_router","data.terraform_remote_state.project_setup","module.keycloak.openstack_networking_secgroup_v2.keycloak_cluster_traffic","module.keycloak.openstack_networking_secgroup_v2.traffic_to_keycloak"]},{"index_key":1,"schema_version":0,"attributes":{"admin_state_up":true,"all_fixed_ips":["10.10.0.164"],"all_security_group_ids":["1ec8a419-f9cf-473f-a022-6499d67d57b8","84c010c6-64c3-4f7a-91f6-e274b5fb1c67","f5b3b6d6-a0ca-4cb8-81f2-eaaa3052cfcb"],"all_tags":[],"allowed_address_pairs":[],"binding":[{"host_id":"","profile":"","vif_details":{},"vif_type":"","vnic_type":"normal"}],"description":"Port of the keycloak instance on the main private network","device_id":"","device_owner":"","dns_assignment":[{"fqdn":"host-10-10-0-164.internal-cloud.isti.cnr.it.","hostname":"host-10-10-0-164","ip_address":"10.10.0.164"}],"dns_name":"","extra_dhcp_option":[],"fixed_ip":[{"ip_address":"10.10.0.164","subnet_id":"19c649ee-96ea-438b-ac0c-512afdf5046d"}],"id":"76d1fe64-cb21-4931-a918-ba19fbb555db","mac_address":"fa:16:3e:97:69:9a","name":"keycloak-02-main-port","network_id":"f371c239-6d5d-4ac8-a17e-af607752d82c","no_fixed_ip":null,"no_security_groups":null,"port_security_enabled":true,"qos_policy_id":"","region":"isti_area_pi_1","security_group_ids":["1ec8a419-f9cf-473f-a022-6499d67d57b8","84c010c6-64c3-4f7a-91f6-e274b5fb1c67","f5b3b6d6-a0ca-4cb8-81f2-eaaa3052cfcb"],"tags":null,"tenant_id":"d0dcc2b7f3004c9a81b87ab60ec3c0d3","timeouts":null,"value_specs":null},"sensitive_attributes":[],"private":"eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiY3JlYXRlIjo2MDAwMDAwMDAwMDAsImRlbGV0ZSI6NjAwMDAwMDAwMDAwfX0=","dependencies":["data.terraform_remote_state.privnet_dns_router","data.terraform_remote_state.project_setup","module.keycloak.openstack_networking_secgroup_v2.keycloak_cluster_traffic","module.keycloak.openstack_networking_secgroup_v2.traffic_to_keycloak"]}]},{"module":"module.keycloak","mode":"managed","type":"openstack_networking_port_v2","name":"keycloak_postgresql_port","provider":"provider[\"registry.opentofu.org/terraform-provider-openstack/openstack\"]","instances":[{"index_key":0,"schema_version":0,"attributes":{"admin_state_up":true,"all_fixed_ips":["192.168.1.83"],"all_security_group_ids":["09df1cb3-0654-47a0-be50-55bb79b011c9"],"all_tags":[],"allowed_address_pairs":[],"binding":[{"host_id":"","profile":"","vif_details":{},"vif_type":"","vnic_type":"normal"}],"description":"Port of the keycloak instance on the dedicated network of the database","device_id":"","device_owner":"","dns_assignment":[{"fqdn":"host-192-168-1-83.internal-cloud.isti.cnr.it.","hostname":"host-192-168-1-83","ip_address":"192.168.1.83"}],"dns_name":"","extra_dhcp_option":[],"fixed_ip":[{"ip_address":"","subnet_id":"228da08f-2b49-4d76-bec4-abab0510f275"}],"id":"b05b2edf-c23b-4b30-bcaf-01adeb90a418","mac_address":"fa:16:3e:9c:ef:f5","name":"keycloak-01-postgresql-port","network_id":"2b4f3653-5016-427f-9ae2-31144f691a93","no_fixed_ip":null,"no_security_groups":null,"port_security_enabled":true,"qos_policy_id":"","region":"isti_area_pi_1","security_group_ids":["09df1cb3-0654-47a0-be50-55bb79b011c9"],"tags":null,"tenant_id":"d0dcc2b7f3004c9a81b87ab60ec3c0d3","timeouts":null,"value_specs":null},"sensitive_attributes":[],"private":"eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiY3JlYXRlIjo2MDAwMDAwMDAwMDAsImRlbGV0ZSI6NjAwMDAwMDAwMDAwfX0=","dependencies":["data.terraform_remote_state.postgresql"]},{"index_key":1,"schema_version":0,"attributes":{"admin_state_up":true,"all_fixed_ips":["192.168.3.83"],"all_security_group_ids":["09df1cb3-0654-47a0-be50-55bb79b011c9"],"all_tags":[],"allowed_address_pairs":[],"binding":[{"host_id":"","profile":"","vif_details":{},"vif_type":"","vnic_type":"normal"}],"description":"Port of the keycloak instance on the dedicated network of the database","device_id":"","device_owner":"","dns_assignment":[{"fqdn":"host-192-168-3-83.internal-cloud.isti.cnr.it.","hostname":"host-192-168-3-83","ip_address":"192.168.3.83"}],"dns_name":"","extra_dhcp_option":[],"fixed_ip":[{"ip_address":"","subnet_id":"228da08f-2b49-4d76-bec4-abab0510f275"}],"id":"1eae7d76-d39f-493b-abc6-44ddfe5a757b","mac_address":"fa:16:3e:d1:3c:26","name":"keycloak-02-postgresql-port","network_id":"2b4f3653-5016-427f-9ae2-31144f691a93","no_fixed_ip":null,"no_security_groups":null,"port_security_enabled":true,"qos_policy_id":"","region":"isti_area_pi_1","security_group_ids":["09df1cb3-0654-47a0-be50-55bb79b011c9"],"tags":null,"tenant_id":"d0dcc2b7f3004c9a81b87ab60ec3c0d3","timeouts":null,"value_specs":null},"sensitive_attributes":[],"private":"eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiY3JlYXRlIjo2MDAwMDAwMDAwMDAsImRlbGV0ZSI6NjAwMDAwMDAwMDAwfX0=","dependencies":["data.terraform_remote_state.postgresql"]}]},{"module":"module.keycloak","mode":"managed","type":"openstack_networking_secgroup_rule_v2","name":"cluster_egress","provider":"provider[\"registry.opentofu.org/terraform-provider-openstack/openstack\"]","instances":[{"index_key":"10.10.0.163","schema_version":0,"attributes":{"description":"Traffic to the keycloak node 10.10.0.163","direction":"egress","ethertype":"IPv4","id":"fade595e-99e5-4681-b8e1-adb4b3947d49","port_range_max":0,"port_range_min":0,"protocol":"","region":"isti_area_pi_1","remote_address_group_id":"","remote_group_id":"","remote_ip_prefix":"10.10.0.163/32","security_group_id":"84c010c6-64c3-4f7a-91f6-e274b5fb1c67","tenant_id":"d0dcc2b7f3004c9a81b87ab60ec3c0d3","timeouts":null},"sensitive_attributes":[],"private":"eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiZGVsZXRlIjo2MDAwMDAwMDAwMDB9fQ==","dependencies":["module.keycloak.openstack_networking_secgroup_v2.keycloak_cluster_traffic"]},{"index_key":"10.10.0.164","schema_version":0,"attributes":{"description":"Traffic to the keycloak node 10.10.0.164","direction":"egress","ethertype":"IPv4","id":"405b5f61-3d94-4406-bec3-56a330e942d9","port_range_max":0,"port_range_min":0,"protocol":"","region":"isti_area_pi_1","remote_address_group_id":"","remote_group_id":"","remote_ip_prefix":"10.10.0.164/32","security_group_id":"84c010c6-64c3-4f7a-91f6-e274b5fb1c67","tenant_id":"d0dcc2b7f3004c9a81b87ab60ec3c0d3","timeouts":null},"sensitive_attributes":[],"private":"eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiZGVsZXRlIjo2MDAwMDAwMDAwMDB9fQ==","dependencies":["module.keycloak.openstack_networking_secgroup_v2.keycloak_cluster_traffic"]}]},{"module":"module.keycloak","mode":"managed","type":"openstack_networking_secgroup_rule_v2","name":"cluster_igmp_egress","provider":"provider[\"registry.opentofu.org/terraform-provider-openstack/openstack\"]","instances":[{"schema_version":0,"attributes":{"description":"Egress IGMP traffic between the keycloak nodes","direction":"egress","ethertype":"IPv4","id":"e88b9874-112b-4446-b38a-f6afc1c78784","port_range_max":0,"port_range_min":0,"protocol":"igmp","region":"isti_area_pi_1","remote_address_group_id":"","remote_group_id":"","remote_ip_prefix":"0.0.0.0/0","security_group_id":"84c010c6-64c3-4f7a-91f6-e274b5fb1c67","tenant_id":"d0dcc2b7f3004c9a81b87ab60ec3c0d3","timeouts":null},"sensitive_attributes":[],"private":"eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiZGVsZXRlIjo2MDAwMDAwMDAwMDB9fQ==","dependencies":["module.keycloak.openstack_networking_secgroup_v2.keycloak_cluster_traffic"]}]},{"module":"module.keycloak","mode":"managed","type":"openstack_networking_secgroup_rule_v2","name":"cluster_igmp_ingress","provider":"provider[\"registry.opentofu.org/terraform-provider-openstack/openstack\"]","instances":[{"schema_version":0,"attributes":{"description":"Ingress IGMP traffic between the keycloak nodes","direction":"ingress","ethertype":"IPv4","id":"c29ba6ef-3536-4600-aee7-f51ac9f0eaa1","port_range_max":0,"port_range_min":0,"protocol":"igmp","region":"isti_area_pi_1","remote_address_group_id":"","remote_group_id":"","remote_ip_prefix":"0.0.0.0/0","security_group_id":"84c010c6-64c3-4f7a-91f6-e274b5fb1c67","tenant_id":"d0dcc2b7f3004c9a81b87ab60ec3c0d3","timeouts":null},"sensitive_attributes":[],"private":"eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiZGVsZXRlIjo2MDAwMDAwMDAwMDB9fQ==","dependencies":["module.keycloak.openstack_networking_secgroup_v2.keycloak_cluster_traffic"]}]},{"module":"module.keycloak","mode":"managed","type":"openstack_networking_secgroup_rule_v2","name":"cluster_tcp","provider":"provider[\"registry.opentofu.org/terraform-provider-openstack/openstack\"]","instances":[{"index_key":"10.10.0.163","schema_version":0,"attributes":{"description":"TCP traffic from the keycloak node 10.10.0.163","direction":"ingress","ethertype":"IPv4","id":"3d515e1c-db8f-49c7-8a58-c093a7a4f8ab","port_range_max":0,"port_range_min":0,"protocol":"tcp","region":"isti_area_pi_1","remote_address_group_id":"","remote_group_id":"","remote_ip_prefix":"10.10.0.163/32","security_group_id":"84c010c6-64c3-4f7a-91f6-e274b5fb1c67","tenant_id":"d0dcc2b7f3004c9a81b87ab60ec3c0d3","timeouts":null},"sensitive_attributes":[],"private":"eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiZGVsZXRlIjo2MDAwMDAwMDAwMDB9fQ==","dependencies":["module.keycloak.openstack_networking_secgroup_v2.keycloak_cluster_traffic"]},{"index_key":"10.10.0.164","schema_version":0,"attributes":{"description":"TCP traffic from the keycloak node 10.10.0.164","direction":"ingress","ethertype":"IPv4","id":"584e09b7-68f9-45dc-ab83-2e486316a89f","port_range_max":0,"port_range_min":0,"protocol":"tcp","region":"isti_area_pi_1","remote_address_group_id":"","remote_group_id":"","remote_ip_prefix":"10.10.0.164/32","security_group_id":"84c010c6-64c3-4f7a-91f6-e274b5fb1c67","tenant_id":"d0dcc2b7f3004c9a81b87ab60ec3c0d3","timeouts":null},"sensitive_attributes":[],"private":"eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiZGVsZXRlIjo2MDAwMDAwMDAwMDB9fQ==","dependencies":["module.keycloak.openstack_networking_secgroup_v2.keycloak_cluster_traffic"]}]},{"module":"module.keycloak","mode":"managed","type":"openstack_networking_secgroup_rule_v2","name":"cluster_udp","provider":"provider[\"registry.opentofu.org/terraform-provider-openstack/openstack\"]","instances":[{"index_key":"10.10.0.163","schema_version":0,"attributes":{"description":"UDP traffic from the keycloak node 10.10.0.163","direction":"ingress","ethertype":"IPv4","id":"d91b3553-8995-4c56-bb6c-eb7533936828","port_range_max":0,"port_range_min":0,"protocol":"udp","region":"isti_area_pi_1","remote_address_group_id":"","remote_group_id":"","remote_ip_prefix":"10.10.0.163/32","security_group_id":"84c010c6-64c3-4f7a-91f6-e274b5fb1c67","tenant_id":"d0dcc2b7f3004c9a81b87ab60ec3c0d3","timeouts":null},"sensitive_attributes":[],"private":"eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiZGVsZXRlIjo2MDAwMDAwMDAwMDB9fQ==","dependencies":["module.keycloak.openstack_networking_secgroup_v2.keycloak_cluster_traffic"]},{"index_key":"10.10.0.164","schema_version":0,"attributes":{"description":"UDP traffic from the keycloak node 10.10.0.164","direction":"ingress","ethertype":"IPv4","id":"4c1f8b94-3432-4039-b74c-d828bda58cdf","port_range_max":0,"port_range_min":0,"protocol":"udp","region":"isti_area_pi_1","remote_address_group_id":"","remote_group_id":"","remote_ip_prefix":"10.10.0.164/32","security_group_id":"84c010c6-64c3-4f7a-91f6-e274b5fb1c67","tenant_id":"d0dcc2b7f3004c9a81b87ab60ec3c0d3","timeouts":null},"sensitive_attributes":[],"private":"eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiZGVsZXRlIjo2MDAwMDAwMDAwMDB9fQ==","dependencies":["module.keycloak.openstack_networking_secgroup_v2.keycloak_cluster_traffic"]}]},{"module":"module.keycloak","mode":"managed","type":"openstack_networking_secgroup_rule_v2","name":"haproxy_to_keycloak_https","provider":"provider[\"registry.opentofu.org/terraform-provider-openstack/openstack\"]","instances":[{"index_key":"10.10.0.11","schema_version":0,"attributes":{"description":"HTTPS traffic from the HAPROXY L7 10.10.0.11","direction":"ingress","ethertype":"IPv4","id":"5c7f02c3-eaf7-423e-9132-c7b69a3f56e0","port_range_max":9443,"port_range_min":9443,"protocol":"tcp","region":"isti_area_pi_1","remote_address_group_id":"","remote_group_id":"","remote_ip_prefix":"10.10.0.11/32","security_group_id":"f5b3b6d6-a0ca-4cb8-81f2-eaaa3052cfcb","tenant_id":"d0dcc2b7f3004c9a81b87ab60ec3c0d3","timeouts":null},"sensitive_attributes":[],"private":"eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiZGVsZXRlIjo2MDAwMDAwMDAwMDB9fQ==","dependencies":["data.terraform_remote_state.project_setup","module.keycloak.openstack_networking_secgroup_v2.traffic_to_keycloak"]},{"index_key":"10.10.0.12","schema_version":0,"attributes":{"description":"HTTPS traffic from the HAPROXY L7 10.10.0.12","direction":"ingress","ethertype":"IPv4","id":"5a3c895b-b47b-47ee-ad19-76819e405943","port_range_max":9443,"port_range_min":9443,"protocol":"tcp","region":"isti_area_pi_1","remote_address_group_id":"","remote_group_id":"","remote_ip_prefix":"10.10.0.12/32","security_group_id":"f5b3b6d6-a0ca-4cb8-81f2-eaaa3052cfcb","tenant_id":"d0dcc2b7f3004c9a81b87ab60ec3c0d3","timeouts":null},"sensitive_attributes":[],"private":"eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiZGVsZXRlIjo2MDAwMDAwMDAwMDB9fQ==","dependencies":["data.terraform_remote_state.project_setup","module.keycloak.openstack_networking_secgroup_v2.traffic_to_keycloak"]}]},{"module":"module.keycloak","mode":"managed","type":"openstack_networking_secgroup_rule_v2","name":"haproxy_to_keycloak_management","provider":"provider[\"registry.opentofu.org/terraform-provider-openstack/openstack\"]","instances":[{"index_key":"10.10.0.11","schema_version":0,"attributes":{"description":"Traffic from the HAPROXY L7 10.10.0.11 to the management port","direction":"ingress","ethertype":"IPv4","id":"d36fc154-e08a-4d75-bada-52591af98fa7","port_range_max":9000,"port_range_min":9000,"protocol":"tcp","region":"isti_area_pi_1","remote_address_group_id":"","remote_group_id":"","remote_ip_prefix":"10.10.0.11/32","security_group_id":"f5b3b6d6-a0ca-4cb8-81f2-eaaa3052cfcb","tenant_id":"d0dcc2b7f3004c9a81b87ab60ec3c0d3","timeouts":null},"sensitive_attributes":[],"private":"eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiZGVsZXRlIjo2MDAwMDAwMDAwMDB9fQ==","dependencies":["data.terraform_remote_state.project_setup","module.keycloak.openstack_networking_secgroup_v2.traffic_to_keycloak"]},{"index_key":"10.10.0.12","schema_version":0,"attributes":{"description":"Traffic from the HAPROXY L7 10.10.0.12 to the management port","direction":"ingress","ethertype":"IPv4","id":"002c9906-c0f5-4299-87f1-36b83a1c8e91","port_range_max":9000,"port_range_min":9000,"protocol":"tcp","region":"isti_area_pi_1","remote_address_group_id":"","remote_group_id":"","remote_ip_prefix":"10.10.0.12/32","security_group_id":"f5b3b6d6-a0ca-4cb8-81f2-eaaa3052cfcb","tenant_id":"d0dcc2b7f3004c9a81b87ab60ec3c0d3","timeouts":null},"sensitive_attributes":[],"private":"eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiZGVsZXRlIjo2MDAwMDAwMDAwMDB9fQ==","dependencies":["data.terraform_remote_state.project_setup","module.keycloak.openstack_networking_secgroup_v2.traffic_to_keycloak"]}]},{"module":"module.keycloak","mode":"managed","type":"openstack_networking_secgroup_rule_v2","name":"prometheus_to_keycloak_metrics","provider":"provider[\"registry.opentofu.org/terraform-provider-openstack/openstack\"]","instances":[{"schema_version":0,"attributes":{"description":"Requests from Prometheus to the management port, that serves the metrics","direction":"ingress","ethertype":"IPv4","id":"d7e0bc4a-5353-4a99-8c8e-2ac5fa18ad89","port_range_max":9000,"port_range_min":9000,"protocol":"tcp","region":"isti_area_pi_1","remote_address_group_id":"","remote_group_id":"","remote_ip_prefix":"10.10.0.10/32","security_group_id":"f5b3b6d6-a0ca-4cb8-81f2-eaaa3052cfcb","tenant_id":"d0dcc2b7f3004c9a81b87ab60ec3c0d3","timeouts":null},"sensitive_attributes":[],"private":"eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiZGVsZXRlIjo2MDAwMDAwMDAwMDB9fQ==","dependencies":["data.terraform_remote_state.project_setup","module.keycloak.openstack_networking_secgroup_v2.traffic_to_keycloak"]}]},{"module":"module.keycloak","mode":"managed","type":"openstack_networking_secgroup_v2","name":"keycloak_cluster_traffic","provider":"provider[\"registry.opentofu.org/terraform-provider-openstack/openstack\"]","instances":[{"schema_version":0,"attributes":{"all_tags":[],"delete_default_rules":true,"description":"Traffic between the nodes of the keycloak cluster","id":"84c010c6-64c3-4f7a-91f6-e274b5fb1c67","name":"keycloak_cluster_traffic","region":"isti_area_pi_1","stateful":false,"tags":null,"tenant_id":"d0dcc2b7f3004c9a81b87ab60ec3c0d3","timeouts":null},"sensitive_attributes":[],"private":"eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiZGVsZXRlIjo2MDAwMDAwMDAwMDB9fQ=="}]},{"module":"module.keycloak","mode":"managed","type":"openstack_networking_secgroup_v2","name":"traffic_to_keycloak","provider":"provider[\"registry.opentofu.org/terraform-provider-openstack/openstack\"]","instances":[{"schema_version":0,"attributes":{"all_tags":[],"delete_default_rules":true,"description":"Traffic from the main L7 HAPROXY load balancers to keycloak","id":"f5b3b6d6-a0ca-4cb8-81f2-eaaa3052cfcb","name":"traffic_to_keycloak_from_the_main_load_balancers","region":"isti_area_pi_1","stateful":false,"tags":null,"tenant_id":"d0dcc2b7f3004c9a81b87ab60ec3c0d3","timeouts":null},"sensitive_attributes":[],"private":"eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiZGVsZXRlIjo2MDAwMDAwMDAwMDB9fQ=="}]}],"check_results":[{"object_kind":"var","config_addr":"module.keycloak.var.keycloak_ip","status":"pass","objects":[{"object_addr":"module.keycloak.var.keycloak_ip","status":"pass"}]}]}