From 1f36f6d08aac105e219eaebf222d3cefeb84df2e Mon Sep 17 00:00:00 2001 From: anttorre Date: Fri, 15 Oct 2021 21:42:38 +0200 Subject: [PATCH 1/6] spid-testenv application --- src/core/env/dev/terraform.tfvars | 3 + src/core/spid-testenv.tf | 13 ++ src/core/variables.tf | 11 +- .../DEV-SelfCare/.bastianhost.ini | 22 +++ src/modules/spid_testenv/.terraform.lock.hcl | 56 ++++++ src/modules/spid_testenv/output.tf | 9 + src/modules/spid_testenv/spid-testenv.tf | 161 ++++++++++++++++++ .../spid_testenv_conf/config.yaml.tpl | 57 +++++++ src/modules/spid_testenv/variables.tf | 25 +++ 9 files changed, 355 insertions(+), 2 deletions(-) create mode 100644 src/core/spid-testenv.tf create mode 100644 src/k8s/subscriptions/DEV-SelfCare/.bastianhost.ini create mode 100644 src/modules/spid_testenv/.terraform.lock.hcl create mode 100644 src/modules/spid_testenv/output.tf create mode 100644 src/modules/spid_testenv/spid-testenv.tf create mode 100644 src/modules/spid_testenv/spid_testenv_conf/config.yaml.tpl create mode 100644 src/modules/spid_testenv/variables.tf diff --git a/src/core/env/dev/terraform.tfvars b/src/core/env/dev/terraform.tfvars index ca2be6901..cd398f8e8 100644 --- a/src/core/env/dev/terraform.tfvars +++ b/src/core/env/dev/terraform.tfvars @@ -52,3 +52,6 @@ aks_max_pods = 100 # CosmosDb MongoDb cosmosdb_mongodb_enable_serverless = true cosmosdb_mongodb_public_network_access_enabled = true + +# spid-testenv +enable_spid_test = true diff --git a/src/core/spid-testenv.tf b/src/core/spid-testenv.tf new file mode 100644 index 000000000..914095b9b --- /dev/null +++ b/src/core/spid-testenv.tf @@ -0,0 +1,13 @@ +module "spid-test-env" { + source = "../modules/spid_testenv" + + enable_spid_test = var.enable_spid_test + + name = format("%s-spid-testenv", local.project) + location = var.location + subscription_name = data.azurerm_subscription.current.display_name + + hub_spid_login_metadata_url = format("https://api.%s.%s/hubspidloginms/metadata", var.dns_zone_prefix, var.external_domain) + + tags = var.tags +} diff --git a/src/core/variables.tf b/src/core/variables.tf index f33211a56..1e8929b72 100644 --- a/src/core/variables.tf +++ b/src/core/variables.tf @@ -419,13 +419,13 @@ variable "dns_default_ttl_sec" { variable "external_domain" { type = string - default = null + default = "pagopa.it" description = "Domain for delegation" } variable "dns_zone_prefix" { type = string - default = null + default = "selfcare" description = "The dns subdomain." } @@ -558,3 +558,10 @@ variable "cosmosdb_mongodb_max_throughput" { description = "The maximum throughput of the MongoDB database (RU/s). Must be between 4,000 and 1,000,000. Must be set in increments of 1,000. Conflicts with throughput" default = 4000 } + +# spid-testenv +variable "enable_spid_test" { + type = bool + description = "to provision italia/spid-testenv2:1.1.0" + default = false +} diff --git a/src/k8s/subscriptions/DEV-SelfCare/.bastianhost.ini b/src/k8s/subscriptions/DEV-SelfCare/.bastianhost.ini new file mode 100644 index 000000000..7c51fff7d --- /dev/null +++ b/src/k8s/subscriptions/DEV-SelfCare/.bastianhost.ini @@ -0,0 +1,22 @@ +aks_private_fqdn=selc-d-aks-ac177aef.b6aa1c51-596c-47ea-8b2b-01ca33d73e21.privatelink.westeurope.azmk8s.io +kube_config_path=~/.kube/config-selc-d-aks +aks_private_fqdn=selc-d-aks-ac177aef.b6aa1c51-596c-47ea-8b2b-01ca33d73e21.privatelink.westeurope.azmk8s.io +kube_config_path=~/.kube/config-selc-d-aks +aks_private_fqdn=selc-d-aks-ac177aef.b6aa1c51-596c-47ea-8b2b-01ca33d73e21.privatelink.westeurope.azmk8s.io +kube_config_path=~/.kube/config-selc-d-aks +aks_private_fqdn=selc-d-aks-ac177aef.b6aa1c51-596c-47ea-8b2b-01ca33d73e21.privatelink.westeurope.azmk8s.io +kube_config_path=~/.kube/config-selc-d-aks +aks_private_fqdn=selc-d-aks-ac177aef.b6aa1c51-596c-47ea-8b2b-01ca33d73e21.privatelink.westeurope.azmk8s.io +kube_config_path=~/.kube/config-selc-d-aks +aks_private_fqdn=selc-d-aks-ac177aef.b6aa1c51-596c-47ea-8b2b-01ca33d73e21.privatelink.westeurope.azmk8s.io +kube_config_path=~/.kube/config-selc-d-aks +aks_private_fqdn=selc-d-aks-ac177aef.b6aa1c51-596c-47ea-8b2b-01ca33d73e21.privatelink.westeurope.azmk8s.io +kube_config_path=~/.kube/config-selc-d-aks +aks_private_fqdn=selc-d-aks-ac177aef.b6aa1c51-596c-47ea-8b2b-01ca33d73e21.privatelink.westeurope.azmk8s.io +kube_config_path=~/.kube/config-selc-d-aks +aks_private_fqdn=selc-d-aks-ac177aef.b6aa1c51-596c-47ea-8b2b-01ca33d73e21.privatelink.westeurope.azmk8s.io +kube_config_path=~/.kube/config-selc-d-aks +aks_private_fqdn=selc-d-aks-ac177aef.b6aa1c51-596c-47ea-8b2b-01ca33d73e21.privatelink.westeurope.azmk8s.io +kube_config_path=~/.kube/config-selc-d-aks +aks_private_fqdn=selc-d-aks-ac177aef.b6aa1c51-596c-47ea-8b2b-01ca33d73e21.privatelink.westeurope.azmk8s.io +kube_config_path=~/.kube/config-selc-d-aks diff --git a/src/modules/spid_testenv/.terraform.lock.hcl b/src/modules/spid_testenv/.terraform.lock.hcl new file mode 100644 index 000000000..936f6aac2 --- /dev/null +++ b/src/modules/spid_testenv/.terraform.lock.hcl @@ -0,0 +1,56 @@ +# This file is maintained automatically by "terraform init". +# Manual edits may be lost in future updates. + +provider "registry.terraform.io/hashicorp/azurerm" { + version = "2.81.0" + hashes = [ + "h1:VZEhiI0ly+qMcDF9iji9AvOKVkU9Ox5nStKI7agqXeU=", + "zh:087f048995b70fb18c8e098d099085dbbb5102d157833405008ef0264860d524", + "zh:112f8897a30ff1ed865625a18dc298114ed91ad078c71753604aae2cd23bf832", + "zh:1cb29842b3946ba95d5ee76431b09dfa01b64669ef593285fbce2f87cb2d1916", + "zh:21b5ae1ddb0781d9e6ce98484e6c6c674c9c4d2267b524db730671f4a0d47c0e", + "zh:36d95984e27aa8ed6218be231ba9ef3e94e7ac8a1c452fdb203b278018385251", + "zh:5f01f7acf7467d78c984c4318ffefeae421c54bb8affa0243c188c6795922819", + "zh:5f3046434fde4255bfd094dc6f926a3b88761d2ce022aaeb4eb78599c945903e", + "zh:68d948ed7144c00554ee0f3b0022ebd6a5e670fa9bb60ab51408b8cfebd4f4b4", + "zh:69b777b554c849b1624bb4d1bb10a68ab697e04dd2271026dd6782ee6e05b780", + "zh:a9283814ee9438aecb48f3a2bb092ca8437af91a5eef3aed4fbfd75ab8fb8268", + "zh:f049c61896d1c58b9e20b42692bc41a5014ba45a7ca40e1dd346cc6db99ba6c5", + ] +} + +provider "registry.terraform.io/hashicorp/local" { + version = "2.1.0" + hashes = [ + "h1:EYZdckuGU3n6APs97nS2LxZm3dDtGqyM4qaIvsmac8o=", + "zh:0f1ec65101fa35050978d483d6e8916664b7556800348456ff3d09454ac1eae2", + "zh:36e42ac19f5d68467aacf07e6adcf83c7486f2e5b5f4339e9671f68525fc87ab", + "zh:6db9db2a1819e77b1642ec3b5e95042b202aee8151a0256d289f2e141bf3ceb3", + "zh:719dfd97bb9ddce99f7d741260b8ece2682b363735c764cac83303f02386075a", + "zh:7598bb86e0378fd97eaa04638c1a4c75f960f62f69d3662e6d80ffa5a89847fe", + "zh:ad0a188b52517fec9eca393f1e2c9daea362b33ae2eb38a857b6b09949a727c1", + "zh:c46846c8df66a13fee6eff7dc5d528a7f868ae0dcf92d79deaac73cc297ed20c", + "zh:dc1a20a2eec12095d04bf6da5321f535351a594a636912361db20eb2a707ccc4", + "zh:e57ab4771a9d999401f6badd8b018558357d3cbdf3d33cc0c4f83e818ca8e94b", + "zh:ebdcde208072b4b0f8d305ebf2bfdc62c926e0717599dcf8ec2fd8c5845031c3", + "zh:ef34c52b68933bedd0868a13ccfd59ff1c820f299760b3c02e008dc95e2ece91", + ] +} + +provider "registry.terraform.io/hashicorp/null" { + version = "3.1.0" + hashes = [ + "h1:vpC6bgUQoJ0znqIKVFevOdq+YQw42bRq0u+H3nto8nA=", + "zh:02a1675fd8de126a00460942aaae242e65ca3380b5bb192e8773ef3da9073fd2", + "zh:53e30545ff8926a8e30ad30648991ca8b93b6fa496272cd23b26763c8ee84515", + "zh:5f9200bf708913621d0f6514179d89700e9aa3097c77dac730e8ba6e5901d521", + "zh:9ebf4d9704faba06b3ec7242c773c0fbfe12d62db7d00356d4f55385fc69bfb2", + "zh:a6576c81adc70326e4e1c999c04ad9ca37113a6e925aefab4765e5a5198efa7e", + "zh:a8a42d13346347aff6c63a37cda9b2c6aa5cc384a55b2fe6d6adfa390e609c53", + "zh:c797744d08a5307d50210e0454f91ca4d1c7621c68740441cf4579390452321d", + "zh:cecb6a304046df34c11229f20a80b24b1603960b794d68361a67c5efe58e62b8", + "zh:e1371aa1e502000d9974cfaff5be4cfa02f47b17400005a16f14d2ef30dc2a70", + "zh:fc39cc1fe71234a0b0369d5c5c7f876c71b956d23d7d6f518289737a001ba69b", + "zh:fea4227271ebf7d9e2b61b89ce2328c7262acd9fd190e1fd6d15a591abfa848e", + ] +} diff --git a/src/modules/spid_testenv/output.tf b/src/modules/spid_testenv/output.tf new file mode 100644 index 000000000..1a173f124 --- /dev/null +++ b/src/modules/spid_testenv/output.tf @@ -0,0 +1,9 @@ +output "container_id" { + description = "The id of the spid_testenv container." + value = azurerm_container_group.spid_testenv[0].id +} + +output "spid_testenv_url" { + description = "The id of the spid_testenv container." + value = azurerm_container_group.spid_testenv[0].fqdn +} diff --git a/src/modules/spid_testenv/spid-testenv.tf b/src/modules/spid_testenv/spid-testenv.tf new file mode 100644 index 000000000..1c582c9d3 --- /dev/null +++ b/src/modules/spid_testenv/spid-testenv.tf @@ -0,0 +1,161 @@ +resource "azurerm_resource_group" "rg_spid_testenv" { + count = var.enable_spid_test ? 1 : 0 + name = format("%s-rg", var.name) + location = var.location + + tags = var.tags +} + +# tfsec:ignore:azure-storage-default-action-deny +resource "azurerm_storage_account" "spid_testenv_storage_account" { + count = var.enable_spid_test ? 1 : 0 + name = replace(format("%s-sa-st", var.name), "-", "") + resource_group_name = azurerm_resource_group.rg_spid_testenv[0].name + location = var.location + enable_https_traffic_only = true + min_tls_version = "TLS1_2" + account_tier = "Standard" + + account_replication_type = "LRS" + + tags = var.tags +} + +resource "azurerm_storage_share" "spid_testenv_storage_share" { + count = var.enable_spid_test ? 1 : 0 + name = format("%s-share", var.name) + + storage_account_name = azurerm_storage_account.spid_testenv_storage_account[0].name + + quota = 1 +} + +resource "azurerm_storage_share" "spid_testenv_caddy_storage_share" { + count = var.enable_spid_test ? 1 : 0 + name = format("%s-caddy-share", var.name) + + storage_account_name = azurerm_storage_account.spid_testenv_storage_account[0].name + + quota = 1 +} + +resource "azurerm_container_group" "spid_testenv" { + count = var.enable_spid_test ? 1 : 0 + name = var.name + location = azurerm_resource_group.rg_spid_testenv[0].location + resource_group_name = azurerm_resource_group.rg_spid_testenv[0].name + ip_address_type = "public" + dns_name_label = var.name + os_type = "Linux" + + container { + name = "spid-testenv2" + image = "italia/spid-testenv2:1.1.0" + cpu = "0.5" + memory = "0.5" + + ports { + port = 8088 + protocol = "TCP" + } + + environment_variables = { + + } + + readiness_probe { + http_get { + path = "/" + port = 8088 + scheme = "Http" + } + initial_delay_seconds = 30 + timeout_seconds = 4 + } + + liveness_probe { + http_get { + path = "/" + port = 8088 + scheme = "Http" + } + initial_delay_seconds = 900 + timeout_seconds = 4 + } + + volume { + mount_path = "/app/conf" + name = "spid-testenv-conf" + read_only = false + share_name = azurerm_storage_share.spid_testenv_storage_share[0].name + + storage_account_key = azurerm_storage_account.spid_testenv_storage_account[0].primary_access_key + storage_account_name = azurerm_storage_account.spid_testenv_storage_account[0].name + } + + } + + container { + name = "caddy-ssl-server" + image = "caddy:2" + cpu = "0.5" + memory = "0.5" + commands = ["caddy", "reverse-proxy", "--from", "${var.name}.${var.location}.azurecontainer.io", "--to", "localhost:8088"] + + ports { + port = 443 + protocol = "TCP" + } + + ports { + port = 80 + protocol = "TCP" + } + + volume { + mount_path = "/data" + name = "caddy-data" + read_only = false + share_name = azurerm_storage_share.spid_testenv_caddy_storage_share[0].name + + storage_account_key = azurerm_storage_account.spid_testenv_storage_account[0].primary_access_key + storage_account_name = azurerm_storage_account.spid_testenv_storage_account[0].name + } + } + + tags = var.tags +} + +resource "local_file" "spid_testenv_config" { + count = var.enable_spid_test ? 1 : 0 + filename = "./spid_testenv_conf/config.yaml" + content = templatefile( + "${path.module}/spid_testenv_conf/config.yaml.tpl", + { + base_url = format("https://%s", trim(azurerm_container_group.spid_testenv[0].fqdn, ".")) + service_provider_metadata_url = var.hub_spid_login_metadata_url + }) +} + +resource "null_resource" "upload_config_spid_testenv" { + count = var.enable_spid_test ? 1 : 0 + triggers = { + "changes-in-config" : md5(local_file.spid_testenv_config[count.index].content) + } + + provisioner "local-exec" { + command = < Date: Mon, 18 Oct 2021 09:50:53 +0200 Subject: [PATCH 2/6] spid-testenv output var not null only if enabled --- src/modules/spid_testenv/output.tf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/modules/spid_testenv/output.tf b/src/modules/spid_testenv/output.tf index 1a173f124..fac8babe8 100644 --- a/src/modules/spid_testenv/output.tf +++ b/src/modules/spid_testenv/output.tf @@ -1,9 +1,9 @@ output "container_id" { description = "The id of the spid_testenv container." - value = azurerm_container_group.spid_testenv[0].id + value = var.enable_spid_test? azurerm_container_group.spid_testenv[0].id : null } output "spid_testenv_url" { description = "The id of the spid_testenv container." - value = azurerm_container_group.spid_testenv[0].fqdn + value = var.enable_spid_test? azurerm_container_group.spid_testenv[0].fqdn : null } From d4104135232d378c31c9080a21d174de3d2947cf Mon Sep 17 00:00:00 2001 From: anttorre Date: Fri, 22 Oct 2021 13:22:56 +0200 Subject: [PATCH 3/6] config.yaml generated by spid-testenv module --- src/core/spid_testenv_conf/config.yaml | 57 ++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 src/core/spid_testenv_conf/config.yaml diff --git a/src/core/spid_testenv_conf/config.yaml b/src/core/spid_testenv_conf/config.yaml new file mode 100644 index 000000000..a3e4e50de --- /dev/null +++ b/src/core/spid_testenv_conf/config.yaml @@ -0,0 +1,57 @@ +--- +# Identity Provider (IdP) +######################### + +# The base URL where spid-testenv2 is reachable at. +base_url: "https://selc-d-spid-testenv.westeurope.azurecontainer.io" + +# Key and certificate used to sign SAML messages. +key_file: "./conf/idp.key" +cert_file: "./conf/idp.crt" + +# Service Providers +################### + +# You can configure multiple Service Provider by specifying their XML metadata, +# using different sources. +metadata: + remote: + - "https://api.dev.selfcare.pagopa.it/hubspidloginms/metadata" + + +# Application configuration +########################### + +# Whether to enable debug mode. When enabled, the log will be more verbose. +debug: true + +# Bind the webserver to the specified IP address (use 0.0.0.0 for all interfaces). +host: "0.0.0.0" +# Port the webserver listens on. +port: 8088 + +# Whether to enable HTTPS. +https: false + +# The TLS key and certificate used for HTTPS, required if HTTPS is enabled. +# https_key_file: "path/to/key" +# https_cert_file: "path/to/cert" + +# File holding the identities of test users. +# It will be automatically created if it doesn't exist. +users_file: "conf/users.json" + +# PostgreSQL database holding the identities of test users. +# If specified, it will override the "user_file" parameter. +# The required tables will be automatically created if they don't exist. +# users_db: 'postgresql+psycopg2://postgres:@localhost:5432/exampledb' + +# If enabled, allows to add new users from the UI. +can_add_user: true + +# Whether to enable the UI to handle the data in the database. +database_admin_interface: true + +# If enabled, allows the user to manipulate the response from the Identity Provider. +# Useful to simulate errors in the response. +show_response_options: true From 8942799ccb25120feaf9f81a01d36ef92fbad132 Mon Sep 17 00:00:00 2001 From: anttorre Date: Fri, 22 Oct 2021 13:36:03 +0200 Subject: [PATCH 4/6] temporarely pointing to local postgres module waiting for PR 104 on azurerm --- src/core/postgres.tf | 3 +- src/modules/postgresql_server/README.md | 86 ++++++ src/modules/postgresql_server/main.tf | 316 +++++++++++++++++++++ src/modules/postgresql_server/outputs.tf | 36 +++ src/modules/postgresql_server/variables.tf | 251 ++++++++++++++++ 5 files changed, 691 insertions(+), 1 deletion(-) create mode 100644 src/modules/postgresql_server/README.md create mode 100644 src/modules/postgresql_server/main.tf create mode 100644 src/modules/postgresql_server/outputs.tf create mode 100644 src/modules/postgresql_server/variables.tf diff --git a/src/core/postgres.tf b/src/core/postgres.tf index 8b3faeace..91c989705 100644 --- a/src/core/postgres.tf +++ b/src/core/postgres.tf @@ -31,7 +31,8 @@ module "postgres_snet" { #tfsec:ignore:azure-database-postgres-configuration-log-connection-throttling #tfsec:ignore:azure-database-postgres-configuration-log-connections module "postgresql" { - source = "git::https://github.com/pagopa/azurerm.git//postgresql_server?ref=v1.0.60" +// source = "git::https://github.com/pagopa/azurerm.git//postgresql_server?ref=v1.0.60" # TODO after apply of https://github.com/pagopa/azurerm/pull/104, use new version and remove local copy of the module + source = "../modules/postgresql_server" name = format("%s-postgresql", local.project) location = azurerm_resource_group.postgres_rg.location diff --git a/src/modules/postgresql_server/README.md b/src/modules/postgresql_server/README.md new file mode 100644 index 000000000..b824a828b --- /dev/null +++ b/src/modules/postgresql_server/README.md @@ -0,0 +1,86 @@ +## Requirements + +No requirements. + +## Providers + +| Name | Version | +|------|---------| +| [azurerm](#provider\_azurerm) | n/a | + +## Modules + +No modules. + +## Resources + +| Name | Type | +|------|------| +| [azurerm_management_lock.this](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/management_lock) | resource | +| [azurerm_monitor_metric_alert.replica](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/monitor_metric_alert) | resource | +| [azurerm_monitor_metric_alert.this](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/monitor_metric_alert) | resource | +| [azurerm_postgresql_configuration.main](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/postgresql_configuration) | resource | +| [azurerm_postgresql_configuration.replica](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/postgresql_configuration) | resource | +| [azurerm_postgresql_firewall_rule.azure](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/postgresql_firewall_rule) | resource | +| [azurerm_postgresql_firewall_rule.azure_replica](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/postgresql_firewall_rule) | resource | +| [azurerm_postgresql_firewall_rule.replica](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/postgresql_firewall_rule) | resource | +| [azurerm_postgresql_firewall_rule.this](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/postgresql_firewall_rule) | resource | +| [azurerm_postgresql_server.replica](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/postgresql_server) | resource | +| [azurerm_postgresql_server.this](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/postgresql_server) | resource | +| [azurerm_postgresql_virtual_network_rule.network_rule](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/postgresql_virtual_network_rule) | resource | +| [azurerm_postgresql_virtual_network_rule.replica](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/postgresql_virtual_network_rule) | resource | +| [azurerm_private_dns_zone.this](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/private_dns_zone) | resource | +| [azurerm_private_dns_zone_virtual_network_link.this](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/private_dns_zone_virtual_network_link) | resource | +| [azurerm_private_endpoint.replica](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/private_endpoint) | resource | +| [azurerm_private_endpoint.this](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/private_endpoint) | resource | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [administrator\_login](#input\_administrator\_login) | The Administrator Login for the PostgreSQL Server. | `string` | n/a | yes | +| [administrator\_login\_password](#input\_administrator\_login\_password) | The Password associated with the administrator\_login for the PostgreSQL Server. | `string` | n/a | yes | +| [db\_version](#input\_db\_version) | Specifies the version of PostgreSQL to use. | `number` | n/a | yes | +| [location](#input\_location) | n/a | `string` | n/a | yes | +| [name](#input\_name) | n/a | `string` | n/a | yes | +| [resource\_group\_name](#input\_resource\_group\_name) | n/a | `string` | n/a | yes | +| [sku\_name](#input\_sku\_name) | Specifies the SKU Name for this PostgreSQL Server. | `string` | n/a | yes | +| [tags](#input\_tags) | n/a | `map(any)` | n/a | yes | +| [virtual\_network\_id](#input\_virtual\_network\_id) | The ID of the Virtual Network that should be linked to the DNS Zone. | `string` | n/a | yes | +| [action](#input\_action) | The ID of the Action Group and optional map of custom string properties to include with the post webhook operation. |
set(object(
{
action_group_id = string
webhook_properties = map(string)
}
))
| `[]` | no | +| [alerts\_enabled](#input\_alerts\_enabled) | Should Metric Alerts be enabled? | `bool` | `true` | no | +| [backup\_retention\_days](#input\_backup\_retention\_days) | Backup retention days for the server, supported values are between | `number` | `7` | no | +| [configuration](#input\_configuration) | Map with PostgreSQL configurations. | `map(string)` | `{}` | no | +| [configuration\_replica](#input\_configuration\_replica) | Map with PostgreSQL configurations. | `map(string)` | `{}` | no | +| [create\_mode](#input\_create\_mode) | The creation mode. Can be used to restore or replicate existing servers. Possible values are Default, Replica, GeoRestore, and PointInTimeRestore | `string` | `"Default"` | no | +| [creation\_source\_server\_id](#input\_creation\_source\_server\_id) | For creation modes other then default the source server ID to use. | `string` | `null` | no | +| [enable\_replica](#input\_enable\_replica) | Create a replica server | `bool` | `false` | no | +| [geo\_redundant\_backup\_enabled](#input\_geo\_redundant\_backup\_enabled) | Turn Geo-redundant server backups on/off. | `bool` | `false` | no | +| [lock\_enable](#input\_lock\_enable) | Apply lock to block accedentaly deletions. | `bool` | `false` | no | +| [monitor\_metric\_alert\_criteria](#input\_monitor\_metric\_alert\_criteria) | Map of name = criteria objects, see these docs for options
https://docs.microsoft.com/en-us/azure/azure-monitor/platform/metrics-supported#microsoftdbforpostgresqlservers
https://docs.microsoft.com/en-us/azure/postgresql/concepts-limits#maximum-connections |
map(object({
# criteria.*.aggregation to be one of [Average Count Minimum Maximum Total]
aggregation = string
metric_name = string
# criteria.0.operator to be one of [Equals NotEquals GreaterThan GreaterThanOrEqual LessThan LessThanOrEqual]
operator = string
threshold = number
# Possible values are PT1M, PT5M, PT15M, PT30M and PT1H
frequency = string
# Possible values are PT1M, PT5M, PT15M, PT30M, PT1H, PT6H, PT12H and P1D.
window_size = string

dimension = list(object(
{
name = string
operator = string
values = list(string)
}
))
}))
| `{}` | no | +| [network\_rules](#input\_network\_rules) | Network rules restricting access to the postgresql server. |
object({
ip_rules = list(string)
allow_access_to_azure_services = bool
})
|
{
"allow_access_to_azure_services": false,
"ip_rules": []
}
| no | +| [private\_dns\_zone\_id](#input\_private\_dns\_zone\_id) | n/a | `string` | `null` | no | +| [private\_dns\_zone\_name](#input\_private\_dns\_zone\_name) | n/a | `string` | `"privatelink.postgres.database.azure.com"` | no | +| [public\_network\_access\_enabled](#input\_public\_network\_access\_enabled) | Whether or not public network access is allowed for this server. | `bool` | `true` | no | +| [replica\_action](#input\_replica\_action) | The ID of the Action Group and optional map of custom string properties to include with the post webhook operation. |
set(object(
{
action_group_id = string
webhook_properties = map(string)
}
))
| `[]` | no | +| [replica\_monitor\_metric\_alert\_criteria](#input\_replica\_monitor\_metric\_alert\_criteria) | Map of name = criteria objects, see these docs for options
https://docs.microsoft.com/en-us/azure/azure-monitor/platform/metrics-supported#microsoftdbforpostgresqlservers
https://docs.microsoft.com/en-us/azure/postgresql/concepts-limits#maximum-connections |
map(object({
# criteria.*.aggregation to be one of [Average Count Minimum Maximum Total]
aggregation = string
metric_name = string
# criteria.0.operator to be one of [Equals NotEquals GreaterThan GreaterThanOrEqual LessThan LessThanOrEqual]
operator = string
threshold = number
# Possible values are PT1M, PT5M, PT15M, PT30M and PT1H
frequency = string
# Possible values are PT1M, PT5M, PT15M, PT30M, PT1H, PT6H, PT12H and P1D.
window_size = string

dimension = list(object(
{
name = string
operator = string
values = list(string)
}
))
}))
| `{}` | no | +| [replica\_network\_rules](#input\_replica\_network\_rules) | Network rules restricting access to the replica postgresql server. |
object({
ip_rules = list(string)
allow_access_to_azure_services = bool
})
|
{
"allow_access_to_azure_services": false,
"ip_rules": []
}
| no | +| [restore\_point\_in\_time](#input\_restore\_point\_in\_time) | When create\_mode is PointInTimeRestore the point in time to restore from creation\_source\_server\_id. | `string` | `null` | no | +| [ssl\_enforcement\_enabled](#input\_ssl\_enforcement\_enabled) | Specifies if SSL should be enforced on connections. | `bool` | `true` | no | +| [ssl\_minimal\_tls\_version\_enforced](#input\_ssl\_minimal\_tls\_version\_enforced) | The mimimun TLS version to support on the sever | `string` | `"TLSEnforcementDisabled"` | no | +| [storage\_mb](#input\_storage\_mb) | Max storage allowed for a server. Possible values are between 5120 MB(5GB) and 1048576 MB(1TB) for the Basic SKU and between 5120 MB(5GB) and 16777216 MB(16TB) for General Purpose/Memory Optimized SKUs. | `number` | `5120` | no | +| [subnet\_id](#input\_subnet\_id) | The id of the subnet that will be used to deploy the database. | `string` | `null` | no | + +## Outputs + +| Name | Description | +|------|-------------| +| [administrator\_login](#output\_administrator\_login) | n/a | +| [administrator\_login\_password](#output\_administrator\_login\_password) | n/a | +| [fqdn](#output\_fqdn) | n/a | +| [id](#output\_id) | n/a | +| [name](#output\_name) | n/a | +| [private\_dns\_zone\_id](#output\_private\_dns\_zone\_id) | n/a | +| [replica\_fqdn](#output\_replica\_fqdn) | n/a | +| [replica\_id](#output\_replica\_id) | n/a | +| [replica\_name](#output\_replica\_name) | n/a | diff --git a/src/modules/postgresql_server/main.tf b/src/modules/postgresql_server/main.tf new file mode 100644 index 000000000..44153be9a --- /dev/null +++ b/src/modules/postgresql_server/main.tf @@ -0,0 +1,316 @@ +resource "azurerm_postgresql_server" "this" { + name = var.name + location = var.location + resource_group_name = var.resource_group_name + + administrator_login = var.administrator_login + administrator_login_password = var.administrator_login_password + + sku_name = var.sku_name + version = var.db_version + storage_mb = var.storage_mb + + backup_retention_days = var.backup_retention_days + geo_redundant_backup_enabled = var.geo_redundant_backup_enabled + + auto_grow_enabled = true + + public_network_access_enabled = var.public_network_access_enabled + ssl_enforcement_enabled = var.ssl_enforcement_enabled + ssl_minimal_tls_version_enforced = var.ssl_minimal_tls_version_enforced + + create_mode = var.create_mode + creation_source_server_id = var.creation_source_server_id + restore_point_in_time = var.restore_point_in_time + + + lifecycle { + ignore_changes = [ + # Autogrow is enabled + storage_mb, + ] + } + + tags = var.tags +} + +resource "azurerm_postgresql_server" "replica" { + count = var.enable_replica ? 1 : 0 + + name = format("%s-rep", var.name) + location = var.location + resource_group_name = var.resource_group_name + + administrator_login = var.administrator_login + administrator_login_password = var.administrator_login_password + + sku_name = var.sku_name + version = var.db_version + storage_mb = var.storage_mb + + backup_retention_days = var.backup_retention_days + geo_redundant_backup_enabled = var.geo_redundant_backup_enabled + + auto_grow_enabled = true + + public_network_access_enabled = var.public_network_access_enabled + ssl_enforcement_enabled = var.ssl_enforcement_enabled + ssl_minimal_tls_version_enforced = var.ssl_minimal_tls_version_enforced + + create_mode = "Replica" + creation_source_server_id = azurerm_postgresql_server.this.id + + lifecycle { + ignore_changes = [ + # Autogrow is enabled + storage_mb, + ] + } + + tags = var.tags +} + +locals { + firewall_rules = [for rule in var.network_rules.ip_rules : { + start : cidrhost(rule, 0) + end : cidrhost(rule, pow(2, (32 - parseint(split("/", rule)[1], 10))) - 1) + }] + + replica_firewall_rules = [for rule in var.replica_network_rules.ip_rules : { + start : cidrhost(rule, 0) + end : cidrhost(rule, pow(2, (32 - parseint(split("/", rule)[1], 10))) - 1) + }] + + private_dns_zone_name = var.private_dns_zone_id == null ? azurerm_private_dns_zone.this[0].name : var.private_dns_zone_name + private_dns_zone_id = var.private_dns_zone_id == null ? azurerm_private_dns_zone.this[0].id : var.private_dns_zone_id + + configuration_replica = var.enable_replica ? var.configuration_replica : {} +} + +resource "azurerm_private_dns_zone" "this" { + count = var.private_dns_zone_id == null ? 1 : 0 + + name = var.private_dns_zone_name + resource_group_name = var.resource_group_name + + tags = var.tags +} + +resource "azurerm_private_dns_zone_virtual_network_link" "this" { + + name = format("%s-private-dns-zone-link", var.name) + resource_group_name = var.resource_group_name + private_dns_zone_name = local.private_dns_zone_name + virtual_network_id = var.virtual_network_id + + tags = var.tags +} + +resource "azurerm_private_endpoint" "this" { + name = format("%s-private-endpoint", azurerm_postgresql_server.this.name) + location = var.location + resource_group_name = var.resource_group_name + subnet_id = var.subnet_id + + private_dns_zone_group { + name = format("%s-private-dns-zone-group", var.name) + private_dns_zone_ids = [local.private_dns_zone_id] + } + + private_service_connection { + name = format("%s-private-service-connection", azurerm_postgresql_server.this.name) + private_connection_resource_id = azurerm_postgresql_server.this.id + is_manual_connection = false + subresource_names = ["postgreSqlServer"] + } + + tags = var.tags +} + +resource "azurerm_private_endpoint" "replica" { + count = var.enable_replica ? 1 : 0 + + name = format("%s-private-endpoint", azurerm_postgresql_server.replica[0].name) + location = var.location + resource_group_name = var.resource_group_name + subnet_id = var.subnet_id + + private_dns_zone_group { + name = format("%s-private-dns-zone-group", var.name) + private_dns_zone_ids = [local.private_dns_zone_id] + } + + private_service_connection { + name = format("%s-private-service-connection", azurerm_postgresql_server.replica[0].name) + private_connection_resource_id = azurerm_postgresql_server.replica[0].id + is_manual_connection = false + subresource_names = ["postgreSqlServer"] + } + + tags = var.tags +} + +resource "azurerm_postgresql_virtual_network_rule" "network_rule" { + count = var.public_network_access_enabled? 1 : 0 + + name = format("%s-vnet-rule", var.name) + resource_group_name = var.resource_group_name + server_name = azurerm_postgresql_server.this.name + subnet_id = var.subnet_id + ignore_missing_vnet_service_endpoint = true +} + +resource "azurerm_postgresql_firewall_rule" "this" { + count = var.public_network_access_enabled? length(local.firewall_rules) : 0 + + name = format("%s-fw-rule-%d", var.name, count.index) + resource_group_name = var.resource_group_name + server_name = azurerm_postgresql_server.this.name + start_ip_address = local.firewall_rules[count.index].start + end_ip_address = local.firewall_rules[count.index].end +} + +resource "azurerm_postgresql_firewall_rule" "azure" { + count = var.network_rules.allow_access_to_azure_services && var.public_network_access_enabled ? 1 : 0 + + name = format("%s-allow-azure-access", var.name) + resource_group_name = var.resource_group_name + server_name = azurerm_postgresql_server.this.name + start_ip_address = "0.0.0.0" + end_ip_address = "0.0.0.0" +} + +resource "azurerm_postgresql_configuration" "main" { + for_each = var.configuration + + name = each.key + resource_group_name = var.resource_group_name + server_name = azurerm_postgresql_server.this.name + value = each.value +} + +resource "azurerm_postgresql_configuration" "replica" { + for_each = local.configuration_replica + + name = each.key + resource_group_name = var.resource_group_name + server_name = azurerm_postgresql_server.replica[0].name + value = each.value +} + +resource "azurerm_monitor_metric_alert" "this" { + for_each = var.monitor_metric_alert_criteria + + name = format("%s-%s", azurerm_postgresql_server.this.name, upper(each.key)) + resource_group_name = var.resource_group_name + scopes = [azurerm_postgresql_server.this.id] + frequency = each.value.frequency + window_size = each.value.window_size + enabled = var.alerts_enabled + + dynamic "action" { + for_each = var.action + content { + # action_group_id - (required) is a type of string + action_group_id = action.value["action_group_id"] + # webhook_properties - (optional) is a type of map of string + webhook_properties = action.value["webhook_properties"] + } + } + + criteria { + aggregation = each.value.aggregation + metric_namespace = "Microsoft.DBforPostgreSQL/servers" + metric_name = each.value.metric_name + operator = each.value.operator + threshold = each.value.threshold + + dynamic "dimension" { + for_each = each.value.dimension + content { + name = dimension.value.name + operator = dimension.value.operator + values = dimension.value.values + } + } + } +} + + +resource "azurerm_monitor_metric_alert" "replica" { + for_each = var.enable_replica ? var.replica_monitor_metric_alert_criteria : {} + + name = format("%s-%s", azurerm_postgresql_server.replica[0].name, upper(each.key)) + resource_group_name = var.resource_group_name + scopes = [azurerm_postgresql_server.replica[0].id] + frequency = each.value.frequency + window_size = each.value.window_size + enabled = var.alerts_enabled + + dynamic "action" { + for_each = var.replica_action + content { + # action_group_id - (required) is a type of string + action_group_id = action.value["action_group_id"] + # webhook_properties - (optional) is a type of map of string + webhook_properties = action.value["webhook_properties"] + } + } + + criteria { + aggregation = each.value.aggregation + metric_namespace = "Microsoft.DBforPostgreSQL/servers" + metric_name = each.value.metric_name + operator = each.value.operator + threshold = each.value.threshold + + dynamic "dimension" { + for_each = each.value.dimension + content { + name = dimension.value.name + operator = dimension.value.operator + values = dimension.value.values + } + } + } +} + + +resource "azurerm_postgresql_virtual_network_rule" "replica" { + count = var.enable_replica && var.public_network_access_enabled ? 1 : 0 + + name = format("%s-rep-vnet-rule", var.name) + resource_group_name = var.resource_group_name + server_name = azurerm_postgresql_server.replica[0].name + subnet_id = var.subnet_id + ignore_missing_vnet_service_endpoint = true +} + +resource "azurerm_postgresql_firewall_rule" "replica" { + count = var.enable_replica ? length(local.replica_firewall_rules) : 0 + + name = format("%s-rep-fw-rule-%d", var.name, count.index) + resource_group_name = var.resource_group_name + server_name = azurerm_postgresql_server.replica[0].name + start_ip_address = local.replica_firewall_rules[count.index].start + end_ip_address = local.replica_firewall_rules[count.index].end +} + +resource "azurerm_postgresql_firewall_rule" "azure_replica" { + count = var.enable_replica && var.replica_network_rules.allow_access_to_azure_services ? 1 : 0 + + name = format("%s-rep-allow-azure-access", var.name) + resource_group_name = var.resource_group_name + server_name = azurerm_postgresql_server.replica[0].name + start_ip_address = "0.0.0.0" + end_ip_address = "0.0.0.0" +} + + +resource "azurerm_management_lock" "this" { + count = var.lock_enable ? 1 : 0 + name = format("%s-lock", azurerm_postgresql_server.this.name) + scope = azurerm_postgresql_server.this.id + lock_level = "CanNotDelete" + notes = "This items can't be deleted in this subscription!" +} diff --git a/src/modules/postgresql_server/outputs.tf b/src/modules/postgresql_server/outputs.tf new file mode 100644 index 000000000..c1cf93652 --- /dev/null +++ b/src/modules/postgresql_server/outputs.tf @@ -0,0 +1,36 @@ +output "id" { + value = azurerm_postgresql_server.this.id +} + +output "name" { + value = azurerm_postgresql_server.this.name +} + +output "fqdn" { + value = azurerm_postgresql_server.this.fqdn +} + +output "private_dns_zone_id" { + value = local.private_dns_zone_id +} + +output "administrator_login" { + value = var.administrator_login +} + +output "administrator_login_password" { + value = var.administrator_login_password + sensitive = true +} + +output "replica_id" { + value = var.enable_replica ? azurerm_postgresql_server.replica[0].id : "" +} + +output "replica_name" { + value = var.enable_replica ? azurerm_postgresql_server.replica[0].name : "" +} + +output "replica_fqdn" { + value = var.enable_replica ? azurerm_postgresql_server.replica[0].fqdn : "" +} diff --git a/src/modules/postgresql_server/variables.tf b/src/modules/postgresql_server/variables.tf new file mode 100644 index 000000000..5f7b5c64c --- /dev/null +++ b/src/modules/postgresql_server/variables.tf @@ -0,0 +1,251 @@ +variable "name" { + type = string +} + +variable "location" { + type = string +} + +variable "resource_group_name" { + type = string +} + +variable "virtual_network_id" { + type = string + description = "The ID of the Virtual Network that should be linked to the DNS Zone." +} + +variable "subnet_id" { + type = string + default = null + description = "The id of the subnet that will be used to deploy the database." +} + +variable "network_rules" { + description = "Network rules restricting access to the postgresql server." + type = object({ + ip_rules = list(string) + allow_access_to_azure_services = bool + }) + default = { + ip_rules = [] + allow_access_to_azure_services = false + } +} + +variable "administrator_login" { + type = string + description = "The Administrator Login for the PostgreSQL Server." +} + +variable "administrator_login_password" { + type = string + description = "The Password associated with the administrator_login for the PostgreSQL Server." + sensitive = true +} + +variable "sku_name" { + type = string + description = "Specifies the SKU Name for this PostgreSQL Server. " +} + +variable "db_version" { + type = number + description = "Specifies the version of PostgreSQL to use." +} + +variable "storage_mb" { + type = number + description = "Max storage allowed for a server. Possible values are between 5120 MB(5GB) and 1048576 MB(1TB) for the Basic SKU and between 5120 MB(5GB) and 16777216 MB(16TB) for General Purpose/Memory Optimized SKUs. " + default = 5120 +} + +variable "public_network_access_enabled" { + type = bool + description = "Whether or not public network access is allowed for this server." + default = true +} + +variable "ssl_enforcement_enabled" { + type = bool + description = "Specifies if SSL should be enforced on connections." + default = true +} + +variable "ssl_minimal_tls_version_enforced" { + type = string + description = "The mimimun TLS version to support on the sever" + default = "TLSEnforcementDisabled" +} + +variable "backup_retention_days" { + type = number + description = "Backup retention days for the server, supported values are between" + default = 7 +} + +variable "geo_redundant_backup_enabled" { + type = bool + description = "Turn Geo-redundant server backups on/off." + default = false +} + +variable "enable_replica" { + type = bool + description = "Create a replica server" + default = false +} + +variable "create_mode" { + type = string + description = "The creation mode. Can be used to restore or replicate existing servers. Possible values are Default, Replica, GeoRestore, and PointInTimeRestore" + default = "Default" +} + +variable "creation_source_server_id" { + type = string + description = "For creation modes other then default the source server ID to use." + default = null +} + +variable "restore_point_in_time" { + type = string + description = "When create_mode is PointInTimeRestore the point in time to restore from creation_source_server_id." + default = null +} + +variable "configuration" { + description = "Map with PostgreSQL configurations." + type = map(string) + default = {} +} + +variable "configuration_replica" { + description = "Map with PostgreSQL configurations." + type = map(string) + default = {} +} + +variable "private_dns_zone_id" { + type = string + default = null +} + +variable "private_dns_zone_name" { + type = string + default = "privatelink.postgres.database.azure.com" +} + +variable "alerts_enabled" { + type = bool + default = true + description = "Should Metric Alerts be enabled?" +} + +variable "action" { + description = "The ID of the Action Group and optional map of custom string properties to include with the post webhook operation." + type = set(object( + { + action_group_id = string + webhook_properties = map(string) + } + )) + default = [] +} + + +variable "monitor_metric_alert_criteria" { + default = {} + + description = < Date: Fri, 22 Oct 2021 17:36:23 +0200 Subject: [PATCH 5/6] fixed hubSpidLoginMetadata url --- src/core/spid-testenv.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/spid-testenv.tf b/src/core/spid-testenv.tf index 914095b9b..5d03fddf5 100644 --- a/src/core/spid-testenv.tf +++ b/src/core/spid-testenv.tf @@ -7,7 +7,7 @@ module "spid-test-env" { location = var.location subscription_name = data.azurerm_subscription.current.display_name - hub_spid_login_metadata_url = format("https://api.%s.%s/hubspidloginms/metadata", var.dns_zone_prefix, var.external_domain) + hub_spid_login_metadata_url = format("https://api.%s.%s/spid/v1/metadata", var.dns_zone_prefix, var.external_domain) tags = var.tags } From 72f16b20b7c84fd98358fc3a9d99959ed9ca009d Mon Sep 17 00:00:00 2001 From: anttorre Date: Fri, 22 Oct 2021 17:45:58 +0200 Subject: [PATCH 6/6] fixed hubSpidLoginMetadata url --- src/core/spid_testenv_conf/config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/spid_testenv_conf/config.yaml b/src/core/spid_testenv_conf/config.yaml index a3e4e50de..191e43d6f 100644 --- a/src/core/spid_testenv_conf/config.yaml +++ b/src/core/spid_testenv_conf/config.yaml @@ -16,7 +16,7 @@ cert_file: "./conf/idp.crt" # using different sources. metadata: remote: - - "https://api.dev.selfcare.pagopa.it/hubspidloginms/metadata" + - "https://api.dev.selfcare.pagopa.it/spid/v1/metadata" # Application configuration