From 42eccf9315174ccb35cdbf8ae8614ee57b784378 Mon Sep 17 00:00:00 2001 From: Krusty93 Date: Mon, 24 Nov 2025 16:48:22 +0100 Subject: [PATCH 01/10] add module --- .../modules/azure_app_configuration/README.md | 71 ++++++++++--------- .../examples/network_access/README.md | 38 ++++++++++ .../examples/network_access/REAMDE.md | 5 ++ .../examples/network_access/data.tf | 20 ++++++ .../examples/network_access/fixtures.tf | 10 +++ .../examples/network_access/locals.tf | 38 ++++++++++ .../examples/network_access/mut.tf | 24 +++++++ .../examples/network_access/outputs.tf | 3 + .../examples/network_access/providers.tf | 33 +++++++++ 9 files changed, 207 insertions(+), 35 deletions(-) create mode 100644 infra/modules/azure_app_configuration/examples/network_access/README.md create mode 100644 infra/modules/azure_app_configuration/examples/network_access/REAMDE.md create mode 100644 infra/modules/azure_app_configuration/examples/network_access/data.tf create mode 100644 infra/modules/azure_app_configuration/examples/network_access/fixtures.tf create mode 100644 infra/modules/azure_app_configuration/examples/network_access/locals.tf create mode 100644 infra/modules/azure_app_configuration/examples/network_access/mut.tf create mode 100644 infra/modules/azure_app_configuration/examples/network_access/outputs.tf create mode 100644 infra/modules/azure_app_configuration/examples/network_access/providers.tf diff --git a/infra/modules/azure_app_configuration/README.md b/infra/modules/azure_app_configuration/README.md index 9e96b6ce3d..946141d38a 100644 --- a/infra/modules/azure_app_configuration/README.md +++ b/infra/modules/azure_app_configuration/README.md @@ -29,53 +29,54 @@ The allowed sizes are: For examples of how to use this module, refer to the [examples](https://github.com/pagopa-dx/terraform-azurerm-azure-app-configuration/tree/main/examples) folder in the module repository. + ## Requirements -| Name | Version | -|------|---------| -| [azurerm](#requirement\_azurerm) | ~> 4.0 | -| [pagopa-dx](#requirement\_pagopa-dx) | ~> 0.8 | +| Name | Version | +| ------------------------------------------------------------------------ | ------- | +| [azurerm](#requirement_azurerm) | ~> 4.0 | +| [pagopa-dx](#requirement_pagopa-dx) | ~> 0.8 | ## Modules -| Name | Source | Version | -|------|--------|---------| -| [app\_roles](#module\_app\_roles) | pagopa-dx/azure-role-assignments/azurerm | ~> 1.3 | -| [appconfig\_team\_roles](#module\_appconfig\_team\_roles) | pagopa-dx/azure-role-assignments/azurerm | ~> 1.3 | +| Name | Source | Version | +| ----------------------------------------------------------------------------------------------- | ---------------------------------------- | ------- | +| [app_roles](#module_app_roles) | pagopa-dx/azure-role-assignments/azurerm | ~> 1.3 | +| [appconfig_team_roles](#module_appconfig_team_roles) | pagopa-dx/azure-role-assignments/azurerm | ~> 1.3 | ## Resources -| Name | Type | -|------|------| -| [azurerm_app_configuration.this](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/app_configuration) | resource | -| [azurerm_monitor_diagnostic_setting.app_configuration](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/monitor_diagnostic_setting) | resource | -| [azurerm_private_endpoint.app_config](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/private_endpoint) | resource | -| [azurerm_private_dns_zone.appconfig](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/private_dns_zone) | data source | +| Name | Type | +| ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------- | +| [azurerm_app_configuration.this](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/app_configuration) | resource | +| [azurerm_monitor_diagnostic_setting.app_configuration](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/monitor_diagnostic_setting) | resource | +| [azurerm_private_endpoint.app_config](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/private_endpoint) | resource | +| [azurerm_private_dns_zone.appconfig](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/private_dns_zone) | data source | ## Inputs -| Name | Description | Type | Default | Required | -|------|-------------|------|---------|:--------:| -| [authorized\_teams](#input\_authorized\_teams) | Object containing lists of principal IDs (Azure AD object IDs) of product teams to be granted read or write permissions on the App Configuration. These represent the teams within the organization that need access to this resource." |
object({
writers = optional(list(string), []),
readers = optional(list(string), [])
})
|
{
"readers": [],
"writers": []
}
| no | -| [diagnostic\_settings](#input\_diagnostic\_settings) | Diagnostic settings for App Configuration logs and metrics. When enabled, sends diagnostics to Log Analytics workspace and/or Storage Account. |
object({
enabled = bool
log_analytics_workspace_id = optional(string, null)
storage_account_id = optional(string, null)
})
|
{
"enabled": false,
"log_analytics_workspace_id": null
}
| no | -| [environment](#input\_environment) | Values which are used to generate resource names and location short names. They are all mandatory except for domain, which should not be used only in the case of a resource used by multiple domains. |
object({
prefix = string
env_short = string
location = string
domain = optional(string)
app_name = string
instance_number = string
})
| n/a | yes | -| [key\_vaults](#input\_key\_vaults) | Optionally, integrate App Configuration with a one or more existing Key Vault for secrets retrieval.
Set `has_rbac_support` to true if the referenced Key Vault uses RBAC model for access control.
Use `app_principal_ids` to set application principal IDs to be granted access to the Key Vault. |
list(object({
name = string
resource_group_name = string
has_rbac_support = bool
app_principal_ids = list(string)
}))
| `null` | no | -| [private\_dns\_zone\_resource\_group\_name](#input\_private\_dns\_zone\_resource\_group\_name) | Name of the resource group containing the private DNS zone for private endpoints. Default is the resource group of the virtual network. | `string` | `null` | no | -| [resource\_group\_name](#input\_resource\_group\_name) | The name of the resource group where resources will be deployed. | `string` | n/a | yes | -| [size](#input\_size) | "App Configuration SKU. Allowed values: 'standard', 'premium'. If not set, it will be determined by the use\_case." | `string` | `null` | no | -| [subnet\_pep\_id](#input\_subnet\_pep\_id) | ID of the subnet hosting private endpoints. | `string` | n/a | yes | -| [subscription\_id](#input\_subscription\_id) | Subscription Id of the involved resources | `string` | n/a | yes | -| [tags](#input\_tags) | A map of tags to assign to the resources. | `map(any)` | n/a | yes | -| [use\_case](#input\_use\_case) | Allowed values: 'default', 'development'. | `string` | `"default"` | no | -| [virtual\_network](#input\_virtual\_network) | Virtual network where the subnet will be created. |
object({
name = string
resource_group_name = string
})
| n/a | yes | +| Name | Description | Type | Default | Required | +| --------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------- | :------: | +| [authorized_teams](#input_authorized_teams) | Object containing lists of principal IDs (Azure AD object IDs) of product teams to be granted read or write permissions on the App Configuration. These represent the teams within the organization that need access to this resource." |
object({
writers = optional(list(string), []),
readers = optional(list(string), [])
})
|
{
"readers": [],
"writers": []
}
| no | +| [environment](#input_environment) | Values which are used to generate resource names and location short names. They are all mandatory except for domain, which should not be used only in the case of a resource used by multiple domains. |
object({
prefix = string
env_short = string
location = string
domain = optional(string)
app_name = string
instance_number = string
})
| n/a | yes | +| [key_vaults](#input_key_vaults) | Optionally, integrate App Configuration with a one or more existing Key Vault for secrets retrieval.
Set `has_rbac_support` to true if the referenced Key Vault uses RBAC model for access control.
Use `app_principal_ids` to set application principal IDs to be granted access to the Key Vault. |
list(object({
name = string
resource_group_name = string
has_rbac_support = bool
app_principal_ids = list(string)
}))
| `null` | no | +| [private_dns_zone_resource_group_name](#input_private_dns_zone_resource_group_name) | Name of the resource group containing the private DNS zone for private endpoints. Default is the resource group of the virtual network. | `string` | `null` | no | +| [resource_group_name](#input_resource_group_name) | The name of the resource group where resources will be deployed. | `string` | n/a | yes | +| [size](#input_size) | "App Configuration SKU. Allowed values: 'standard', 'premium'. If not set, it will be determined by the use_case." | `string` | `null` | no | +| [subnet_pep_id](#input_subnet_pep_id) | ID of the subnet hosting private endpoints. | `string` | n/a | yes | +| [subscription_id](#input_subscription_id) | Subscription Id of the involved resources | `string` | n/a | yes | +| [tags](#input_tags) | A map of tags to assign to the resources. | `map(any)` | n/a | yes | +| [use_case](#input_use_case) | Allowed values: 'default', 'development'. | `string` | `"default"` | no | +| [virtual_network](#input_virtual_network) | Virtual network where the subnet will be created. |
object({
name = string
resource_group_name = string
})
| n/a | yes | ## Outputs -| Name | Description | -|------|-------------| -| [endpoint](#output\_endpoint) | The service endpoint URL | -| [id](#output\_id) | The ID of the Azure Cosmos DB account. | -| [name](#output\_name) | The name of the Azure Cosmos DB account. | -| [principal\_id](#output\_principal\_id) | The system-assigned managed identity pricipal id | -| [resource\_group\_name](#output\_resource\_group\_name) | The name of the resource group containing the Azure Cosmos DB account. | +| Name | Description | +| -------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------- | +| [endpoint](#output_endpoint) | The service endpoint URL | +| [id](#output_id) | The ID of the Azure Cosmos DB account. | +| [name](#output_name) | The name of the Azure Cosmos DB account. | +| [principal_id](#output_principal_id) | The system-assigned managed identity pricipal id | +| [resource_group_name](#output_resource_group_name) | The name of the resource group containing the Azure Cosmos DB account. | + diff --git a/infra/modules/azure_app_configuration/examples/network_access/README.md b/infra/modules/azure_app_configuration/examples/network_access/README.md new file mode 100644 index 0000000000..eb4d81f55f --- /dev/null +++ b/infra/modules/azure_app_configuration/examples/network_access/README.md @@ -0,0 +1,38 @@ +# network_access + + +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 1.13.0 | +| [azurerm](#requirement\_azurerm) | ~> 4.0 | +| [pagopa-dx](#requirement\_pagopa-dx) | ~> 0.8 | +| [random](#requirement\_random) | ~> 3.7 | + +## Modules + +| Name | Source | Version | +|------|--------|---------| +| [private\_appcs](#module\_private\_appcs) | ../../ | n/a | + +## Resources + +| Name | Type | +|------|------| +| [azurerm_resource_group.e2e_appcs](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/resource_group) | resource | +| [random_integer.appcs_instance](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/integer) | resource | +| [azurerm_resource_group.network](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/resource_group) | data source | +| [azurerm_subnet.pep](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/subnet) | data source | +| [azurerm_virtual_network.e2e](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/virtual_network) | data source | + +## Inputs + +No inputs. + +## Outputs + +| Name | Description | +|------|-------------| +| [name](#output\_name) | n/a | + diff --git a/infra/modules/azure_app_configuration/examples/network_access/REAMDE.md b/infra/modules/azure_app_configuration/examples/network_access/REAMDE.md new file mode 100644 index 0000000000..4df5cd0c99 --- /dev/null +++ b/infra/modules/azure_app_configuration/examples/network_access/REAMDE.md @@ -0,0 +1,5 @@ +# network_access + + + + diff --git a/infra/modules/azure_app_configuration/examples/network_access/data.tf b/infra/modules/azure_app_configuration/examples/network_access/data.tf new file mode 100644 index 0000000000..208aa45d47 --- /dev/null +++ b/infra/modules/azure_app_configuration/examples/network_access/data.tf @@ -0,0 +1,20 @@ +data "azurerm_virtual_network" "e2e" { + name = local.e2e_virtual_network.name + resource_group_name = local.e2e_virtual_network.resource_group_name +} + +data "azurerm_subnet" "pep" { + name = provider::pagopa-dx::resource_name(merge(local.naming_config, { + name = "pep", + resource_type = "subnet" + })) + virtual_network_name = data.azurerm_virtual_network.e2e.name + resource_group_name = data.azurerm_virtual_network.e2e.resource_group_name +} + +data "azurerm_resource_group" "network" { + name = provider::pagopa-dx::resource_name(merge(local.naming_config, { + name = "network" + resource_type = "resource_group" + })) +} diff --git a/infra/modules/azure_app_configuration/examples/network_access/fixtures.tf b/infra/modules/azure_app_configuration/examples/network_access/fixtures.tf new file mode 100644 index 0000000000..0b8e731e33 --- /dev/null +++ b/infra/modules/azure_app_configuration/examples/network_access/fixtures.tf @@ -0,0 +1,10 @@ +resource "azurerm_resource_group" "e2e_appcs" { + name = provider::pagopa-dx::resource_name(merge(local.naming_config, { + domain = "e2e" + name = "appcs", + resource_type = "resource_group" + })) + location = local.environment.location + + tags = local.tags +} diff --git a/infra/modules/azure_app_configuration/examples/network_access/locals.tf b/infra/modules/azure_app_configuration/examples/network_access/locals.tf new file mode 100644 index 0000000000..d7481adcaa --- /dev/null +++ b/infra/modules/azure_app_configuration/examples/network_access/locals.tf @@ -0,0 +1,38 @@ +locals { + tags = { + CostCenter = "TS000 - Tecnologia e Servizi" + CreatedBy = "Terraform" + Environment = "Dev" + BusinessUnit = "DevEx" + Source = "https://github.com/pagopa/dx/tests/azure_app_configuration" + ManagementTeam = "Developer Experience" + TestSuite = "e2e" + } + + environment = { + prefix = "dx" + env_short = "d" + location = "italynorth" + app_name = "e2e" + instance_number = "01" + } + + naming_config = { + prefix = local.environment.prefix, + environment = local.environment.env_short, + location = local.environment.location, + name = local.environment.app_name, + instance_number = tonumber(local.environment.instance_number), + } + + e2e_virtual_network = { + name = provider::pagopa-dx::resource_name(merge(local.naming_config, { + name = "e2e", + resource_type = "virtual_network" + })) + resource_group_name = provider::pagopa-dx::resource_name(merge(local.naming_config, { + name = "e2e", + resource_type = "resource_group" + })) + } +} diff --git a/infra/modules/azure_app_configuration/examples/network_access/mut.tf b/infra/modules/azure_app_configuration/examples/network_access/mut.tf new file mode 100644 index 0000000000..8e26a436c8 --- /dev/null +++ b/infra/modules/azure_app_configuration/examples/network_access/mut.tf @@ -0,0 +1,24 @@ +resource "random_integer" "appcs_instance" { + min = 1 + max = 99 +} + +module "private_appcs" { + source = "../../" + # version = ">= 0.3" + + # provider::dx::resource_name(merge(local.naming_config, { resource_type = "key_vault", domain = "int", instance_number = random_integer.kv_instance.result })) + environment = (merge(local.environment, { instance_number = random_integer.appcs_instance.result })) + resource_group_name = azurerm_resource_group.e2e_appcs.name + + subnet_pep_id = data.azurerm_subnet.pep.id + + virtual_network = { + name = local.e2e_virtual_network.name + resource_group_name = local.e2e_virtual_network.resource_group_name + } + + private_dns_zone_resource_group_name = data.azurerm_resource_group.network.name + + tags = local.tags +} diff --git a/infra/modules/azure_app_configuration/examples/network_access/outputs.tf b/infra/modules/azure_app_configuration/examples/network_access/outputs.tf new file mode 100644 index 0000000000..df43cc6eee --- /dev/null +++ b/infra/modules/azure_app_configuration/examples/network_access/outputs.tf @@ -0,0 +1,3 @@ +output "name" { + value = module.private_appcs.name +} diff --git a/infra/modules/azure_app_configuration/examples/network_access/providers.tf b/infra/modules/azure_app_configuration/examples/network_access/providers.tf new file mode 100644 index 0000000000..75e33e5c13 --- /dev/null +++ b/infra/modules/azure_app_configuration/examples/network_access/providers.tf @@ -0,0 +1,33 @@ +terraform { + required_version = ">= 1.13.0" + + required_providers { + azurerm = { + source = "hashicorp/azurerm" + version = "~> 4.0" + } + pagopa-dx = { + source = "pagopa-dx/azure" + version = "~> 0.8" + } + random = { + source = "hashicorp/random" + version = "~> 3.7" + } + } +} + +provider "azurerm" { + features { + resource_group { + prevent_deletion_if_contains_resources = false + } + app_configuration { + purge_soft_delete_on_destroy = true + recover_soft_deleted = true + } + } +} + +provider "random" { +} From cb0749dad8a3ceae2f6425ec4530a9d7213b97da Mon Sep 17 00:00:00 2001 From: Krusty93 Date: Mon, 24 Nov 2025 18:06:19 +0100 Subject: [PATCH 02/10] add integration tests and fixes --- .../tests/setup/README.md | 68 ++++++++++--------- 1 file changed, 35 insertions(+), 33 deletions(-) diff --git a/infra/modules/azure_app_configuration/tests/setup/README.md b/infra/modules/azure_app_configuration/tests/setup/README.md index a46df95900..11a1e7d420 100644 --- a/infra/modules/azure_app_configuration/tests/setup/README.md +++ b/infra/modules/azure_app_configuration/tests/setup/README.md @@ -1,13 +1,14 @@ # setup + ## Requirements -| Name | Version | -|------|---------| -| [azurerm](#requirement\_azurerm) | ~> 4.0 | -| [dx](#requirement\_dx) | ~> 0.8 | -| [random](#requirement\_random) | ~> 3.7 | +| Name | Version | +| ------------------------------------------------------------------ | ------- | +| [azurerm](#requirement_azurerm) | ~> 4.0 | +| [dx](#requirement_dx) | ~> 0.8 | +| [random](#requirement_random) | ~> 3.7 | ## Modules @@ -15,39 +16,40 @@ No modules. ## Resources -| Name | Type | -|------|------| -| [azurerm_key_vault.kv](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/key_vault) | resource | -| [azurerm_private_endpoint.kv](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/private_endpoint) | resource | -| [azurerm_resource_group.sut](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/resource_group) | resource | -| [random_integer.appcs_kv_instance](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/integer) | resource | -| [azurerm_client_config.current](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/client_config) | data source | -| [azurerm_private_dns_zone.appcs](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/private_dns_zone) | data source | -| [azurerm_private_dns_zone.kv](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/private_dns_zone) | data source | -| [azurerm_resource_group.network](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/resource_group) | data source | -| [azurerm_resource_group.test](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/resource_group) | data source | -| [azurerm_subnet.pep](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/subnet) | data source | +| Name | Type | +| ------------------------------------------------------------------------------------------------------------------------------------------------ | ----------- | +| [azurerm_key_vault.kv](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/key_vault) | resource | +| [azurerm_private_endpoint.kv](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/private_endpoint) | resource | +| [azurerm_resource_group.sut](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/resource_group) | resource | +| [random_integer.appcs_kv_instance](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/integer) | resource | +| [azurerm_client_config.current](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/client_config) | data source | +| [azurerm_private_dns_zone.appcs](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/private_dns_zone) | data source | +| [azurerm_private_dns_zone.kv](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/private_dns_zone) | data source | +| [azurerm_resource_group.network](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/resource_group) | data source | +| [azurerm_resource_group.test](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/resource_group) | data source | +| [azurerm_subnet.pep](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/subnet) | data source | | [azurerm_user_assigned_identity.test](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/user_assigned_identity) | data source | -| [azurerm_virtual_network.vnet](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/virtual_network) | data source | +| [azurerm_virtual_network.vnet](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/virtual_network) | data source | ## Inputs -| Name | Description | Type | Default | Required | -|------|-------------|------|---------|:--------:| -| [environment](#input\_environment) | n/a |
object({
prefix = string
env_short = string
location = string
domain = optional(string)
app_name = string
instance_number = string
})
| n/a | yes | -| [tags](#input\_tags) | Tags to apply to setup resources | `map(string)` | n/a | yes | -| [test\_kind](#input\_test\_kind) | A value between integration and e2e | `string` | n/a | yes | +| Name | Description | Type | Default | Required | +| ------------------------------------------------------------------ | ----------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | :------: | +| [environment](#input_environment) | n/a |
object({
prefix = string
env_short = string
location = string
domain = optional(string)
app_name = string
instance_number = string
})
| n/a | yes | +| [tags](#input_tags) | Tags to apply to setup resources | `map(string)` | n/a | yes | +| [test_kind](#input_test_kind) | A value between integration and e2e | `string` | n/a | yes | ## Outputs -| Name | Description | -|------|-------------| -| [key\_vaults](#output\_key\_vaults) | n/a | -| [managed\_identity\_principal\_id](#output\_managed\_identity\_principal\_id) | n/a | -| [private\_dns\_zone\_appcs](#output\_private\_dns\_zone\_appcs) | n/a | -| [private\_dns\_zone\_resource\_group\_name](#output\_private\_dns\_zone\_resource\_group\_name) | n/a | -| [resource\_group\_name](#output\_resource\_group\_name) | n/a | -| [subnet\_pep\_id](#output\_subnet\_pep\_id) | n/a | -| [subscription\_id](#output\_subscription\_id) | n/a | -| [virtual\_network](#output\_virtual\_network) | n/a | +| Name | Description | +| ----------------------------------------------------------------------------------------------------------------------------------------------- | ----------- | +| [key_vaults](#output_key_vaults) | n/a | +| [managed_identity_principal_id](#output_managed_identity_principal_id) | n/a | +| [private_dns_zone_appcs](#output_private_dns_zone_appcs) | n/a | +| [private_dns_zone_resource_group_name](#output_private_dns_zone_resource_group_name) | n/a | +| [resource_group_name](#output_resource_group_name) | n/a | +| [subnet_pep_id](#output_subnet_pep_id) | n/a | +| [subscription_id](#output_subscription_id) | n/a | +| [virtual_network](#output_virtual_network) | n/a | + From f9f7bbf6af35c40ae7842b02ef940ae81eb1ef39 Mon Sep 17 00:00:00 2001 From: Krusty93 Date: Mon, 24 Nov 2025 18:06:34 +0100 Subject: [PATCH 03/10] remove example --- .../examples/network_access/README.md | 38 ------------------- .../examples/network_access/REAMDE.md | 5 --- .../examples/network_access/data.tf | 20 ---------- .../examples/network_access/fixtures.tf | 10 ----- .../examples/network_access/locals.tf | 38 ------------------- .../examples/network_access/mut.tf | 24 ------------ .../examples/network_access/outputs.tf | 3 -- .../examples/network_access/providers.tf | 33 ---------------- 8 files changed, 171 deletions(-) delete mode 100644 infra/modules/azure_app_configuration/examples/network_access/README.md delete mode 100644 infra/modules/azure_app_configuration/examples/network_access/REAMDE.md delete mode 100644 infra/modules/azure_app_configuration/examples/network_access/data.tf delete mode 100644 infra/modules/azure_app_configuration/examples/network_access/fixtures.tf delete mode 100644 infra/modules/azure_app_configuration/examples/network_access/locals.tf delete mode 100644 infra/modules/azure_app_configuration/examples/network_access/mut.tf delete mode 100644 infra/modules/azure_app_configuration/examples/network_access/outputs.tf delete mode 100644 infra/modules/azure_app_configuration/examples/network_access/providers.tf diff --git a/infra/modules/azure_app_configuration/examples/network_access/README.md b/infra/modules/azure_app_configuration/examples/network_access/README.md deleted file mode 100644 index eb4d81f55f..0000000000 --- a/infra/modules/azure_app_configuration/examples/network_access/README.md +++ /dev/null @@ -1,38 +0,0 @@ -# network_access - - -## Requirements - -| Name | Version | -|------|---------| -| [terraform](#requirement\_terraform) | >= 1.13.0 | -| [azurerm](#requirement\_azurerm) | ~> 4.0 | -| [pagopa-dx](#requirement\_pagopa-dx) | ~> 0.8 | -| [random](#requirement\_random) | ~> 3.7 | - -## Modules - -| Name | Source | Version | -|------|--------|---------| -| [private\_appcs](#module\_private\_appcs) | ../../ | n/a | - -## Resources - -| Name | Type | -|------|------| -| [azurerm_resource_group.e2e_appcs](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/resource_group) | resource | -| [random_integer.appcs_instance](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/integer) | resource | -| [azurerm_resource_group.network](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/resource_group) | data source | -| [azurerm_subnet.pep](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/subnet) | data source | -| [azurerm_virtual_network.e2e](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/virtual_network) | data source | - -## Inputs - -No inputs. - -## Outputs - -| Name | Description | -|------|-------------| -| [name](#output\_name) | n/a | - diff --git a/infra/modules/azure_app_configuration/examples/network_access/REAMDE.md b/infra/modules/azure_app_configuration/examples/network_access/REAMDE.md deleted file mode 100644 index 4df5cd0c99..0000000000 --- a/infra/modules/azure_app_configuration/examples/network_access/REAMDE.md +++ /dev/null @@ -1,5 +0,0 @@ -# network_access - - - - diff --git a/infra/modules/azure_app_configuration/examples/network_access/data.tf b/infra/modules/azure_app_configuration/examples/network_access/data.tf deleted file mode 100644 index 208aa45d47..0000000000 --- a/infra/modules/azure_app_configuration/examples/network_access/data.tf +++ /dev/null @@ -1,20 +0,0 @@ -data "azurerm_virtual_network" "e2e" { - name = local.e2e_virtual_network.name - resource_group_name = local.e2e_virtual_network.resource_group_name -} - -data "azurerm_subnet" "pep" { - name = provider::pagopa-dx::resource_name(merge(local.naming_config, { - name = "pep", - resource_type = "subnet" - })) - virtual_network_name = data.azurerm_virtual_network.e2e.name - resource_group_name = data.azurerm_virtual_network.e2e.resource_group_name -} - -data "azurerm_resource_group" "network" { - name = provider::pagopa-dx::resource_name(merge(local.naming_config, { - name = "network" - resource_type = "resource_group" - })) -} diff --git a/infra/modules/azure_app_configuration/examples/network_access/fixtures.tf b/infra/modules/azure_app_configuration/examples/network_access/fixtures.tf deleted file mode 100644 index 0b8e731e33..0000000000 --- a/infra/modules/azure_app_configuration/examples/network_access/fixtures.tf +++ /dev/null @@ -1,10 +0,0 @@ -resource "azurerm_resource_group" "e2e_appcs" { - name = provider::pagopa-dx::resource_name(merge(local.naming_config, { - domain = "e2e" - name = "appcs", - resource_type = "resource_group" - })) - location = local.environment.location - - tags = local.tags -} diff --git a/infra/modules/azure_app_configuration/examples/network_access/locals.tf b/infra/modules/azure_app_configuration/examples/network_access/locals.tf deleted file mode 100644 index d7481adcaa..0000000000 --- a/infra/modules/azure_app_configuration/examples/network_access/locals.tf +++ /dev/null @@ -1,38 +0,0 @@ -locals { - tags = { - CostCenter = "TS000 - Tecnologia e Servizi" - CreatedBy = "Terraform" - Environment = "Dev" - BusinessUnit = "DevEx" - Source = "https://github.com/pagopa/dx/tests/azure_app_configuration" - ManagementTeam = "Developer Experience" - TestSuite = "e2e" - } - - environment = { - prefix = "dx" - env_short = "d" - location = "italynorth" - app_name = "e2e" - instance_number = "01" - } - - naming_config = { - prefix = local.environment.prefix, - environment = local.environment.env_short, - location = local.environment.location, - name = local.environment.app_name, - instance_number = tonumber(local.environment.instance_number), - } - - e2e_virtual_network = { - name = provider::pagopa-dx::resource_name(merge(local.naming_config, { - name = "e2e", - resource_type = "virtual_network" - })) - resource_group_name = provider::pagopa-dx::resource_name(merge(local.naming_config, { - name = "e2e", - resource_type = "resource_group" - })) - } -} diff --git a/infra/modules/azure_app_configuration/examples/network_access/mut.tf b/infra/modules/azure_app_configuration/examples/network_access/mut.tf deleted file mode 100644 index 8e26a436c8..0000000000 --- a/infra/modules/azure_app_configuration/examples/network_access/mut.tf +++ /dev/null @@ -1,24 +0,0 @@ -resource "random_integer" "appcs_instance" { - min = 1 - max = 99 -} - -module "private_appcs" { - source = "../../" - # version = ">= 0.3" - - # provider::dx::resource_name(merge(local.naming_config, { resource_type = "key_vault", domain = "int", instance_number = random_integer.kv_instance.result })) - environment = (merge(local.environment, { instance_number = random_integer.appcs_instance.result })) - resource_group_name = azurerm_resource_group.e2e_appcs.name - - subnet_pep_id = data.azurerm_subnet.pep.id - - virtual_network = { - name = local.e2e_virtual_network.name - resource_group_name = local.e2e_virtual_network.resource_group_name - } - - private_dns_zone_resource_group_name = data.azurerm_resource_group.network.name - - tags = local.tags -} diff --git a/infra/modules/azure_app_configuration/examples/network_access/outputs.tf b/infra/modules/azure_app_configuration/examples/network_access/outputs.tf deleted file mode 100644 index df43cc6eee..0000000000 --- a/infra/modules/azure_app_configuration/examples/network_access/outputs.tf +++ /dev/null @@ -1,3 +0,0 @@ -output "name" { - value = module.private_appcs.name -} diff --git a/infra/modules/azure_app_configuration/examples/network_access/providers.tf b/infra/modules/azure_app_configuration/examples/network_access/providers.tf deleted file mode 100644 index 75e33e5c13..0000000000 --- a/infra/modules/azure_app_configuration/examples/network_access/providers.tf +++ /dev/null @@ -1,33 +0,0 @@ -terraform { - required_version = ">= 1.13.0" - - required_providers { - azurerm = { - source = "hashicorp/azurerm" - version = "~> 4.0" - } - pagopa-dx = { - source = "pagopa-dx/azure" - version = "~> 0.8" - } - random = { - source = "hashicorp/random" - version = "~> 3.7" - } - } -} - -provider "azurerm" { - features { - resource_group { - prevent_deletion_if_contains_resources = false - } - app_configuration { - purge_soft_delete_on_destroy = true - recover_soft_deleted = true - } - } -} - -provider "random" { -} From 72a3aff7fde1aa7195605046c981c661fd4052fd Mon Sep 17 00:00:00 2001 From: Krusty93 Date: Mon, 24 Nov 2025 18:12:15 +0100 Subject: [PATCH 04/10] add examples --- .../examples/keyvault_integration/README.md | 43 +++++++++++++++++ .../examples/keyvault_integration/data.tf | 29 +++++++++++ .../examples/keyvault_integration/fixtures.tf | 48 +++++++++++++++++++ .../examples/keyvault_integration/locals.tf | 38 +++++++++++++++ .../examples/keyvault_integration/mut.tf | 30 ++++++++++++ .../examples/keyvault_integration/outputs.tf | 3 ++ .../keyvault_integration/providers.tf | 37 ++++++++++++++ .../examples/network_access/README.md | 38 +++++++++++++++ .../examples/network_access/data.tf | 20 ++++++++ .../examples/network_access/fixtures.tf | 10 ++++ .../examples/network_access/locals.tf | 38 +++++++++++++++ .../examples/network_access/mut.tf | 22 +++++++++ .../examples/network_access/outputs.tf | 3 ++ .../examples/network_access/providers.tf | 33 +++++++++++++ 14 files changed, 392 insertions(+) create mode 100644 infra/modules/azure_app_configuration/examples/keyvault_integration/README.md create mode 100644 infra/modules/azure_app_configuration/examples/keyvault_integration/data.tf create mode 100644 infra/modules/azure_app_configuration/examples/keyvault_integration/fixtures.tf create mode 100644 infra/modules/azure_app_configuration/examples/keyvault_integration/locals.tf create mode 100644 infra/modules/azure_app_configuration/examples/keyvault_integration/mut.tf create mode 100644 infra/modules/azure_app_configuration/examples/keyvault_integration/outputs.tf create mode 100644 infra/modules/azure_app_configuration/examples/keyvault_integration/providers.tf create mode 100644 infra/modules/azure_app_configuration/examples/network_access/README.md create mode 100644 infra/modules/azure_app_configuration/examples/network_access/data.tf create mode 100644 infra/modules/azure_app_configuration/examples/network_access/fixtures.tf create mode 100644 infra/modules/azure_app_configuration/examples/network_access/locals.tf create mode 100644 infra/modules/azure_app_configuration/examples/network_access/mut.tf create mode 100644 infra/modules/azure_app_configuration/examples/network_access/outputs.tf create mode 100644 infra/modules/azure_app_configuration/examples/network_access/providers.tf diff --git a/infra/modules/azure_app_configuration/examples/keyvault_integration/README.md b/infra/modules/azure_app_configuration/examples/keyvault_integration/README.md new file mode 100644 index 0000000000..63be0f3146 --- /dev/null +++ b/infra/modules/azure_app_configuration/examples/keyvault_integration/README.md @@ -0,0 +1,43 @@ +# keyvault_integration + + +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 1.13.0 | +| [azurerm](#requirement\_azurerm) | ~> 4.0 | +| [pagopa-dx](#requirement\_pagopa-dx) | ~> 0.8 | +| [random](#requirement\_random) | ~> 3.7 | + +## Modules + +| Name | Source | Version | +|------|--------|---------| +| [appcs\_with\_kv](#module\_appcs\_with\_kv) | pagopa-dx/azure-app-configuration/azurerm | ~> 0.0 | + +## Resources + +| Name | Type | +|------|------| +| [azurerm_key_vault.kv](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/key_vault) | resource | +| [azurerm_private_endpoint.kv](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/private_endpoint) | resource | +| [azurerm_resource_group.e2e_appcs](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/resource_group) | resource | +| [random_integer.appcs_instance](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/integer) | resource | +| [azurerm_client_config.current](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/client_config) | data source | +| [azurerm_private_dns_zone.kv](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/private_dns_zone) | data source | +| [azurerm_resource_group.network](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/resource_group) | data source | +| [azurerm_subnet.pep](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/subnet) | data source | +| [azurerm_subscription.current](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/subscription) | data source | +| [azurerm_virtual_network.e2e](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/virtual_network) | data source | + +## Inputs + +No inputs. + +## Outputs + +| Name | Description | +|------|-------------| +| [name](#output\_name) | n/a | + diff --git a/infra/modules/azure_app_configuration/examples/keyvault_integration/data.tf b/infra/modules/azure_app_configuration/examples/keyvault_integration/data.tf new file mode 100644 index 0000000000..a603649866 --- /dev/null +++ b/infra/modules/azure_app_configuration/examples/keyvault_integration/data.tf @@ -0,0 +1,29 @@ +data "azurerm_client_config" "current" {} + +data "azurerm_subscription" "current" {} + +data "azurerm_private_dns_zone" "kv" { + name = "privatelink.vaultcore.azure.net" + resource_group_name = local.e2e_virtual_network.resource_group_name +} + +data "azurerm_virtual_network" "e2e" { + name = local.e2e_virtual_network.name + resource_group_name = local.e2e_virtual_network.resource_group_name +} + +data "azurerm_subnet" "pep" { + name = provider::pagopa-dx::resource_name(merge(local.naming_config, { + name = "pep", + resource_type = "subnet" + })) + virtual_network_name = data.azurerm_virtual_network.e2e.name + resource_group_name = data.azurerm_virtual_network.e2e.resource_group_name +} + +data "azurerm_resource_group" "network" { + name = provider::pagopa-dx::resource_name(merge(local.naming_config, { + name = "network" + resource_type = "resource_group" + })) +} diff --git a/infra/modules/azure_app_configuration/examples/keyvault_integration/fixtures.tf b/infra/modules/azure_app_configuration/examples/keyvault_integration/fixtures.tf new file mode 100644 index 0000000000..48ce1ec4a2 --- /dev/null +++ b/infra/modules/azure_app_configuration/examples/keyvault_integration/fixtures.tf @@ -0,0 +1,48 @@ +resource "azurerm_resource_group" "e2e_appcs" { + name = provider::pagopa-dx::resource_name(merge(local.naming_config, { + domain = "e2e" + name = "appcs", + resource_type = "resource_group" + })) + location = local.environment.location + + tags = local.tags +} + +resource "azurerm_key_vault" "kv" { + name = provider::dx::resource_name(merge(local.naming_config, { resource_type = "key_vault", domain = "e2e", instance_number = random_integer.appcs_instance.result })) + location = azurerm_resource_group.e2e_appcs.location + resource_group_name = azurerm_resource_group.e2e_appcs.name + tenant_id = data.azurerm_client_config.current.tenant_id + sku_name = "standard" + rbac_authorization_enabled = true + purge_protection_enabled = true + soft_delete_retention_days = 7 + public_network_access_enabled = false + network_acls { + bypass = "AzureServices" + default_action = "Deny" + } + tags = local.tags +} + +resource "azurerm_private_endpoint" "kv" { + name = provider::dx::resource_name(merge(local.naming_config, { resource_type = "key_vault_private_endpoint", domain = "e2e", instance_number = random_integer.appcs_instance.result })) + location = azurerm_resource_group.e2e_appcs.location + resource_group_name = azurerm_resource_group.e2e_appcs.name + subnet_id = data.azurerm_subnet.pep.id + + private_service_connection { + name = provider::dx::resource_name(merge(local.naming_config, { resource_type = "key_vault_private_endpoint", domain = "e2e", instance_number = random_integer.appcs_instance.result })) + private_connection_resource_id = azurerm_key_vault.kv.id + is_manual_connection = false + subresource_names = ["vault"] + } + + private_dns_zone_group { + name = "private-dns-zone-group" + private_dns_zone_ids = [data.azurerm_private_dns_zone.kv.id] + } + + tags = local.tags +} diff --git a/infra/modules/azure_app_configuration/examples/keyvault_integration/locals.tf b/infra/modules/azure_app_configuration/examples/keyvault_integration/locals.tf new file mode 100644 index 0000000000..d7481adcaa --- /dev/null +++ b/infra/modules/azure_app_configuration/examples/keyvault_integration/locals.tf @@ -0,0 +1,38 @@ +locals { + tags = { + CostCenter = "TS000 - Tecnologia e Servizi" + CreatedBy = "Terraform" + Environment = "Dev" + BusinessUnit = "DevEx" + Source = "https://github.com/pagopa/dx/tests/azure_app_configuration" + ManagementTeam = "Developer Experience" + TestSuite = "e2e" + } + + environment = { + prefix = "dx" + env_short = "d" + location = "italynorth" + app_name = "e2e" + instance_number = "01" + } + + naming_config = { + prefix = local.environment.prefix, + environment = local.environment.env_short, + location = local.environment.location, + name = local.environment.app_name, + instance_number = tonumber(local.environment.instance_number), + } + + e2e_virtual_network = { + name = provider::pagopa-dx::resource_name(merge(local.naming_config, { + name = "e2e", + resource_type = "virtual_network" + })) + resource_group_name = provider::pagopa-dx::resource_name(merge(local.naming_config, { + name = "e2e", + resource_type = "resource_group" + })) + } +} diff --git a/infra/modules/azure_app_configuration/examples/keyvault_integration/mut.tf b/infra/modules/azure_app_configuration/examples/keyvault_integration/mut.tf new file mode 100644 index 0000000000..e783f0ff3e --- /dev/null +++ b/infra/modules/azure_app_configuration/examples/keyvault_integration/mut.tf @@ -0,0 +1,30 @@ +resource "random_integer" "appcs_instance" { + min = 1 + max = 99 +} + +module "appcs_with_kv" { + source = "pagopa-dx/azure-app-configuration/azurerm" + version = "~> 0.0" + + environment = (merge(local.environment, { instance_number = random_integer.appcs_instance.result })) + resource_group_name = azurerm_resource_group.e2e_appcs.name + + subnet_pep_id = data.azurerm_subnet.pep.id + + virtual_network = { + name = local.e2e_virtual_network.name + resource_group_name = local.e2e_virtual_network.resource_group_name + } + + private_dns_zone_resource_group_name = data.azurerm_resource_group.network.name + + key_vault = { + has_rbac_support = true + name = azurerm_key_vault.kv.name + resource_group_name = azurerm_key_vault.kv.resource_group_name + subscription_id = data.azurerm_subscription.current.subscription_id + } + + tags = local.tags +} diff --git a/infra/modules/azure_app_configuration/examples/keyvault_integration/outputs.tf b/infra/modules/azure_app_configuration/examples/keyvault_integration/outputs.tf new file mode 100644 index 0000000000..b1fca7ad28 --- /dev/null +++ b/infra/modules/azure_app_configuration/examples/keyvault_integration/outputs.tf @@ -0,0 +1,3 @@ +output "name" { + value = module.appcs_with_kv.name +} diff --git a/infra/modules/azure_app_configuration/examples/keyvault_integration/providers.tf b/infra/modules/azure_app_configuration/examples/keyvault_integration/providers.tf new file mode 100644 index 0000000000..2afef9ed75 --- /dev/null +++ b/infra/modules/azure_app_configuration/examples/keyvault_integration/providers.tf @@ -0,0 +1,37 @@ +terraform { + required_version = ">= 1.13.0" + + required_providers { + azurerm = { + source = "hashicorp/azurerm" + version = "~> 4.0" + } + pagopa-dx = { + source = "pagopa-dx/azure" + version = "~> 0.8" + } + random = { + source = "hashicorp/random" + version = "~> 3.7" + } + } +} + +provider "azurerm" { + features { + resource_group { + prevent_deletion_if_contains_resources = false + } + key_vault { + purge_soft_delete_on_destroy = true + recover_soft_deleted_key_vaults = false + } + app_configuration { + purge_soft_delete_on_destroy = true + recover_soft_deleted = true + } + } +} + +provider "random" { +} diff --git a/infra/modules/azure_app_configuration/examples/network_access/README.md b/infra/modules/azure_app_configuration/examples/network_access/README.md new file mode 100644 index 0000000000..1f96294e44 --- /dev/null +++ b/infra/modules/azure_app_configuration/examples/network_access/README.md @@ -0,0 +1,38 @@ +# network_access + + +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 1.13.0 | +| [azurerm](#requirement\_azurerm) | ~> 4.0 | +| [pagopa-dx](#requirement\_pagopa-dx) | ~> 0.8 | +| [random](#requirement\_random) | ~> 3.7 | + +## Modules + +| Name | Source | Version | +|------|--------|---------| +| [private\_appcs](#module\_private\_appcs) | pagopa-dx/azure-app-configuration/azurerm | ~> 0.0 | + +## Resources + +| Name | Type | +|------|------| +| [azurerm_resource_group.e2e_appcs](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/resource_group) | resource | +| [random_integer.appcs_instance](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/integer) | resource | +| [azurerm_resource_group.network](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/resource_group) | data source | +| [azurerm_subnet.pep](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/subnet) | data source | +| [azurerm_virtual_network.e2e](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/virtual_network) | data source | + +## Inputs + +No inputs. + +## Outputs + +| Name | Description | +|------|-------------| +| [name](#output\_name) | n/a | + diff --git a/infra/modules/azure_app_configuration/examples/network_access/data.tf b/infra/modules/azure_app_configuration/examples/network_access/data.tf new file mode 100644 index 0000000000..208aa45d47 --- /dev/null +++ b/infra/modules/azure_app_configuration/examples/network_access/data.tf @@ -0,0 +1,20 @@ +data "azurerm_virtual_network" "e2e" { + name = local.e2e_virtual_network.name + resource_group_name = local.e2e_virtual_network.resource_group_name +} + +data "azurerm_subnet" "pep" { + name = provider::pagopa-dx::resource_name(merge(local.naming_config, { + name = "pep", + resource_type = "subnet" + })) + virtual_network_name = data.azurerm_virtual_network.e2e.name + resource_group_name = data.azurerm_virtual_network.e2e.resource_group_name +} + +data "azurerm_resource_group" "network" { + name = provider::pagopa-dx::resource_name(merge(local.naming_config, { + name = "network" + resource_type = "resource_group" + })) +} diff --git a/infra/modules/azure_app_configuration/examples/network_access/fixtures.tf b/infra/modules/azure_app_configuration/examples/network_access/fixtures.tf new file mode 100644 index 0000000000..0b8e731e33 --- /dev/null +++ b/infra/modules/azure_app_configuration/examples/network_access/fixtures.tf @@ -0,0 +1,10 @@ +resource "azurerm_resource_group" "e2e_appcs" { + name = provider::pagopa-dx::resource_name(merge(local.naming_config, { + domain = "e2e" + name = "appcs", + resource_type = "resource_group" + })) + location = local.environment.location + + tags = local.tags +} diff --git a/infra/modules/azure_app_configuration/examples/network_access/locals.tf b/infra/modules/azure_app_configuration/examples/network_access/locals.tf new file mode 100644 index 0000000000..d7481adcaa --- /dev/null +++ b/infra/modules/azure_app_configuration/examples/network_access/locals.tf @@ -0,0 +1,38 @@ +locals { + tags = { + CostCenter = "TS000 - Tecnologia e Servizi" + CreatedBy = "Terraform" + Environment = "Dev" + BusinessUnit = "DevEx" + Source = "https://github.com/pagopa/dx/tests/azure_app_configuration" + ManagementTeam = "Developer Experience" + TestSuite = "e2e" + } + + environment = { + prefix = "dx" + env_short = "d" + location = "italynorth" + app_name = "e2e" + instance_number = "01" + } + + naming_config = { + prefix = local.environment.prefix, + environment = local.environment.env_short, + location = local.environment.location, + name = local.environment.app_name, + instance_number = tonumber(local.environment.instance_number), + } + + e2e_virtual_network = { + name = provider::pagopa-dx::resource_name(merge(local.naming_config, { + name = "e2e", + resource_type = "virtual_network" + })) + resource_group_name = provider::pagopa-dx::resource_name(merge(local.naming_config, { + name = "e2e", + resource_type = "resource_group" + })) + } +} diff --git a/infra/modules/azure_app_configuration/examples/network_access/mut.tf b/infra/modules/azure_app_configuration/examples/network_access/mut.tf new file mode 100644 index 0000000000..791b002aa2 --- /dev/null +++ b/infra/modules/azure_app_configuration/examples/network_access/mut.tf @@ -0,0 +1,22 @@ +resource "random_integer" "appcs_instance" { + min = 1 + max = 99 +} + +module "private_appcs" { + source = "pagopa-dx/azure-app-configuration/azurerm" + version = "~> 0.0" + + environment = (merge(local.environment, { instance_number = random_integer.appcs_instance.result })) + resource_group_name = azurerm_resource_group.e2e_appcs.name + + subnet_pep_id = data.azurerm_subnet.pep.id + + virtual_network = { + name = local.e2e_virtual_network.name + resource_group_name = local.e2e_virtual_network.resource_group_name + } + + private_dns_zone_resource_group_name = data.azurerm_resource_group.network.name + tags = local.tags +} diff --git a/infra/modules/azure_app_configuration/examples/network_access/outputs.tf b/infra/modules/azure_app_configuration/examples/network_access/outputs.tf new file mode 100644 index 0000000000..df43cc6eee --- /dev/null +++ b/infra/modules/azure_app_configuration/examples/network_access/outputs.tf @@ -0,0 +1,3 @@ +output "name" { + value = module.private_appcs.name +} diff --git a/infra/modules/azure_app_configuration/examples/network_access/providers.tf b/infra/modules/azure_app_configuration/examples/network_access/providers.tf new file mode 100644 index 0000000000..75e33e5c13 --- /dev/null +++ b/infra/modules/azure_app_configuration/examples/network_access/providers.tf @@ -0,0 +1,33 @@ +terraform { + required_version = ">= 1.13.0" + + required_providers { + azurerm = { + source = "hashicorp/azurerm" + version = "~> 4.0" + } + pagopa-dx = { + source = "pagopa-dx/azure" + version = "~> 0.8" + } + random = { + source = "hashicorp/random" + version = "~> 3.7" + } + } +} + +provider "azurerm" { + features { + resource_group { + prevent_deletion_if_contains_resources = false + } + app_configuration { + purge_soft_delete_on_destroy = true + recover_soft_deleted = true + } + } +} + +provider "random" { +} From 992e0d307262217b6dc09fcc0c48038df7bdf7f2 Mon Sep 17 00:00:00 2001 From: Krusty93 Date: Tue, 25 Nov 2025 16:37:49 +0100 Subject: [PATCH 05/10] add test app --- .github/workflows/_release-docker-e2e.yaml | 44 ++++++ go.work | 3 +- go.work.sum | 6 +- .../tests/apps/all_scenarios/Dockerfile | 16 +++ .../tests/apps/all_scenarios/README.md | 1 + .../tests/apps/all_scenarios/project.json | 19 +++ .../tests/apps/all_scenarios/src/go.mod | 16 +++ .../tests/apps/all_scenarios/src/go.sum | 20 +++ .../tests/apps/all_scenarios/src/main.go | 131 ++++++++++++++++++ 9 files changed, 251 insertions(+), 5 deletions(-) create mode 100644 .github/workflows/_release-docker-e2e.yaml create mode 100644 infra/modules/azure_app_configuration/tests/apps/all_scenarios/Dockerfile create mode 100644 infra/modules/azure_app_configuration/tests/apps/all_scenarios/README.md create mode 100644 infra/modules/azure_app_configuration/tests/apps/all_scenarios/project.json create mode 100644 infra/modules/azure_app_configuration/tests/apps/all_scenarios/src/go.mod create mode 100644 infra/modules/azure_app_configuration/tests/apps/all_scenarios/src/go.sum create mode 100644 infra/modules/azure_app_configuration/tests/apps/all_scenarios/src/main.go diff --git a/.github/workflows/_release-docker-e2e.yaml b/.github/workflows/_release-docker-e2e.yaml new file mode 100644 index 0000000000..6addacfc2e --- /dev/null +++ b/.github/workflows/_release-docker-e2e.yaml @@ -0,0 +1,44 @@ +# Build and publish the application Docker image for the E2E App Configuration - including all scenarios. + +name: Publish E2E App Configuration - All Scenarios +on: + workflow_dispatch: + push: + branches: + - main + paths: + - "infra/modules/azure_app_configuration/tests/apps/all_scenarios/**" + +env: + MODULE_NAME: "azure_app_configuration" + +jobs: + publish: + name: Build and Push Docker Image + runs-on: ubuntu-latest + permissions: + contents: read + id-token: write + attestations: write + packages: write + env: + IMAGE_NAME: "pagopa/e2e-appconfiguration-network-access" + IMAGE_TAG: "latest" + + steps: + - name: Checkout + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + + - name: Docker Build and Push + id: docker_build + uses: pagopa/dx/actions/docker-build-push@main + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + dockerfile_path: infra/modules/${{ env.MODULE_NAME }}/tests/apps/all_scenarios/Dockerfile + dockerfile_context: infra/modules/${{ env.MODULE_NAME }}/tests/apps/all_scenarios/src + docker_image_name: ${{ env.IMAGE_NAME }} + docker_image_description: "Web app which exposes endpoints to access App Configuration. Used for E2E tests of the Azure App Configuration Terraform module." + docker_image_authors: "PagoPA" + build_platforms: "linux/amd64,linux/arm64" + push_to_registry: true diff --git a/go.work b/go.work index b088f0fb64..9c23ba6889 100644 --- a/go.work +++ b/go.work @@ -1,6 +1,7 @@ -go 1.25.3 +go 1.25.4 use ( + ./infra/modules/azure_app_configuration/tests/apps/all_scenarios/src ./infra/modules/azure_cosmos_account/tests ./providers/aws ./providers/aws/tools diff --git a/go.work.sum b/go.work.sum index 092fbab918..26d74264a5 100644 --- a/go.work.sum +++ b/go.work.sum @@ -18,12 +18,11 @@ github.com/Azure/azure-sdk-for-go v64.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9mo github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.1/go.mod h1:Ot/6aikWnKWi4l9QB7qVSwa8iMphQNqkWALMoNT3rzM= github.com/Azure/azure-sdk-for-go/sdk/azcore v1.19.1 h1:5YTBM8QDVIBN3sxBil89WfdAAqDZbyJTgh688DSxX5w= github.com/Azure/azure-sdk-for-go/sdk/azcore v1.19.1/go.mod h1:YD5h/ldMsG0XiIw7PdyNhLxaM317eFh5yNLccNfGdyw= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.10.1 h1:B+blDbyVIG3WaikNxPnhPiJ1MThR03b3vKGtER95TP4= github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.10.1/go.mod h1:JdM5psgjfBf5fo2uWOZhflPWyDBZ/O/CNAH9CtsuZE4= github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.13.0 h1:KpMC6LFL7mqpExyMC9jVOYRiVhLmamjeZfRsUpB7l4s= github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.13.0/go.mod h1:J7MUC/wtRpfGVbQ5sIItY5/FuVWmvzlY21WAOfQnq/I= github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.0/go.mod h1:j2chePtV91HrC22tGoRX3sGY42uF13WzmmV80/OdVAA= -github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.2 h1:9iefClla7iYpfYWdzPCRDozdmndjTm8DXdpCzPajMgA= -github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.2/go.mod h1:XtLgD3ZD34DAaVIIAyG3objl5DynM3CQ/vMcbBNJZGI= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/appcontainers/armappcontainers/v3 v3.0.0 h1:NYYoOOPGOqUXw/bGIVd6OY/K8J23a18IAlAx1tOHWNo= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/appcontainers/armappcontainers/v3 v3.0.0/go.mod h1:LDN3sr8FJ36sY6ZmMes6Q2vHJ+5r1aFsE3wEo7VbXJg= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.2.0 h1:Dd+RhdJn0OTtVGaeDLZpcumkIVCtA/3/Fo42+eoYvVM= @@ -172,6 +171,7 @@ github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10/go.mod h1 github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= github.com/redis/go-redis/v9 v9.8.0/go.mod h1:huWgSWd8mW6+m0VPhJjSSQ+d6Nh1VICQ6Q5lHuCH/Iw= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= +github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/sebdah/goldie v1.0.0 h1:9GNhIat69MSlz/ndaBg48vl9dF5fI+NBB6kfOxgfkMc= @@ -233,7 +233,6 @@ golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk= golang.org/x/net v0.36.0/go.mod h1:bFmbeoIPfrw4sMHNhb4J9f6+tPziuGjq7Jk/38fxi1I= golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E= -golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8= golang.org/x/net v0.44.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY= golang.org/x/net v0.45.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY= golang.org/x/net v0.46.0 h1:giFlY12I07fugqwPuWJi68oOnpfqFnJIJzaIIm2JVV4= @@ -282,7 +281,6 @@ golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU= golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA= -golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU= golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k= golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= diff --git a/infra/modules/azure_app_configuration/tests/apps/all_scenarios/Dockerfile b/infra/modules/azure_app_configuration/tests/apps/all_scenarios/Dockerfile new file mode 100644 index 0000000000..2985c423cd --- /dev/null +++ b/infra/modules/azure_app_configuration/tests/apps/all_scenarios/Dockerfile @@ -0,0 +1,16 @@ +# Dockerfile +FROM public.ecr.aws/docker/library/golang:tip-alpine3.22 AS build + +WORKDIR /src +COPY go.mod . +RUN go mod download +COPY . . +RUN CGO_ENABLED=0 go build -o app main.go + +# trivy:ignore:AVD-DS-0002 +# trivy:ignore:AVD-DS-0026 +FROM gcr.io/distroless/base-debian12:nonroot + +EXPOSE 8080 +ENTRYPOINT ["/app"] +COPY --from=build /src/app /app diff --git a/infra/modules/azure_app_configuration/tests/apps/all_scenarios/README.md b/infra/modules/azure_app_configuration/tests/apps/all_scenarios/README.md new file mode 100644 index 0000000000..16d4141ace --- /dev/null +++ b/infra/modules/azure_app_configuration/tests/apps/all_scenarios/README.md @@ -0,0 +1 @@ +# All Scenarios diff --git a/infra/modules/azure_app_configuration/tests/apps/all_scenarios/project.json b/infra/modules/azure_app_configuration/tests/apps/all_scenarios/project.json new file mode 100644 index 0000000000..a4a99d2208 --- /dev/null +++ b/infra/modules/azure_app_configuration/tests/apps/all_scenarios/project.json @@ -0,0 +1,19 @@ +{ + "$schema": "../../../../../../node_modules/nx/schemas/project-schema.json", + "name": "app_configuration_tests_all_scenarios", + "version": "0.0.0", + "description": "Simple application for Terraform E2E tests, which exposes endpoints to test connectivity and integration with App Configuration", + "private": true, + "targets": { + "docker:build": { + "options": { + "platform": "linux/amd64,linux/arm64" + } + }, + "docker:run": { + "options": { + "p": "8080:8080" + } + } + } +} diff --git a/infra/modules/azure_app_configuration/tests/apps/all_scenarios/src/go.mod b/infra/modules/azure_app_configuration/tests/apps/all_scenarios/src/go.mod new file mode 100644 index 0000000000..9e55088878 --- /dev/null +++ b/infra/modules/azure_app_configuration/tests/apps/all_scenarios/src/go.mod @@ -0,0 +1,16 @@ +module github.com/pagopa/dx/modules/azurerm_azure_app_configuration/tests/apps/all_scenarios + +go 1.25.4 + +require ( + github.com/Azure/AppConfiguration-GoProvider/azureappconfiguration v1.3.0 // indirect + github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.2 // indirect + github.com/Azure/azure-sdk-for-go/sdk/data/azappconfig v1.2.0 // indirect + github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.2 // indirect + github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azsecrets v1.4.0 // indirect + github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.2.0 // indirect + github.com/go-viper/mapstructure/v2 v2.4.0 // indirect + golang.org/x/net v0.42.0 // indirect + golang.org/x/sync v0.16.0 // indirect + golang.org/x/text v0.27.0 // indirect +) diff --git a/infra/modules/azure_app_configuration/tests/apps/all_scenarios/src/go.sum b/infra/modules/azure_app_configuration/tests/apps/all_scenarios/src/go.sum new file mode 100644 index 0000000000..001fe04ae9 --- /dev/null +++ b/infra/modules/azure_app_configuration/tests/apps/all_scenarios/src/go.sum @@ -0,0 +1,20 @@ +github.com/Azure/AppConfiguration-GoProvider/azureappconfiguration v1.3.0 h1:LpR4+JABMeDLrCJZUlS2QRJ1OiQRkSFnMiJ+HOPgE8U= +github.com/Azure/AppConfiguration-GoProvider/azureappconfiguration v1.3.0/go.mod h1:JZjuVES/kbo6vp6wC0W5Mk72obx6BM54JCBa+oZY4mk= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.2 h1:Hr5FTipp7SL07o2FvoVOX9HRiRH3CR3Mj8pxqCcdD5A= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.2/go.mod h1:QyVsSSN64v5TGltphKLQ2sQxe4OBQg0J1eKRcVBnfgE= +github.com/Azure/azure-sdk-for-go/sdk/data/azappconfig v1.2.0 h1:uU4FujKFQAz31AbWOO3INV9qfIanHeIUSsGhRlcJJmg= +github.com/Azure/azure-sdk-for-go/sdk/data/azappconfig v1.2.0/go.mod h1:qr3M3Oy6V98VR0c5tCHKUpaeJTRQh6KYzJewRtFWqfc= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.2 h1:9iefClla7iYpfYWdzPCRDozdmndjTm8DXdpCzPajMgA= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.2/go.mod h1:XtLgD3ZD34DAaVIIAyG3objl5DynM3CQ/vMcbBNJZGI= +github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azsecrets v1.4.0 h1:/g8S6wk65vfC6m3FIxJ+i5QDyN9JWwXI8Hb0Img10hU= +github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azsecrets v1.4.0/go.mod h1:gpl+q95AzZlKVI3xSoseF9QPrypk0hQqBiJYeB/cR/I= +github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.2.0 h1:nCYfgcSyHZXJI8J0IWE5MsCGlb2xp9fJiXyxWgmOFg4= +github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.2.0/go.mod h1:ucUjca2JtSZboY8IoUqyQyuuXvwbMBVwFOm0vdQPNhA= +github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs= +github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= +golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs= +golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8= +golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw= +golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4= +golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU= diff --git a/infra/modules/azure_app_configuration/tests/apps/all_scenarios/src/main.go b/infra/modules/azure_app_configuration/tests/apps/all_scenarios/src/main.go new file mode 100644 index 0000000000..763bd345c8 --- /dev/null +++ b/infra/modules/azure_app_configuration/tests/apps/all_scenarios/src/main.go @@ -0,0 +1,131 @@ +package main + +import ( + "context" + "fmt" + "log" + "net" + "net/http" + "time" + + "github.com/Azure/AppConfiguration-GoProvider/azureappconfiguration" + "github.com/Azure/azure-sdk-for-go/sdk/azidentity" +) + +type Config struct { + TestKey string `json:"test-key"` +} + +type Secret struct { + SecretKey string `json:"secret-key"` +} + +func main() { + mux := http.NewServeMux() + mux.HandleFunc("/setting", settingHandler) + mux.HandleFunc("/secret", secretHandler) + mux.HandleFunc("/reachability", reachabilityHandler) + + addr := ":8080" + log.Printf("listening on %s", addr) + if err := http.ListenAndServe(addr, mux); err != nil { + log.Printf("listen error: %s", err) + } +} + +func reachabilityHandler(w http.ResponseWriter, r *http.Request) { + hostname := getHostnameFromQueryString(r) + + _, err := net.LookupIP(hostname) + if err != nil { + log.Printf("Failed to resolve endpoint \"%s\"", hostname) + w.WriteHeader(http.StatusBadGateway) + return + } + + w.WriteHeader(http.StatusNoContent) +} + +func settingHandler(w http.ResponseWriter, r *http.Request) { + hostname := getHostnameFromQueryString(r) + + ctx, cancel := context.WithTimeout(r.Context(), 10*time.Second) + defer cancel() + + provider, err := loadAzureAppConfiguration(ctx, hostname, false) + if err != nil { + log.Printf("Failed to load Azure App Configuration: %v", err) + w.WriteHeader(http.StatusBadGateway) + return + } + + var config Config + if err := provider.Unmarshal(&config, nil); err != nil { + log.Printf("Failed to unmarshal configuration: %v", err) + } + + w.WriteHeader(http.StatusOK) + fmt.Fprintf(w, `{"key":"%s"}`, config.TestKey) +} + +func secretHandler(w http.ResponseWriter, r *http.Request) { + hostname := getHostnameFromQueryString(r) + + ctx, cancel := context.WithTimeout(r.Context(), 10*time.Second) + defer cancel() + + provider, err := loadAzureAppConfiguration(ctx, hostname, true) + if err != nil { + log.Printf("Failed to load Azure App Configuration: %v", err) + w.WriteHeader(http.StatusBadGateway) + return + } + + var secret Secret + if err := provider.Unmarshal(&secret, nil); err != nil { + log.Printf("Failed to unmarshal configuration: %v", err) + } + + w.WriteHeader(http.StatusOK) + fmt.Fprintf(w, `{"secret-key":"%s"}`, secret.SecretKey) +} + +func getHostnameFromQueryString(r *http.Request) string { + q := r.URL.Query() + instanceName := q.Get("instanceName") + return fmt.Sprintf("%s.azconfig.io", instanceName) +} + +func loadAzureAppConfiguration(ctx context.Context, hostname string, enableSecret bool) (*azureappconfiguration.AzureAppConfiguration, error) { + credential, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Printf("Failed to create credential: %v", err) + } + + authOptions := azureappconfiguration.AuthenticationOptions{ + Endpoint: fmt.Sprintf("https://%s", hostname), + Credential: credential, + } + + keyFilter := "Setting" + if enableSecret { + keyFilter = "Secret" + } + + options := &azureappconfiguration.Options{ + Selectors: []azureappconfiguration.Selector{ + { + KeyFilter: fmt.Sprintf("%s:*", keyFilter), + }, + }, + TrimKeyPrefixes: []string{fmt.Sprintf("%s:", keyFilter)}, + } + + if enableSecret { + options.KeyVaultOptions = azureappconfiguration.KeyVaultOptions{ + Credential: credential, + } + } + + return azureappconfiguration.Load(ctx, authOptions, options) +} From 5424c9e19b4e3ad9faae84ad9c3078d3ca9c688e Mon Sep 17 00:00:00 2001 From: Krusty93 Date: Wed, 26 Nov 2025 10:26:32 +0100 Subject: [PATCH 06/10] add test app --- .dockerignore | 34 ++++++++++++++++ ..._release-docker-e2e-appconfiguration.yaml} | 3 +- go.work | 1 + .../tests/apps/all_scenarios/src/go.mod | 13 ++++++- .../tests/apps/all_scenarios/src/go.sum | 39 +++++++++++++++++++ .../tests/apps/all_scenarios/src/main.go | 15 ------- 6 files changed, 88 insertions(+), 17 deletions(-) create mode 100644 .dockerignore rename .github/workflows/{_release-docker-e2e.yaml => _release-docker-e2e-appconfiguration.yaml} (91%) diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000000..a424c32c6f --- /dev/null +++ b/.dockerignore @@ -0,0 +1,34 @@ +# git +.git +.gitignore + +# node +node_modules +.env +dist +.pnpm-store +vite.config.*.timestamp* +vitest.config.*.timestamp* + +# Go +terraform-provider-azure +providers/azure/terraform-provider-azure + +# Terraform +**/.terraform/* +*.tfstate +*.tfstate.* +override.tf +override.tf.json +*_override.tf +*_override.tf.json +**/modules/**/.terraform.lock.hcl +**/_modules/**/.terraform.lock.hcl + +# MacOS +*.DS_Store + +# NX +.nx/cache +.nx/workspace-data +.github/instructions/nx.instructions.md diff --git a/.github/workflows/_release-docker-e2e.yaml b/.github/workflows/_release-docker-e2e-appconfiguration.yaml similarity index 91% rename from .github/workflows/_release-docker-e2e.yaml rename to .github/workflows/_release-docker-e2e-appconfiguration.yaml index 6addacfc2e..6fa2376ace 100644 --- a/.github/workflows/_release-docker-e2e.yaml +++ b/.github/workflows/_release-docker-e2e-appconfiguration.yaml @@ -6,6 +6,7 @@ on: push: branches: - main + - CES-1469-aggiungere-esempi-del-modulo-da-usare-per-i-test-e-2-e paths: - "infra/modules/azure_app_configuration/tests/apps/all_scenarios/**" @@ -22,7 +23,7 @@ jobs: attestations: write packages: write env: - IMAGE_NAME: "pagopa/e2e-appconfiguration-network-access" + IMAGE_NAME: "pagopa/e2e-appconfiguration-all-scenarios" IMAGE_TAG: "latest" steps: diff --git a/go.work b/go.work index 9c23ba6889..2e1edcb470 100644 --- a/go.work +++ b/go.work @@ -1,6 +1,7 @@ go 1.25.4 use ( + ./infra/modules/azure_app_configuration/tests ./infra/modules/azure_app_configuration/tests/apps/all_scenarios/src ./infra/modules/azure_cosmos_account/tests ./providers/aws diff --git a/infra/modules/azure_app_configuration/tests/apps/all_scenarios/src/go.mod b/infra/modules/azure_app_configuration/tests/apps/all_scenarios/src/go.mod index 9e55088878..a836ac875e 100644 --- a/infra/modules/azure_app_configuration/tests/apps/all_scenarios/src/go.mod +++ b/infra/modules/azure_app_configuration/tests/apps/all_scenarios/src/go.mod @@ -3,14 +3,25 @@ module github.com/pagopa/dx/modules/azurerm_azure_app_configuration/tests/apps/a go 1.25.4 require ( - github.com/Azure/AppConfiguration-GoProvider/azureappconfiguration v1.3.0 // indirect + github.com/Azure/AppConfiguration-GoProvider/azureappconfiguration v1.3.0 + github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.10.1 +) + +require ( github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.2 // indirect github.com/Azure/azure-sdk-for-go/sdk/data/azappconfig v1.2.0 // indirect github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.2 // indirect github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azsecrets v1.4.0 // indirect github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.2.0 // indirect + github.com/AzureAD/microsoft-authentication-library-for-go v1.4.2 // indirect github.com/go-viper/mapstructure/v2 v2.4.0 // indirect + github.com/golang-jwt/jwt/v5 v5.2.2 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/kylelemons/godebug v1.1.0 // indirect + github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect + golang.org/x/crypto v0.40.0 // indirect golang.org/x/net v0.42.0 // indirect golang.org/x/sync v0.16.0 // indirect + golang.org/x/sys v0.34.0 // indirect golang.org/x/text v0.27.0 // indirect ) diff --git a/infra/modules/azure_app_configuration/tests/apps/all_scenarios/src/go.sum b/infra/modules/azure_app_configuration/tests/apps/all_scenarios/src/go.sum index 001fe04ae9..8dfa6298d0 100644 --- a/infra/modules/azure_app_configuration/tests/apps/all_scenarios/src/go.sum +++ b/infra/modules/azure_app_configuration/tests/apps/all_scenarios/src/go.sum @@ -2,6 +2,10 @@ github.com/Azure/AppConfiguration-GoProvider/azureappconfiguration v1.3.0 h1:LpR github.com/Azure/AppConfiguration-GoProvider/azureappconfiguration v1.3.0/go.mod h1:JZjuVES/kbo6vp6wC0W5Mk72obx6BM54JCBa+oZY4mk= github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.2 h1:Hr5FTipp7SL07o2FvoVOX9HRiRH3CR3Mj8pxqCcdD5A= github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.2/go.mod h1:QyVsSSN64v5TGltphKLQ2sQxe4OBQg0J1eKRcVBnfgE= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.10.1 h1:B+blDbyVIG3WaikNxPnhPiJ1MThR03b3vKGtER95TP4= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.10.1/go.mod h1:JdM5psgjfBf5fo2uWOZhflPWyDBZ/O/CNAH9CtsuZE4= +github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.2 h1:yz1bePFlP5Vws5+8ez6T3HWXPmwOK7Yvq8QxDBD3SKY= +github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.2/go.mod h1:Pa9ZNPuoNu/GztvBSKk9J1cDJW6vk/n0zLtV4mgd8N8= github.com/Azure/azure-sdk-for-go/sdk/data/azappconfig v1.2.0 h1:uU4FujKFQAz31AbWOO3INV9qfIanHeIUSsGhRlcJJmg= github.com/Azure/azure-sdk-for-go/sdk/data/azappconfig v1.2.0/go.mod h1:qr3M3Oy6V98VR0c5tCHKUpaeJTRQh6KYzJewRtFWqfc= github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.2 h1:9iefClla7iYpfYWdzPCRDozdmndjTm8DXdpCzPajMgA= @@ -10,11 +14,46 @@ github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azsecrets v1.4.0 h1:/g8S github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azsecrets v1.4.0/go.mod h1:gpl+q95AzZlKVI3xSoseF9QPrypk0hQqBiJYeB/cR/I= github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.2.0 h1:nCYfgcSyHZXJI8J0IWE5MsCGlb2xp9fJiXyxWgmOFg4= github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.2.0/go.mod h1:ucUjca2JtSZboY8IoUqyQyuuXvwbMBVwFOm0vdQPNhA= +github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1 h1:WJTmL004Abzc5wDB5VtZG2PJk5ndYDgVacGqfirKxjM= +github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1/go.mod h1:tCcJZ0uHAmvjsVYzEFivsRTN00oz5BEsRgQHu5JZ9WE= +github.com/AzureAD/microsoft-authentication-library-for-go v1.4.2 h1:oygO0locgZJe7PpYPXT5A29ZkwJaPqcva7BVeemZOZs= +github.com/AzureAD/microsoft-authentication-library-for-go v1.4.2/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs= github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= +github.com/golang-jwt/jwt/v5 v5.2.2 h1:Rl4B7itRWVtYIHFrSNd7vhTiz9UpLdi6gZhZ3wEeDy8= +github.com/golang-jwt/jwt/v5 v5.2.2/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/keybase/go-keychain v0.0.1 h1:way+bWYa6lDppZoZcgMbYsvC7GxljxrskdNInRtuthU= +github.com/keybase/go-keychain v0.0.1/go.mod h1:PdEILRW3i9D8JcdM+FmY6RwkHGnhHxXwkPPMeUgOK1k= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ= +github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/redis/go-redis/v9 v9.8.0 h1:q3nRvjrlge/6UD7eTu/DSg2uYiU2mCL0G/uzBWqhicI= +github.com/redis/go-redis/v9 v9.8.0/go.mod h1:huWgSWd8mW6+m0VPhJjSSQ+d6Nh1VICQ6Q5lHuCH/Iw= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +golang.org/x/crypto v0.40.0 h1:r4x+VvoG5Fm+eJcxMaY8CQM7Lb0l1lsmjGBQ6s8BfKM= +golang.org/x/crypto v0.40.0/go.mod h1:Qr1vMER5WyS2dfPHAlsOj01wgLbsyWtFn/aY+5+ZdxY= golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs= golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8= golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw= golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA= +golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4= golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/infra/modules/azure_app_configuration/tests/apps/all_scenarios/src/main.go b/infra/modules/azure_app_configuration/tests/apps/all_scenarios/src/main.go index 763bd345c8..378d267cd2 100644 --- a/infra/modules/azure_app_configuration/tests/apps/all_scenarios/src/main.go +++ b/infra/modules/azure_app_configuration/tests/apps/all_scenarios/src/main.go @@ -4,7 +4,6 @@ import ( "context" "fmt" "log" - "net" "net/http" "time" @@ -24,7 +23,6 @@ func main() { mux := http.NewServeMux() mux.HandleFunc("/setting", settingHandler) mux.HandleFunc("/secret", secretHandler) - mux.HandleFunc("/reachability", reachabilityHandler) addr := ":8080" log.Printf("listening on %s", addr) @@ -33,19 +31,6 @@ func main() { } } -func reachabilityHandler(w http.ResponseWriter, r *http.Request) { - hostname := getHostnameFromQueryString(r) - - _, err := net.LookupIP(hostname) - if err != nil { - log.Printf("Failed to resolve endpoint \"%s\"", hostname) - w.WriteHeader(http.StatusBadGateway) - return - } - - w.WriteHeader(http.StatusNoContent) -} - func settingHandler(w http.ResponseWriter, r *http.Request) { hostname := getHostnameFromQueryString(r) From 37e4c334e368c90dc213017a1ad8483acc850e54 Mon Sep 17 00:00:00 2001 From: Krusty93 Date: Wed, 26 Nov 2025 11:19:46 +0100 Subject: [PATCH 07/10] add terratest project --- .../tests/apps/all_scenarios/src/main.go | 6 +- .../azure_app_configuration/tests/e2e_test.go | 70 +++++++++++++++++++ .../azure_app_configuration/tests/go.mod | 3 + 3 files changed, 77 insertions(+), 2 deletions(-) create mode 100644 infra/modules/azure_app_configuration/tests/e2e_test.go create mode 100644 infra/modules/azure_app_configuration/tests/go.mod diff --git a/infra/modules/azure_app_configuration/tests/apps/all_scenarios/src/main.go b/infra/modules/azure_app_configuration/tests/apps/all_scenarios/src/main.go index 378d267cd2..b1168eb1a5 100644 --- a/infra/modules/azure_app_configuration/tests/apps/all_scenarios/src/main.go +++ b/infra/modules/azure_app_configuration/tests/apps/all_scenarios/src/main.go @@ -19,6 +19,8 @@ type Secret struct { SecretKey string `json:"secret-key"` } +const timeout = 5 + func main() { mux := http.NewServeMux() mux.HandleFunc("/setting", settingHandler) @@ -34,7 +36,7 @@ func main() { func settingHandler(w http.ResponseWriter, r *http.Request) { hostname := getHostnameFromQueryString(r) - ctx, cancel := context.WithTimeout(r.Context(), 10*time.Second) + ctx, cancel := context.WithTimeout(r.Context(), timeout*time.Second) defer cancel() provider, err := loadAzureAppConfiguration(ctx, hostname, false) @@ -56,7 +58,7 @@ func settingHandler(w http.ResponseWriter, r *http.Request) { func secretHandler(w http.ResponseWriter, r *http.Request) { hostname := getHostnameFromQueryString(r) - ctx, cancel := context.WithTimeout(r.Context(), 10*time.Second) + ctx, cancel := context.WithTimeout(r.Context(), timeout*time.Second) defer cancel() provider, err := loadAzureAppConfiguration(ctx, hostname, true) diff --git a/infra/modules/azure_app_configuration/tests/e2e_test.go b/infra/modules/azure_app_configuration/tests/e2e_test.go new file mode 100644 index 0000000000..fb36c5c65a --- /dev/null +++ b/infra/modules/azure_app_configuration/tests/e2e_test.go @@ -0,0 +1,70 @@ +package test + +import ( + "crypto/tls" + "fmt" + "strings" + "testing" + "time" + + httpHelper "github.com/gruntwork-io/terratest/modules/http-helper" + "github.com/gruntwork-io/terratest/modules/terraform" + test_structure "github.com/gruntwork-io/terratest/modules/test-structure" +) + +func TestAppConfigurationNetworkSettings(t *testing.T) { + fixtureFolder := "../examples/network_access/" + + test_structure.RunTestStage(t, "setup", func() { + terraformOptions := &terraform.Options{ + TerraformDir: fixtureFolder, + } + + test_structure.SaveTerraformOptions(t, fixtureFolder, terraformOptions) + + terraform.InitAndApply(t, terraformOptions) + }) + + test_structure.RunTestStage(t, "validate_private_connectivity", func() { + terraformOptions := test_structure.LoadTerraformOptions(t, fixtureFolder) + + appConfigName := terraform.Output(t, terraformOptions, "name") + publicApp := terraform.Output(t, terraformOptions, "public_app_ip_address") + privateApp := terraform.Output(t, terraformOptions, "private_app_ip_address") + + probeSetting(t, privateApp, appConfigName, 200) + probeSetting(t, publicApp, appConfigName, 502) + }) + + // test_structure.RunTestStage(t, "teardown", func() { + // terraformOptions := test_structure.LoadTerraformOptions(t, fixtureFolder) + // terraform.Destroy(t, terraformOptions) + // }) +} + +func probeSetting(t *testing.T, appIPAddress string, appConfigName string, expectedStatus int) { + url := fmt.Sprintf("http://%s:8080/setting?instanceName=%s", appIPAddress, appConfigName) + + maxRetries := 3 + delay := 5 * time.Second + + options := httpHelper.HttpGetOptions{ + Url: url, + TlsConfig: &tls.Config{}, + Timeout: 15, + } + + httpHelper.HttpGetWithRetryWithCustomValidationWithOptions(t, options, maxRetries, delay, func(statusCode int, body string) bool { + if statusCode != expectedStatus { + return false + } + if expectedStatus == 502 { + return true + } + trimmed := strings.TrimSpace(body) + if expectedStatus == 200 { + return trimmed == `{"key":"test value"}` + } + return false + }) +} diff --git a/infra/modules/azure_app_configuration/tests/go.mod b/infra/modules/azure_app_configuration/tests/go.mod new file mode 100644 index 0000000000..e88bba5fb8 --- /dev/null +++ b/infra/modules/azure_app_configuration/tests/go.mod @@ -0,0 +1,3 @@ +module github.com/pagopa/dx/modules/azure_app_configuration/e2e + +go 1.25.4 From f63ec8c741df0b7d340a5e2f221b9a61862c41f8 Mon Sep 17 00:00:00 2001 From: Krusty93 Date: Wed, 26 Nov 2025 11:23:47 +0100 Subject: [PATCH 08/10] add fixtures --- .../examples/keyvault_integration/fixtures.tf | 63 +++++ .../examples/keyvault_integration/mut.tf | 3 +- .../examples/keyvault_integration/outputs.tf | 4 + .../examples/network_access/README.md | 23 +- .../examples/network_access/data.tf | 22 +- .../examples/network_access/fixtures.tf | 216 +++++++++++++++++- .../examples/network_access/locals.tf | 13 +- .../examples/network_access/mut.tf | 26 ++- .../examples/network_access/outputs.tf | 8 + .../examples/network_access/providers.tf | 5 +- .../azure_app_configuration/tests/e2e_test.go | 19 ++ 11 files changed, 392 insertions(+), 10 deletions(-) diff --git a/infra/modules/azure_app_configuration/examples/keyvault_integration/fixtures.tf b/infra/modules/azure_app_configuration/examples/keyvault_integration/fixtures.tf index 48ce1ec4a2..0fd8e2f3c6 100644 --- a/infra/modules/azure_app_configuration/examples/keyvault_integration/fixtures.tf +++ b/infra/modules/azure_app_configuration/examples/keyvault_integration/fixtures.tf @@ -46,3 +46,66 @@ resource "azurerm_private_endpoint" "kv" { tags = local.tags } + +resource "dx_available_subnet_cidr" "private_app" { + virtual_network_id = data.azurerm_virtual_network.e2e.id + prefix_length = 26 +} + +resource "azurerm_subnet" "private_app" { + name = provider::dx::resource_name(merge(local.naming_config, { + name = "appcs-private", + resource_type = "container_instance_subnet" + })) + resource_group_name = local.e2e_virtual_network.resource_group_name + virtual_network_name = local.e2e_virtual_network.name + address_prefixes = [dx_available_subnet_cidr.private_app.cidr_block] + + delegation { + name = "Microsoft.ContainerInstance/containerGroups" + + service_delegation { + name = "Microsoft.ContainerInstance/containerGroups" + actions = [ + "Microsoft.Network/virtualNetworks/subnets/action", + ] + } + } +} + +resource "azurerm_container_group" "private_app" { + name = provider::dx::resource_name( + merge(local.naming_config, { name = "appcs-private", resource_type = "container_instance" }) + ) + location = local.environment.location + resource_group_name = azurerm_resource_group.e2e_appcs.name + + identity { type = "SystemAssigned" } + + os_type = "Linux" + + container { + name = "network-access" + image = local.docker_image + cpu = "0.5" + memory = "1.5" + ports { + port = 8080 + } + } + + ip_address_type = "Private" + + subnet_ids = [ + azurerm_subnet.private_app.id + ] + + diagnostics { + log_analytics { + workspace_id = data.azurerm_log_analytics_workspace.e2e.workspace_id + workspace_key = data.azurerm_log_analytics_workspace.e2e.primary_shared_key + } + } + + tags = local.tags +} diff --git a/infra/modules/azure_app_configuration/examples/keyvault_integration/mut.tf b/infra/modules/azure_app_configuration/examples/keyvault_integration/mut.tf index e783f0ff3e..63efb9b6e8 100644 --- a/infra/modules/azure_app_configuration/examples/keyvault_integration/mut.tf +++ b/infra/modules/azure_app_configuration/examples/keyvault_integration/mut.tf @@ -10,8 +10,9 @@ module "appcs_with_kv" { environment = (merge(local.environment, { instance_number = random_integer.appcs_instance.result })) resource_group_name = azurerm_resource_group.e2e_appcs.name - subnet_pep_id = data.azurerm_subnet.pep.id + subscription_id = data.azurerm_subscription.current.subscription_id + subnet_pep_id = data.azurerm_subnet.pep.id virtual_network = { name = local.e2e_virtual_network.name resource_group_name = local.e2e_virtual_network.resource_group_name diff --git a/infra/modules/azure_app_configuration/examples/keyvault_integration/outputs.tf b/infra/modules/azure_app_configuration/examples/keyvault_integration/outputs.tf index b1fca7ad28..7cbeb6f83e 100644 --- a/infra/modules/azure_app_configuration/examples/keyvault_integration/outputs.tf +++ b/infra/modules/azure_app_configuration/examples/keyvault_integration/outputs.tf @@ -1,3 +1,7 @@ output "name" { value = module.appcs_with_kv.name } + +output "private_app_ip_address" { + value = azurerm_container_group.private_app.ip_address +} diff --git a/infra/modules/azure_app_configuration/examples/network_access/README.md b/infra/modules/azure_app_configuration/examples/network_access/README.md index 1f96294e44..d314ca0032 100644 --- a/infra/modules/azure_app_configuration/examples/network_access/README.md +++ b/infra/modules/azure_app_configuration/examples/network_access/README.md @@ -7,23 +7,40 @@ |------|---------| | [terraform](#requirement\_terraform) | >= 1.13.0 | | [azurerm](#requirement\_azurerm) | ~> 4.0 | -| [pagopa-dx](#requirement\_pagopa-dx) | ~> 0.8 | +| [dx](#requirement\_dx) | ~> 0.8 | | [random](#requirement\_random) | ~> 3.7 | ## Modules | Name | Source | Version | |------|--------|---------| -| [private\_appcs](#module\_private\_appcs) | pagopa-dx/azure-app-configuration/azurerm | ~> 0.0 | +| [integration\_github\_roles](#module\_integration\_github\_roles) | pagopa-dx/azure-role-assignments/azurerm | ~> 1.0 | +| [private\_appcs](#module\_private\_appcs) | ../../ | n/a | +| [role\_appcs\_private](#module\_role\_appcs\_private) | pagopa-dx/azure-role-assignments/azurerm | ~> 1.0 | +| [role\_appcs\_public](#module\_role\_appcs\_public) | pagopa-dx/azure-role-assignments/azurerm | ~> 1.0 | ## Resources | Name | Type | |------|------| +| [azurerm_app_configuration_key.test_secret](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/app_configuration_key) | resource | +| [azurerm_app_configuration_key.test_setting](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/app_configuration_key) | resource | +| [azurerm_container_group.private_app](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/container_group) | resource | +| [azurerm_container_group.public_app](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/container_group) | resource | +| [azurerm_key_vault.kv](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/key_vault) | resource | +| [azurerm_key_vault_secret.test_secret](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/key_vault_secret) | resource | +| [azurerm_private_endpoint.kv](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/private_endpoint) | resource | | [azurerm_resource_group.e2e_appcs](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/resource_group) | resource | +| [azurerm_subnet.private_app](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/subnet) | resource | +| [dx_available_subnet_cidr.private_app](https://registry.terraform.io/providers/pagopa-dx/azure/latest/docs/resources/available_subnet_cidr) | resource | | [random_integer.appcs_instance](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/integer) | resource | +| [azurerm_client_config.current](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/client_config) | data source | +| [azurerm_log_analytics_workspace.e2e](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/log_analytics_workspace) | data source | +| [azurerm_private_dns_zone.kv](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/private_dns_zone) | data source | | [azurerm_resource_group.network](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/resource_group) | data source | | [azurerm_subnet.pep](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/subnet) | data source | +| [azurerm_subscription.current](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/subscription) | data source | +| [azurerm_user_assigned_identity.integration_github](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/user_assigned_identity) | data source | | [azurerm_virtual_network.e2e](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/virtual_network) | data source | ## Inputs @@ -35,4 +52,6 @@ No inputs. | Name | Description | |------|-------------| | [name](#output\_name) | n/a | +| [private\_app\_ip\_address](#output\_private\_app\_ip\_address) | n/a | +| [public\_app\_ip\_address](#output\_public\_app\_ip\_address) | n/a | diff --git a/infra/modules/azure_app_configuration/examples/network_access/data.tf b/infra/modules/azure_app_configuration/examples/network_access/data.tf index 208aa45d47..3976ac7fdb 100644 --- a/infra/modules/azure_app_configuration/examples/network_access/data.tf +++ b/infra/modules/azure_app_configuration/examples/network_access/data.tf @@ -1,10 +1,28 @@ +data "azurerm_client_config" "current" {} + +data "azurerm_subscription" "current" {} + +data "azurerm_log_analytics_workspace" "e2e" { + name = local.e2e_log_analytics_workspace.name + resource_group_name = local.e2e_virtual_network.resource_group_name +} + +data "azurerm_private_dns_zone" "kv" { + name = "privatelink.vaultcore.azure.net" + resource_group_name = data.azurerm_resource_group.network.name +} + +data "azurerm_user_assigned_identity" "integration_github" { + name = "dx-d-itn-devex-integration-id-01" + resource_group_name = "dx-d-itn-devex-rg-01" +} data "azurerm_virtual_network" "e2e" { name = local.e2e_virtual_network.name resource_group_name = local.e2e_virtual_network.resource_group_name } data "azurerm_subnet" "pep" { - name = provider::pagopa-dx::resource_name(merge(local.naming_config, { + name = provider::dx::resource_name(merge(local.naming_config, { name = "pep", resource_type = "subnet" })) @@ -13,7 +31,7 @@ data "azurerm_subnet" "pep" { } data "azurerm_resource_group" "network" { - name = provider::pagopa-dx::resource_name(merge(local.naming_config, { + name = provider::dx::resource_name(merge(local.naming_config, { name = "network" resource_type = "resource_group" })) diff --git a/infra/modules/azure_app_configuration/examples/network_access/fixtures.tf b/infra/modules/azure_app_configuration/examples/network_access/fixtures.tf index 0b8e731e33..a407478c09 100644 --- a/infra/modules/azure_app_configuration/examples/network_access/fixtures.tf +++ b/infra/modules/azure_app_configuration/examples/network_access/fixtures.tf @@ -1,5 +1,5 @@ resource "azurerm_resource_group" "e2e_appcs" { - name = provider::pagopa-dx::resource_name(merge(local.naming_config, { + name = provider::dx::resource_name(merge(local.naming_config, { domain = "e2e" name = "appcs", resource_type = "resource_group" @@ -8,3 +8,217 @@ resource "azurerm_resource_group" "e2e_appcs" { tags = local.tags } + +resource "azurerm_container_group" "public_app" { + name = provider::dx::resource_name( + merge(local.naming_config, { name = "appcs-public", resource_type = "container_instance" }) + ) + location = local.environment.location + resource_group_name = azurerm_resource_group.e2e_appcs.name + + identity { type = "SystemAssigned" } + + os_type = "Linux" + + container { + name = "network-access" + image = local.docker_image + cpu = "0.5" + memory = "1.5" + ports { + port = 8080 + } + } + + diagnostics { + log_analytics { + workspace_id = data.azurerm_log_analytics_workspace.e2e.workspace_id + workspace_key = data.azurerm_log_analytics_workspace.e2e.primary_shared_key + } + } + + tags = local.tags +} + +resource "dx_available_subnet_cidr" "private_app" { + virtual_network_id = data.azurerm_virtual_network.e2e.id + prefix_length = 26 +} + +resource "azurerm_subnet" "private_app" { + name = provider::dx::resource_name(merge(local.naming_config, { + name = "appcs-private", + resource_type = "container_instance_subnet" + })) + resource_group_name = local.e2e_virtual_network.resource_group_name + virtual_network_name = local.e2e_virtual_network.name + address_prefixes = [dx_available_subnet_cidr.private_app.cidr_block] + + delegation { + name = "Microsoft.ContainerInstance/containerGroups" + + service_delegation { + name = "Microsoft.ContainerInstance/containerGroups" + actions = [ + "Microsoft.Network/virtualNetworks/subnets/action", + ] + } + } +} + +resource "azurerm_container_group" "private_app" { + name = provider::dx::resource_name( + merge(local.naming_config, { name = "appcs-private", resource_type = "container_instance" }) + ) + location = local.environment.location + resource_group_name = azurerm_resource_group.e2e_appcs.name + + identity { type = "SystemAssigned" } + + os_type = "Linux" + + container { + name = "network-access" + image = local.docker_image + cpu = "0.5" + memory = "1.5" + ports { + port = 8080 + } + } + + ip_address_type = "Private" + + subnet_ids = [ + azurerm_subnet.private_app.id + ] + + diagnostics { + log_analytics { + workspace_id = data.azurerm_log_analytics_workspace.e2e.workspace_id + workspace_key = data.azurerm_log_analytics_workspace.e2e.primary_shared_key + } + } + + tags = local.tags +} + +#trivy:ignore:AVD-AZU-0016 +resource "azurerm_key_vault" "kv" { + name = provider::dx::resource_name(merge(local.naming_config, { resource_type = "key_vault", instance_number = random_integer.appcs_instance.result })) + location = azurerm_resource_group.e2e_appcs.location + resource_group_name = azurerm_resource_group.e2e_appcs.name + tenant_id = data.azurerm_client_config.current.tenant_id + rbac_authorization_enabled = true + sku_name = "standard" + purge_protection_enabled = false + public_network_access_enabled = false + + network_acls { + bypass = "AzureServices" + default_action = "Deny" + } + + tags = local.tags +} + +#trivy:ignore:AVD-AZU-0015 +#trivy:ignore:AVD-AZU-0017 +resource "azurerm_key_vault_secret" "test_secret" { + name = "secret-key" + key_vault_id = azurerm_key_vault.kv.id + value = "secret-value" + + depends_on = [ + module.integration_github_roles + ] +} + +resource "azurerm_private_endpoint" "kv" { + name = provider::dx::resource_name(merge(local.naming_config, { resource_type = "key_vault_private_endpoint", instance_number = random_integer.appcs_instance.result })) + location = azurerm_resource_group.e2e_appcs.location + resource_group_name = azurerm_resource_group.e2e_appcs.name + subnet_id = data.azurerm_subnet.pep.id + + private_service_connection { + name = provider::dx::resource_name(merge(local.naming_config, { resource_type = "key_vault_private_endpoint", instance_number = random_integer.appcs_instance.result })) + private_connection_resource_id = azurerm_key_vault.kv.id + is_manual_connection = false + subresource_names = ["vault"] + } + + private_dns_zone_group { + name = "private-dns-zone-group" + private_dns_zone_ids = [data.azurerm_private_dns_zone.kv.id] + } + + tags = local.tags +} + +module "role_appcs_private" { + source = "pagopa-dx/azure-role-assignments/azurerm" + version = "~> 1.0" + + principal_id = azurerm_container_group.private_app.identity[0].principal_id + subscription_id = data.azurerm_subscription.current.subscription_id + + app_config = [ + { + name = module.private_appcs.name + resource_group_name = module.private_appcs.resource_group_name + description = "Allow private Container Instance to read from App Configuration" + role = "reader" + } + ] + + # key_vault = { + # name = module.private_keyvault.key_vault_name + # resource_group_name = module.private_keyvault.resource_group_name + # has_rbac_enabled = true + # } +} + +module "role_appcs_public" { + source = "pagopa-dx/azure-role-assignments/azurerm" + version = "~> 1.0" + + principal_id = azurerm_container_group.public_app.identity[0].principal_id + subscription_id = data.azurerm_subscription.current.subscription_id + + app_config = [ + { + name = module.private_appcs.name + resource_group_name = module.private_appcs.resource_group_name + description = "Allow public Container Instance to read from App Configuration" + role = "reader" + } + ] +} + +module "integration_github_roles" { + source = "pagopa-dx/azure-role-assignments/azurerm" + version = "~> 1.0" + + principal_id = data.azurerm_user_assigned_identity.integration_github.principal_id + subscription_id = data.azurerm_subscription.current.subscription_id + + app_config = [ + { + name = module.private_appcs.name + resource_group_name = module.private_appcs.resource_group_name + description = "Allow GitHub to write settings on App Configuration" + role = "writer" + } + ] + + key_vault = [ + { + name = azurerm_key_vault.kv.name + resource_group_name = azurerm_key_vault.kv.resource_group_name + description = "Allow GitHub to write secrets on Key Vault" + roles = { + secrets = "writer" + } + } + ] +} diff --git a/infra/modules/azure_app_configuration/examples/network_access/locals.tf b/infra/modules/azure_app_configuration/examples/network_access/locals.tf index d7481adcaa..c12ab0b8d6 100644 --- a/infra/modules/azure_app_configuration/examples/network_access/locals.tf +++ b/infra/modules/azure_app_configuration/examples/network_access/locals.tf @@ -26,13 +26,22 @@ locals { } e2e_virtual_network = { - name = provider::pagopa-dx::resource_name(merge(local.naming_config, { + name = provider::dx::resource_name(merge(local.naming_config, { name = "e2e", resource_type = "virtual_network" })) - resource_group_name = provider::pagopa-dx::resource_name(merge(local.naming_config, { + resource_group_name = provider::dx::resource_name(merge(local.naming_config, { name = "e2e", resource_type = "resource_group" })) } + + e2e_log_analytics_workspace = { + name = provider::dx::resource_name(merge(local.naming_config, { + name = "e2e", + resource_type = "log_analytics" + })) + } + + docker_image = "ghcr.io/pagopa/e2e-appconfiguration-all-scenarios:latest" } diff --git a/infra/modules/azure_app_configuration/examples/network_access/mut.tf b/infra/modules/azure_app_configuration/examples/network_access/mut.tf index 791b002aa2..005e7440ce 100644 --- a/infra/modules/azure_app_configuration/examples/network_access/mut.tf +++ b/infra/modules/azure_app_configuration/examples/network_access/mut.tf @@ -10,8 +10,9 @@ module "private_appcs" { environment = (merge(local.environment, { instance_number = random_integer.appcs_instance.result })) resource_group_name = azurerm_resource_group.e2e_appcs.name - subnet_pep_id = data.azurerm_subnet.pep.id + subscription_id = data.azurerm_subscription.current.subscription_id + subnet_pep_id = data.azurerm_subnet.pep.id virtual_network = { name = local.e2e_virtual_network.name resource_group_name = local.e2e_virtual_network.resource_group_name @@ -20,3 +21,26 @@ module "private_appcs" { private_dns_zone_resource_group_name = data.azurerm_resource_group.network.name tags = local.tags } + +resource "azurerm_app_configuration_key" "test_setting" { + configuration_store_id = module.private_appcs.id + key = "Setting:test-key" + value = "test value" + content_type = "application/json" + + depends_on = [ + module.integration_github_roles + ] +} + +resource "azurerm_app_configuration_key" "test_secret" { + configuration_store_id = module.private_appcs.id + key = "Secret:secret-key" + type = "vault" + vault_key_reference = azurerm_key_vault_secret.test_secret.versionless_id + + depends_on = [ + module.integration_github_roles, + azurerm_key_vault_secret.test_secret + ] +} diff --git a/infra/modules/azure_app_configuration/examples/network_access/outputs.tf b/infra/modules/azure_app_configuration/examples/network_access/outputs.tf index df43cc6eee..44a2a88497 100644 --- a/infra/modules/azure_app_configuration/examples/network_access/outputs.tf +++ b/infra/modules/azure_app_configuration/examples/network_access/outputs.tf @@ -1,3 +1,11 @@ output "name" { value = module.private_appcs.name } + +output "public_app_ip_address" { + value = azurerm_container_group.public_app.ip_address +} + +output "private_app_ip_address" { + value = azurerm_container_group.private_app.ip_address +} diff --git a/infra/modules/azure_app_configuration/examples/network_access/providers.tf b/infra/modules/azure_app_configuration/examples/network_access/providers.tf index 75e33e5c13..d8ebedddaf 100644 --- a/infra/modules/azure_app_configuration/examples/network_access/providers.tf +++ b/infra/modules/azure_app_configuration/examples/network_access/providers.tf @@ -6,7 +6,7 @@ terraform { source = "hashicorp/azurerm" version = "~> 4.0" } - pagopa-dx = { + dx = { source = "pagopa-dx/azure" version = "~> 0.8" } @@ -29,5 +29,8 @@ provider "azurerm" { } } +provider "dx" { +} + provider "random" { } diff --git a/infra/modules/azure_app_configuration/tests/e2e_test.go b/infra/modules/azure_app_configuration/tests/e2e_test.go index fb36c5c65a..00e4ba32c7 100644 --- a/infra/modules/azure_app_configuration/tests/e2e_test.go +++ b/infra/modules/azure_app_configuration/tests/e2e_test.go @@ -42,6 +42,25 @@ func TestAppConfigurationNetworkSettings(t *testing.T) { // }) } +func TestAppConfigurationKeyVaultIntegration(t *testing.T) { + fixtureFolder := "../examples/key_vault_integration/" + + test_structure.RunTestStage(t, "setup", func() { + terraformOptions := &terraform.Options{ + TerraformDir: fixtureFolder, + } + + test_structure.SaveTerraformOptions(t, fixtureFolder, terraformOptions) + + terraform.InitAndApply(t, terraformOptions) + }) + + test_structure.RunTestStage(t, "validate_keyvault_integration", func() { + terraformOptions := test_structure.LoadTerraformOptions(t, fixtureFolder) + + }) +} + func probeSetting(t *testing.T, appIPAddress string, appConfigName string, expectedStatus int) { url := fmt.Sprintf("http://%s:8080/setting?instanceName=%s", appIPAddress, appConfigName) From 46939253b1c093e1290edfdb2206123a8d8987f7 Mon Sep 17 00:00:00 2001 From: Krusty93 Date: Fri, 13 Feb 2026 16:16:14 +0100 Subject: [PATCH 09/10] update readme --- .../modules/azure_app_configuration/README.md | 71 +++++++++---------- 1 file changed, 35 insertions(+), 36 deletions(-) diff --git a/infra/modules/azure_app_configuration/README.md b/infra/modules/azure_app_configuration/README.md index 946141d38a..9e96b6ce3d 100644 --- a/infra/modules/azure_app_configuration/README.md +++ b/infra/modules/azure_app_configuration/README.md @@ -29,54 +29,53 @@ The allowed sizes are: For examples of how to use this module, refer to the [examples](https://github.com/pagopa-dx/terraform-azurerm-azure-app-configuration/tree/main/examples) folder in the module repository. - ## Requirements -| Name | Version | -| ------------------------------------------------------------------------ | ------- | -| [azurerm](#requirement_azurerm) | ~> 4.0 | -| [pagopa-dx](#requirement_pagopa-dx) | ~> 0.8 | +| Name | Version | +|------|---------| +| [azurerm](#requirement\_azurerm) | ~> 4.0 | +| [pagopa-dx](#requirement\_pagopa-dx) | ~> 0.8 | ## Modules -| Name | Source | Version | -| ----------------------------------------------------------------------------------------------- | ---------------------------------------- | ------- | -| [app_roles](#module_app_roles) | pagopa-dx/azure-role-assignments/azurerm | ~> 1.3 | -| [appconfig_team_roles](#module_appconfig_team_roles) | pagopa-dx/azure-role-assignments/azurerm | ~> 1.3 | +| Name | Source | Version | +|------|--------|---------| +| [app\_roles](#module\_app\_roles) | pagopa-dx/azure-role-assignments/azurerm | ~> 1.3 | +| [appconfig\_team\_roles](#module\_appconfig\_team\_roles) | pagopa-dx/azure-role-assignments/azurerm | ~> 1.3 | ## Resources -| Name | Type | -| ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------- | -| [azurerm_app_configuration.this](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/app_configuration) | resource | -| [azurerm_monitor_diagnostic_setting.app_configuration](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/monitor_diagnostic_setting) | resource | -| [azurerm_private_endpoint.app_config](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/private_endpoint) | resource | -| [azurerm_private_dns_zone.appconfig](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/private_dns_zone) | data source | +| Name | Type | +|------|------| +| [azurerm_app_configuration.this](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/app_configuration) | resource | +| [azurerm_monitor_diagnostic_setting.app_configuration](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/monitor_diagnostic_setting) | resource | +| [azurerm_private_endpoint.app_config](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/private_endpoint) | resource | +| [azurerm_private_dns_zone.appconfig](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/private_dns_zone) | data source | ## Inputs -| Name | Description | Type | Default | Required | -| --------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------- | :------: | -| [authorized_teams](#input_authorized_teams) | Object containing lists of principal IDs (Azure AD object IDs) of product teams to be granted read or write permissions on the App Configuration. These represent the teams within the organization that need access to this resource." |
object({
writers = optional(list(string), []),
readers = optional(list(string), [])
})
|
{
"readers": [],
"writers": []
}
| no | -| [environment](#input_environment) | Values which are used to generate resource names and location short names. They are all mandatory except for domain, which should not be used only in the case of a resource used by multiple domains. |
object({
prefix = string
env_short = string
location = string
domain = optional(string)
app_name = string
instance_number = string
})
| n/a | yes | -| [key_vaults](#input_key_vaults) | Optionally, integrate App Configuration with a one or more existing Key Vault for secrets retrieval.
Set `has_rbac_support` to true if the referenced Key Vault uses RBAC model for access control.
Use `app_principal_ids` to set application principal IDs to be granted access to the Key Vault. |
list(object({
name = string
resource_group_name = string
has_rbac_support = bool
app_principal_ids = list(string)
}))
| `null` | no | -| [private_dns_zone_resource_group_name](#input_private_dns_zone_resource_group_name) | Name of the resource group containing the private DNS zone for private endpoints. Default is the resource group of the virtual network. | `string` | `null` | no | -| [resource_group_name](#input_resource_group_name) | The name of the resource group where resources will be deployed. | `string` | n/a | yes | -| [size](#input_size) | "App Configuration SKU. Allowed values: 'standard', 'premium'. If not set, it will be determined by the use_case." | `string` | `null` | no | -| [subnet_pep_id](#input_subnet_pep_id) | ID of the subnet hosting private endpoints. | `string` | n/a | yes | -| [subscription_id](#input_subscription_id) | Subscription Id of the involved resources | `string` | n/a | yes | -| [tags](#input_tags) | A map of tags to assign to the resources. | `map(any)` | n/a | yes | -| [use_case](#input_use_case) | Allowed values: 'default', 'development'. | `string` | `"default"` | no | -| [virtual_network](#input_virtual_network) | Virtual network where the subnet will be created. |
object({
name = string
resource_group_name = string
})
| n/a | yes | +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [authorized\_teams](#input\_authorized\_teams) | Object containing lists of principal IDs (Azure AD object IDs) of product teams to be granted read or write permissions on the App Configuration. These represent the teams within the organization that need access to this resource." |
object({
writers = optional(list(string), []),
readers = optional(list(string), [])
})
|
{
"readers": [],
"writers": []
}
| no | +| [diagnostic\_settings](#input\_diagnostic\_settings) | Diagnostic settings for App Configuration logs and metrics. When enabled, sends diagnostics to Log Analytics workspace and/or Storage Account. |
object({
enabled = bool
log_analytics_workspace_id = optional(string, null)
storage_account_id = optional(string, null)
})
|
{
"enabled": false,
"log_analytics_workspace_id": null
}
| no | +| [environment](#input\_environment) | Values which are used to generate resource names and location short names. They are all mandatory except for domain, which should not be used only in the case of a resource used by multiple domains. |
object({
prefix = string
env_short = string
location = string
domain = optional(string)
app_name = string
instance_number = string
})
| n/a | yes | +| [key\_vaults](#input\_key\_vaults) | Optionally, integrate App Configuration with a one or more existing Key Vault for secrets retrieval.
Set `has_rbac_support` to true if the referenced Key Vault uses RBAC model for access control.
Use `app_principal_ids` to set application principal IDs to be granted access to the Key Vault. |
list(object({
name = string
resource_group_name = string
has_rbac_support = bool
app_principal_ids = list(string)
}))
| `null` | no | +| [private\_dns\_zone\_resource\_group\_name](#input\_private\_dns\_zone\_resource\_group\_name) | Name of the resource group containing the private DNS zone for private endpoints. Default is the resource group of the virtual network. | `string` | `null` | no | +| [resource\_group\_name](#input\_resource\_group\_name) | The name of the resource group where resources will be deployed. | `string` | n/a | yes | +| [size](#input\_size) | "App Configuration SKU. Allowed values: 'standard', 'premium'. If not set, it will be determined by the use\_case." | `string` | `null` | no | +| [subnet\_pep\_id](#input\_subnet\_pep\_id) | ID of the subnet hosting private endpoints. | `string` | n/a | yes | +| [subscription\_id](#input\_subscription\_id) | Subscription Id of the involved resources | `string` | n/a | yes | +| [tags](#input\_tags) | A map of tags to assign to the resources. | `map(any)` | n/a | yes | +| [use\_case](#input\_use\_case) | Allowed values: 'default', 'development'. | `string` | `"default"` | no | +| [virtual\_network](#input\_virtual\_network) | Virtual network where the subnet will be created. |
object({
name = string
resource_group_name = string
})
| n/a | yes | ## Outputs -| Name | Description | -| -------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------- | -| [endpoint](#output_endpoint) | The service endpoint URL | -| [id](#output_id) | The ID of the Azure Cosmos DB account. | -| [name](#output_name) | The name of the Azure Cosmos DB account. | -| [principal_id](#output_principal_id) | The system-assigned managed identity pricipal id | -| [resource_group_name](#output_resource_group_name) | The name of the resource group containing the Azure Cosmos DB account. | - +| Name | Description | +|------|-------------| +| [endpoint](#output\_endpoint) | The service endpoint URL | +| [id](#output\_id) | The ID of the Azure Cosmos DB account. | +| [name](#output\_name) | The name of the Azure Cosmos DB account. | +| [principal\_id](#output\_principal\_id) | The system-assigned managed identity pricipal id | +| [resource\_group\_name](#output\_resource\_group\_name) | The name of the resource group containing the Azure Cosmos DB account. | From 155fa1905bd55572a665402e9ad8fcc194cce1b2 Mon Sep 17 00:00:00 2001 From: Krusty93 Date: Fri, 13 Feb 2026 16:39:13 +0100 Subject: [PATCH 10/10] trigger action --- .github/workflows/_release-docker-e2e-appconfiguration.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/_release-docker-e2e-appconfiguration.yaml b/.github/workflows/_release-docker-e2e-appconfiguration.yaml index 6fa2376ace..62edb5dae6 100644 --- a/.github/workflows/_release-docker-e2e-appconfiguration.yaml +++ b/.github/workflows/_release-docker-e2e-appconfiguration.yaml @@ -7,8 +7,8 @@ on: branches: - main - CES-1469-aggiungere-esempi-del-modulo-da-usare-per-i-test-e-2-e - paths: - - "infra/modules/azure_app_configuration/tests/apps/all_scenarios/**" + # paths: + # - "infra/modules/azure_app_configuration/tests/apps/all_scenarios/**" env: MODULE_NAME: "azure_app_configuration"