From a4df8062fad1d6bfbe26151cd5dc66331cee8c7b Mon Sep 17 00:00:00 2001 From: Borislav Raynov Date: Tue, 18 Nov 2025 17:59:45 +0200 Subject: [PATCH 1/9] Add initial module --- src/_outputs.tf | 4 ++ src/_variables.resources.tf | 2 + .../postgresql_flexible_server/_locals.tf | 22 +++++++ .../postgresql_flexible_server/_outputs.tf | 7 +++ .../postgresql_flexible_server/_variables.tf | 18 ++++++ .../postgresql_flexible_server/main.tf | 62 +++++++++++++++++++ src/postgresql_flexible_servers.tf | 23 +++++++ 7 files changed, 138 insertions(+) create mode 100644 src/modules/postgresql_flexible_server/_locals.tf create mode 100644 src/modules/postgresql_flexible_server/_outputs.tf create mode 100644 src/modules/postgresql_flexible_server/_variables.tf create mode 100644 src/modules/postgresql_flexible_server/main.tf create mode 100644 src/postgresql_flexible_servers.tf diff --git a/src/_outputs.tf b/src/_outputs.tf index 5ed17337..4cb2771f 100644 --- a/src/_outputs.tf +++ b/src/_outputs.tf @@ -86,6 +86,10 @@ output "postgres" { value = module.postgres } +output "postgresql_flexible_servers" { + value = module.postgres +} + output "container_registries" { value = module.container_registries } diff --git a/src/_variables.resources.tf b/src/_variables.resources.tf index 8a7b8885..b6979a30 100644 --- a/src/_variables.resources.tf +++ b/src/_variables.resources.tf @@ -40,6 +40,8 @@ variable "public_ips" { default = {} } variable "postgres" { default = {} } +variable "postgresql_flexible_servers" { default = {} } + variable "keyvaults" { default = {} } variable "storage_accounts" { default = {} } diff --git a/src/modules/postgresql_flexible_server/_locals.tf b/src/modules/postgresql_flexible_server/_locals.tf new file mode 100644 index 00000000..56f1f47a --- /dev/null +++ b/src/modules/postgresql_flexible_server/_locals.tf @@ -0,0 +1,22 @@ +locals { + resource_group = var.resources[ + try(var.settings.lz_key, var.client_config.landingzone_key) + ].resource_groups[var.settings.resource_group_ref] + resource_group_name = local.resource_group.name + location = local.resource_group.location + + key_vault_id = try( + var.resources[ + try(var.settings.key_vault_lz_key, var.client_config.landingzone_key) + ].keyvaults[ + var.settings.key_vault_ref + ].id, + null + ) + + tags = merge( + var.global_settings.tags, + var.global_settings.inherit_resource_group_tags ? local.resource_group.tags : {}, + try(var.settings.tags, {}) + ) +} diff --git a/src/modules/postgresql_flexible_server/_outputs.tf b/src/modules/postgresql_flexible_server/_outputs.tf new file mode 100644 index 00000000..69137758 --- /dev/null +++ b/src/modules/postgresql_flexible_server/_outputs.tf @@ -0,0 +1,7 @@ +output "id" { + value = azurerm_postgresql_flexible_server.main.id +} + +output "fqdn" { + value = azurerm_postgresql_flexible_server.main.fqdn +} diff --git a/src/modules/postgresql_flexible_server/_variables.tf b/src/modules/postgresql_flexible_server/_variables.tf new file mode 100644 index 00000000..bb7a9d86 --- /dev/null +++ b/src/modules/postgresql_flexible_server/_variables.tf @@ -0,0 +1,18 @@ +variable "global_settings" { + description = "Global settings for tinycaf" +} + +variable "settings" { + description = "All the configuration for this resource" +} + +variable "resources" { + description = "All required resources" +} + +variable "client_config" { + description = "Client config such as current landingzone key" + type = object({ + landingzone_key = string + }) +} diff --git a/src/modules/postgresql_flexible_server/main.tf b/src/modules/postgresql_flexible_server/main.tf new file mode 100644 index 00000000..4bbf4da4 --- /dev/null +++ b/src/modules/postgresql_flexible_server/main.tf @@ -0,0 +1,62 @@ +resource "azurerm_postgresql_flexible_server" "main" { + name = var.settings.name + location = local.location + resource_group_name = local.resource_group_name + tags = local.tags + + administrator_login = var.settings.keyvault_ref != null ? "postgreadmin" : null + # administrator_login_password = var.settings.keyvault_ref != null ? random_password.admin[0].result : null + + sku_name = try(var.settings.sku_name, "GP_Gen5_4") + version = try(var.settings.version, "11") + storage_mb = try(var.settings.storage_mb, 5120) + + backup_retention_days = try(var.settings.backup_retention_days, 7) + geo_redundant_backup_enabled = try(var.settings.geo_redundant_backup_enabled, true) + auto_grow_enabled = try(var.settings.auto_grow_enabled, true) + + public_network_access_enabled = try(var.settings.public_network_access_enabled, false) + # ssl_enforcement_enabled = try(var.settings.ssl_enforcement_enabled, true) + # ssl_minimal_tls_version_enforced = try(var.settings.ssl_minimal_tls_version_enforced, "TLS1_2") + # create_mode = try(var.settings.create_mode, "Default") + # creation_source_server_id = try(var.settings.creation_source_server_id, null) + # infrastructure_encryption_enabled = try(var.settings.infrastructure_encryption_enabled, false) + + # dynamic "identity" { + # for_each = var.settings.use_system_identity == true ? [1] : [] + # content { + # type = "SystemAssigned" + # } + # } + # dynamic "threat_detection_policy" { + # for_each = try([var.settings.threat_detection_policy], []) + + # content { + # enabled = try(threat_detection_policy.value.enabled, null) + # disabled_alerts = try(threat_detection_policy.value.disabled_alerts, null) + # email_account_admins = try(threat_detection_policy.value.email_account_admins, null) + # email_addresses = try(threat_detection_policy.value.email_addresses, null) + # retention_days = try(threat_detection_policy.value.retention_days, null) + # storage_account_access_key = try(threat_detection_policy.value.storage_account_access_key, null) + # storage_endpoint = try(threat_detection_policy.value.storage_endpoint, null) + # } + # } + # } + + # resource "random_password" "admin" { + # count = try(length(trimspace(var.settings.keyvault_ref)) > 0, false) ? 1 : 0 + # length = 15 + # min_upper = 2 + # min_lower = 2 + # min_special = 2 + # numeric = true + # special = true + # override_special = "!@#$%&" + # } + + # resource "azurerm_key_vault_secret" "admin_password" { + # count = try(length(trimspace(var.settings.keyvault_ref)) > 0, false) ? 1 : 0 + # name = "${var.settings.name}-psqladmin-password" + # value = random_password.admin[0].result + # key_vault_id = local.key_vault_id +} diff --git a/src/postgresql_flexible_servers.tf b/src/postgresql_flexible_servers.tf new file mode 100644 index 00000000..dde1d561 --- /dev/null +++ b/src/postgresql_flexible_servers.tf @@ -0,0 +1,23 @@ +module "postgresql_flexible_server" { + source = "./modules/postgresql_flexible_server" + for_each = var.postgresql_flexible_servers + settings = each.value + global_settings = local.global_settings + + resources = merge( + { + (var.landingzone.key) = { + resource_groups = module.resource_groups + managed_identities = module.managed_identities + keyvaults = module.keyvaults + } + }, + { + for k, v in module.remote_states : k => v.outputs + } + ) + + client_config = { + landingzone_key = var.landingzone.key + } +} From c46dbf7a48e6577cb3be30973f9e5a009ff47ac3 Mon Sep 17 00:00:00 2001 From: Borislav Raynov Date: Mon, 24 Nov 2025 10:16:06 +0200 Subject: [PATCH 2/9] Add module's argumetns --- .../postgresql_flexible_server/_locals.tf | 64 +++++++++- .../postgresql_flexible_server/main.tf | 115 +++++++++--------- src/postgresql_flexible_servers.tf | 8 +- 3 files changed, 125 insertions(+), 62 deletions(-) diff --git a/src/modules/postgresql_flexible_server/_locals.tf b/src/modules/postgresql_flexible_server/_locals.tf index 56f1f47a..affdc522 100644 --- a/src/modules/postgresql_flexible_server/_locals.tf +++ b/src/modules/postgresql_flexible_server/_locals.tf @@ -5,15 +5,71 @@ locals { resource_group_name = local.resource_group.name location = local.resource_group.location - key_vault_id = try( + delegated_subnet_id = try( var.resources[ - try(var.settings.key_vault_lz_key, var.client_config.landingzone_key) - ].keyvaults[ - var.settings.key_vault_ref + try(var.settings.vnet_lz_key, var.client_config.landingzone_key) + ].virtual_networks[ + split("/", var.settings.subnet_ref)[0] + ].subnets[ + split("/", var.settings.subnet_ref)[1] ].id, + var.settings.delegated_subnet_id, null ) + private_dns_zone_id = try( + var.resources[ + try(var.settings.pdns_lz_key, var.client_config.landingzone_key) + ].private_dns_zones[ + var.settings.pdns_ref + ].id, + var.settings.private_dns_zone_id, + null + ) + + key_vault_key_id = try( + var.resources[ + try(var.settings.customer_managed_key.kvkey_lz_key, var.client_config.landingzone_key) + ].key_vault_keys[ + var.settings.customer_managed_key.kvkey_ref + ].versionless_id, + var.settings.customer_managed_key.key_vault_key_id + ) + + geo_backup_key_vault_key_id = try( + var.resources[ + try(var.settings.customer_managed_key.geo_kvkey_lz_key, var.client_config.landingzone_key) + ].key_vault_keys[ + var.settings.customer_managed_key.geo_kvkey_ref + ].versionless_id, + var.settings.customer_managed_key.geo_backup_key_vault_key_id + ) + + primary_user_assigned_identity_id = try( + var.resources[ + try(var.settings.customer_managed_key.prime_mi_lz_key, var.client_config.landingzone_key) + ].managed_identities[ + var.settings.customer_managed_key.prime_mi_ref + ].id, + var.settings.customer_managed_key.primary_user_assigned_identity_id + ) + + geo_backup_user_assigned_identity_id = try( + var.resources[ + try(var.settings.customer_managed_key.geo_mi_lz_key, var.client_config.landingzone_key) + ].managed_identities[ + var.settings.customer_managed_key.geo_mi_ref + ].id, + var.settings.customer_managed_key.geo_backup_user_assigned_identity_id + ) + + identity_ids = [ + for id_ref in try(var.settings.identity.identity_ids_ref, []) : + var.resources[ + try(var.settings.identity.mi_lz_key, var.client_config.landingzone_key) + ].managed_identities[id_ref].id + ] + tags = merge( var.global_settings.tags, var.global_settings.inherit_resource_group_tags ? local.resource_group.tags : {}, diff --git a/src/modules/postgresql_flexible_server/main.tf b/src/modules/postgresql_flexible_server/main.tf index 4bbf4da4..a81da83b 100644 --- a/src/modules/postgresql_flexible_server/main.tf +++ b/src/modules/postgresql_flexible_server/main.tf @@ -1,62 +1,67 @@ resource "azurerm_postgresql_flexible_server" "main" { - name = var.settings.name - location = local.location - resource_group_name = local.resource_group_name - tags = local.tags + name = var.settings.name + resource_group_name = local.resource_group_name + location = local.location + tags = local.tags + delegated_subnet_id = local.delegated_subnet_id + private_dns_zone_id = local.private_dns_zone_id + administrator_login = try(var.settings.administrator_login, null) + administrator_password = try(var.settings.administrator_password, null) + backup_retention_days = try(var.settings.backup_retention_days, null) + geo_redundant_backup_enabled = try(var.settings.geo_redundant_backup_enabled, null) + create_mode = try(var.settings.create_mode, null) + public_network_access_enabled = try(var.settings.public_network_access_enabled, null) + point_in_time_restore_time_in_utc = try(var.settings.point_in_time_restore_time_in_utc, null) + replication_role = try(var.settings.replication_role, null) + sku_name = try(var.settings.sku_name, null) + source_server_id = try(var.settings.source_server_id, null) + auto_grow_enabled = try(var.settings.auto_grow_enabled, null) + storage_mb = try(var.settings.storage_mb, null) + storage_tier = try(var.settings.storage_tier, null) + version = try(var.settings.version, null) + zone = try(var.settings.zone, null) - administrator_login = var.settings.keyvault_ref != null ? "postgreadmin" : null - # administrator_login_password = var.settings.keyvault_ref != null ? random_password.admin[0].result : null + dynamic "identity" { + for_each = can(var.settings.identity) ? [1] : [] + content { + type = var.settings.identity.type + identity_ids = try(local.identity_ids, null) + } + } - sku_name = try(var.settings.sku_name, "GP_Gen5_4") - version = try(var.settings.version, "11") - storage_mb = try(var.settings.storage_mb, 5120) + dynamic "authentication" { + for_each = can(var.settings.authentication) ? [1] : [] + content { + active_directory_auth_enabled = try(var.settings.authentication.active_directory_auth_enabled, null) + password_auth_enabled = try(var.settings.authentication.password_auth_enabled, null) + tenant_id = try(var.settings.authentication.tenant_id, null) + } + } - backup_retention_days = try(var.settings.backup_retention_days, 7) - geo_redundant_backup_enabled = try(var.settings.geo_redundant_backup_enabled, true) - auto_grow_enabled = try(var.settings.auto_grow_enabled, true) + dynamic "customer_managed_key" { + for_each = can(var.settings.customer_managed_key) ? [1] : [] + content { + key_vault_key_id = local.key_vault_key_id + primary_user_assigned_identity_id = try(local.primary_user_assigned_identity_id, null) + geo_backup_user_assigned_identity_id = try(local.geo_backup_user_assigned_identity_id, null) + geo_backup_key_vault_key_id = try(local.geo_backup_key_vault_key_id, null) + } + } - public_network_access_enabled = try(var.settings.public_network_access_enabled, false) - # ssl_enforcement_enabled = try(var.settings.ssl_enforcement_enabled, true) - # ssl_minimal_tls_version_enforced = try(var.settings.ssl_minimal_tls_version_enforced, "TLS1_2") - # create_mode = try(var.settings.create_mode, "Default") - # creation_source_server_id = try(var.settings.creation_source_server_id, null) - # infrastructure_encryption_enabled = try(var.settings.infrastructure_encryption_enabled, false) + dynamic "high_availability" { + for_each = can(var.settings.high_availability) ? [1] : [] + content { + mode = var.settings.high_availability.mode + standby_availability_zone = try(var.settings.high_availability.standby_availability_zone, null) + } + } - # dynamic "identity" { - # for_each = var.settings.use_system_identity == true ? [1] : [] - # content { - # type = "SystemAssigned" - # } - # } - # dynamic "threat_detection_policy" { - # for_each = try([var.settings.threat_detection_policy], []) - - # content { - # enabled = try(threat_detection_policy.value.enabled, null) - # disabled_alerts = try(threat_detection_policy.value.disabled_alerts, null) - # email_account_admins = try(threat_detection_policy.value.email_account_admins, null) - # email_addresses = try(threat_detection_policy.value.email_addresses, null) - # retention_days = try(threat_detection_policy.value.retention_days, null) - # storage_account_access_key = try(threat_detection_policy.value.storage_account_access_key, null) - # storage_endpoint = try(threat_detection_policy.value.storage_endpoint, null) - # } - # } - # } - - # resource "random_password" "admin" { - # count = try(length(trimspace(var.settings.keyvault_ref)) > 0, false) ? 1 : 0 - # length = 15 - # min_upper = 2 - # min_lower = 2 - # min_special = 2 - # numeric = true - # special = true - # override_special = "!@#$%&" - # } - - # resource "azurerm_key_vault_secret" "admin_password" { - # count = try(length(trimspace(var.settings.keyvault_ref)) > 0, false) ? 1 : 0 - # name = "${var.settings.name}-psqladmin-password" - # value = random_password.admin[0].result - # key_vault_id = local.key_vault_id + dynamic "maintenance_window" { + for_each = can(var.settings.maintenance_window) ? [1] : [] + content { + day_of_week = try(var.settings.maintenance_window.day_of_week, null) + start_hour = try(var.settings.maintenance_window.start_hour, null) + start_minute = try(var.settings.maintenance_window.start_minute, null) + } + } } diff --git a/src/postgresql_flexible_servers.tf b/src/postgresql_flexible_servers.tf index dde1d561..687f3042 100644 --- a/src/postgresql_flexible_servers.tf +++ b/src/postgresql_flexible_servers.tf @@ -7,9 +7,11 @@ module "postgresql_flexible_server" { resources = merge( { (var.landingzone.key) = { - resource_groups = module.resource_groups - managed_identities = module.managed_identities - keyvaults = module.keyvaults + resource_groups = module.resource_groups + managed_identities = module.managed_identities + virtual_networks = module.virtual_networks + private_dns_zones = module.private_dns_zones + keyvkey_vault_keysaults = module.key_vault_keys } }, { From 64d2e8f854248457970f3f8d72b37867694c19af Mon Sep 17 00:00:00 2001 From: Borislav Raynov Date: Mon, 24 Nov 2025 10:17:24 +0200 Subject: [PATCH 3/9] Fix module name --- src/postgresql_flexible_servers.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/postgresql_flexible_servers.tf b/src/postgresql_flexible_servers.tf index 687f3042..75c602fb 100644 --- a/src/postgresql_flexible_servers.tf +++ b/src/postgresql_flexible_servers.tf @@ -1,4 +1,4 @@ -module "postgresql_flexible_server" { +module "postgresql_flexible_servers" { source = "./modules/postgresql_flexible_server" for_each = var.postgresql_flexible_servers settings = each.value From 7468f38973d496792add2b0a8c3aaa0083e9a920 Mon Sep 17 00:00:00 2001 From: Borislav Raynov Date: Mon, 24 Nov 2025 10:26:39 +0200 Subject: [PATCH 4/9] Fix references naming --- src/modules/postgresql_flexible_server/_locals.tf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/modules/postgresql_flexible_server/_locals.tf b/src/modules/postgresql_flexible_server/_locals.tf index affdc522..90e05637 100644 --- a/src/modules/postgresql_flexible_server/_locals.tf +++ b/src/modules/postgresql_flexible_server/_locals.tf @@ -19,9 +19,9 @@ locals { private_dns_zone_id = try( var.resources[ - try(var.settings.pdns_lz_key, var.client_config.landingzone_key) + try(var.settings.dnszone_lz_key, var.client_config.landingzone_key) ].private_dns_zones[ - var.settings.pdns_ref + var.settings.dnszone_ref ].id, var.settings.private_dns_zone_id, null From a5251f0f3998f2265c41cec0feaf79d51cdcdc30 Mon Sep 17 00:00:00 2001 From: Borislav Raynov Date: Mon, 24 Nov 2025 10:43:39 +0200 Subject: [PATCH 5/9] Fix references in locals --- src/modules/postgresql_flexible_server/_locals.tf | 9 ++++++--- src/modules/postgresql_flexible_server/main.tf | 6 +++--- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/modules/postgresql_flexible_server/_locals.tf b/src/modules/postgresql_flexible_server/_locals.tf index 90e05637..714548c7 100644 --- a/src/modules/postgresql_flexible_server/_locals.tf +++ b/src/modules/postgresql_flexible_server/_locals.tf @@ -42,7 +42,8 @@ locals { ].key_vault_keys[ var.settings.customer_managed_key.geo_kvkey_ref ].versionless_id, - var.settings.customer_managed_key.geo_backup_key_vault_key_id + var.settings.customer_managed_key.geo_backup_key_vault_key_id, + null ) primary_user_assigned_identity_id = try( @@ -51,7 +52,8 @@ locals { ].managed_identities[ var.settings.customer_managed_key.prime_mi_ref ].id, - var.settings.customer_managed_key.primary_user_assigned_identity_id + var.settings.customer_managed_key.primary_user_assigned_identity_id, + null ) geo_backup_user_assigned_identity_id = try( @@ -60,7 +62,8 @@ locals { ].managed_identities[ var.settings.customer_managed_key.geo_mi_ref ].id, - var.settings.customer_managed_key.geo_backup_user_assigned_identity_id + var.settings.customer_managed_key.geo_backup_user_assigned_identity_id, + null ) identity_ids = [ diff --git a/src/modules/postgresql_flexible_server/main.tf b/src/modules/postgresql_flexible_server/main.tf index a81da83b..586eeee4 100644 --- a/src/modules/postgresql_flexible_server/main.tf +++ b/src/modules/postgresql_flexible_server/main.tf @@ -42,9 +42,9 @@ resource "azurerm_postgresql_flexible_server" "main" { for_each = can(var.settings.customer_managed_key) ? [1] : [] content { key_vault_key_id = local.key_vault_key_id - primary_user_assigned_identity_id = try(local.primary_user_assigned_identity_id, null) - geo_backup_user_assigned_identity_id = try(local.geo_backup_user_assigned_identity_id, null) - geo_backup_key_vault_key_id = try(local.geo_backup_key_vault_key_id, null) + primary_user_assigned_identity_id = local.primary_user_assigned_identity_id + geo_backup_user_assigned_identity_id = local.geo_backup_user_assigned_identity_id + geo_backup_key_vault_key_id = local.geo_backup_key_vault_key_id } } From 58db17641bcef2de9d8510ce4dd34989843f0926 Mon Sep 17 00:00:00 2001 From: Borislav Raynov Date: Mon, 24 Nov 2025 10:46:50 +0200 Subject: [PATCH 6/9] Fix typo --- src/postgresql_flexible_servers.tf | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/postgresql_flexible_servers.tf b/src/postgresql_flexible_servers.tf index 75c602fb..6c62b01c 100644 --- a/src/postgresql_flexible_servers.tf +++ b/src/postgresql_flexible_servers.tf @@ -7,11 +7,11 @@ module "postgresql_flexible_servers" { resources = merge( { (var.landingzone.key) = { - resource_groups = module.resource_groups - managed_identities = module.managed_identities - virtual_networks = module.virtual_networks - private_dns_zones = module.private_dns_zones - keyvkey_vault_keysaults = module.key_vault_keys + resource_groups = module.resource_groups + managed_identities = module.managed_identities + virtual_networks = module.virtual_networks + private_dns_zones = module.private_dns_zones + key_vault_keys = module.key_vault_keys } }, { From 6d50d3139e4340c49ad27089863c78aa66c1bebe Mon Sep 17 00:00:00 2001 From: Borislav Raynov Date: Mon, 24 Nov 2025 10:56:49 +0200 Subject: [PATCH 7/9] Add example --- examples/postgresql_flexible_servers.tfvars | 138 ++++++++++++++++++++ 1 file changed, 138 insertions(+) create mode 100644 examples/postgresql_flexible_servers.tfvars diff --git a/examples/postgresql_flexible_servers.tfvars b/examples/postgresql_flexible_servers.tfvars new file mode 100644 index 00000000..435bb244 --- /dev/null +++ b/examples/postgresql_flexible_servers.tfvars @@ -0,0 +1,138 @@ +postgresql_flexible_servers = { + flex_postgres_server_test = { + resource_group_ref = "rg_test" + name = "pg-flex-example" + administrator_login = "pgadmin" + administrator_password = "SuperSecurePassword123!" + sku_name = "B_Standard_B1ms" + version = "14" + zone = "1" + + storage_mb = 32768 + storage_tier = "P15" + auto_grow_enabled = true + + backup_retention_days = 7 + geo_redundant_backup_enabled = false + + public_network_access_enabled = false + subnet_ref = "vnet_test/snet_sqlmi" + dnszone_ref = "pdns_zone_test" + + identity = { + type = "SystemAssigned" + identity_ids_ref = ["mi_test"] + } + + authentication = { + active_directory_auth_enabled = true + password_auth_enabled = true + } + + customer_managed_key = { + kvkey_ref = "kvkey_test1" + } + + high_availability = { + mode = "ZoneRedundant" + standby_availability_zone = "2" + } + + maintenance_window = { + day_of_week = 1 + start_hour = 2 + start_minute = 30 + } + } +} + +# pre-requisites +resource_groups = { + rg_test = { + name = "rg-test-01" + location = "northeurope" + tags = { + DeployDate = "11/07/2025", + DeadLine = "11/07/2026", + Owner = "Test Test", + Project = "Test", + } + } +} + +virtual_networks = { + vnet_test = { + name = "vnet-test-dv-ne-01" + resource_group_ref = "rg_test" + cidr = ["10.10.10.0/24"] + subnets = { + snet_sqlmi = { + name = "snet-sql-managed-instance" + cidr = ["10.10.10.0/25"] + delegation = "sql_managed_instance" + } + snet_private_endpoints = { + name = "snet-private-endpoints" + cidr = ["10.10.10.128/25"] + service_endpoints = ["Microsoft.Storage", "Microsoft.KeyVault"] + } + } + } +} + +private_dns_zones = { + pdns_zone_test = { + name = "privatelink.postgres.database.azure.com" + resource_group_ref = "rg_test" + vnet_ref = ["vnet_test"] + } +} + +managed_identities = { + mi_test = { + name = "id-test-dv-ne-01" + resource_group_ref = "rg_test" + } +} + +key_vault_keys = { + kvkey_test1 = { + name = "generated-certificate" + key_vault_ref = "kv_test" + key_type = "RSA" + key_size = "2048" + + key_opts = [ + "decrypt", + "encrypt", + "sign", + "unwrapKey", + "verify", + "wrapKey", + ] + + rotation_policy = { + expire_after = "P90D" + notify_before_expiry = "P29D" + automatic = { + time_before_expiry = "P30D" + } + } + } +} + +keyvaults = { + kv_test = { + name = "kv-test-dv-ne-01" + resource_group_ref = "rg_test" + network_rules = { + default_action = "Deny" + allowed_ips = ["10.10.10.10", "20.20.20.20"] + subnets = { + allow_app1 = { + subnet_ref = "vnet_test/snet_private_endpoints" + } + } + } + } +} From b8f183b76daf8227e3f2942015077ffccfe47d80 Mon Sep 17 00:00:00 2001 From: Borislav Raynov Date: Mon, 24 Nov 2025 11:07:27 +0200 Subject: [PATCH 8/9] Add optional admin password to KV --- .../postgresql_flexible_server/_locals.tf | 18 +++++++++++++++ .../postgresql_flexible_server/main.tf | 22 +++++++++++++++++-- src/postgresql_flexible_servers.tf | 1 + 3 files changed, 39 insertions(+), 2 deletions(-) diff --git a/src/modules/postgresql_flexible_server/_locals.tf b/src/modules/postgresql_flexible_server/_locals.tf index 714548c7..458b7be9 100644 --- a/src/modules/postgresql_flexible_server/_locals.tf +++ b/src/modules/postgresql_flexible_server/_locals.tf @@ -73,6 +73,24 @@ locals { ].managed_identities[id_ref].id ] + administrator_password = try( + ( + try(length(trimspace(var.settings.key_vault_ref)) > 0, false) + ? random_password.admin[0].result + : try(var.settings.administrator_password, random_password.admin[0].result) + ), + null + ) + + key_vault_id = try( + var.resources[ + try(var.settings.key_vault_lz_key, var.client_config.landingzone_key) + ].keyvaults[ + var.settings.key_vault_ref + ].id, + null + ) + tags = merge( var.global_settings.tags, var.global_settings.inherit_resource_group_tags ? local.resource_group.tags : {}, diff --git a/src/modules/postgresql_flexible_server/main.tf b/src/modules/postgresql_flexible_server/main.tf index 586eeee4..1b66df4d 100644 --- a/src/modules/postgresql_flexible_server/main.tf +++ b/src/modules/postgresql_flexible_server/main.tf @@ -5,8 +5,8 @@ resource "azurerm_postgresql_flexible_server" "main" { tags = local.tags delegated_subnet_id = local.delegated_subnet_id private_dns_zone_id = local.private_dns_zone_id - administrator_login = try(var.settings.administrator_login, null) - administrator_password = try(var.settings.administrator_password, null) + administrator_login = try(var.settings.administrator_login, "${var.settings.name}-pgadim") + administrator_password = local.administrator_password backup_retention_days = try(var.settings.backup_retention_days, null) geo_redundant_backup_enabled = try(var.settings.geo_redundant_backup_enabled, null) create_mode = try(var.settings.create_mode, null) @@ -65,3 +65,21 @@ resource "azurerm_postgresql_flexible_server" "main" { } } } + +resource "random_password" "admin" { + count = try(length(trimspace(var.settings.key_vault_ref)) > 0, false) ? 1 : 0 + length = try(var.settings.password_settings.length, 123) + min_upper = try(var.settings.password_settings.min_upper, 2) + min_lower = try(var.settings.password_settings.min_lower, 2) + min_special = try(var.settings.password_settings.min_special, 2) + numeric = try(var.settings.password_settings.numeric, true) + special = try(var.settings.password_settings.special, true) + override_special = try(var.settings.password_settings.override_special, "!@#$%&") +} + +resource "azurerm_key_vault_secret" "admin_password" { + count = try(length(trimspace(var.settings.key_vault_ref)) > 0, false) ? 1 : 0 + name = try(var.settings.custom_secret_name, "${var.settings.name}-${var.settings.administrator_login}") + value = random_password.admin[0].result + key_vault_id = local.key_vault_id +} diff --git a/src/postgresql_flexible_servers.tf b/src/postgresql_flexible_servers.tf index 6c62b01c..5868f3e5 100644 --- a/src/postgresql_flexible_servers.tf +++ b/src/postgresql_flexible_servers.tf @@ -12,6 +12,7 @@ module "postgresql_flexible_servers" { virtual_networks = module.virtual_networks private_dns_zones = module.private_dns_zones key_vault_keys = module.key_vault_keys + keyvaults = module.keyvaults } }, { From 3478fc993886cb39979ccc36d1b1e05acf6f580b Mon Sep 17 00:00:00 2001 From: Borislav Raynov Date: Mon, 24 Nov 2025 11:12:59 +0200 Subject: [PATCH 9/9] Change default admin pass length --- src/modules/postgresql_flexible_server/main.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/postgresql_flexible_server/main.tf b/src/modules/postgresql_flexible_server/main.tf index 1b66df4d..4acb059a 100644 --- a/src/modules/postgresql_flexible_server/main.tf +++ b/src/modules/postgresql_flexible_server/main.tf @@ -68,7 +68,7 @@ resource "azurerm_postgresql_flexible_server" "main" { resource "random_password" "admin" { count = try(length(trimspace(var.settings.key_vault_ref)) > 0, false) ? 1 : 0 - length = try(var.settings.password_settings.length, 123) + length = try(var.settings.password_settings.length, 20) min_upper = try(var.settings.password_settings.min_upper, 2) min_lower = try(var.settings.password_settings.min_lower, 2) min_special = try(var.settings.password_settings.min_special, 2)