diff --git a/.azuredevops/templates/steps/tf_destroy.yaml b/.azuredevops/templates/steps/tf_destroy.yaml new file mode 100644 index 00000000..2b62c27b --- /dev/null +++ b/.azuredevops/templates/steps/tf_destroy.yaml @@ -0,0 +1,37 @@ +--- + +parameters: + - name: tfCommandOptions + type: string + default: '' + +steps: + - template: tf_init.yaml + + - task: TerraformTaskV4@4 + name: TerraformDestroy + displayName: Terraform Destroy - $(ENVIRONMENT) environment + continueOnError: false + inputs: + provider: azurerm + command: destroy + workingDirectory: $(TF_DIRECTORY) + commandOptions: -var-file=$(tfVarsFile) ${{ parameters.tfCommandOptions }} -var="environment=$(ENVIRONMENT)" + environmentServiceNameAzureRM: $(SERVICE_CONNECTION) + + - task: AzureCLI@2 + displayName: Clean-up Backend + inputs: + azureSubscription: $(SERVICE_CONNECTION) + scriptLocation: inlineScript + scriptType: bash + workingDirectory: $(tfExecutionDir) + inlineScript: | + # Check if the backend configuration file exists and if it does, delete it: + container_exists=$(az storage container exists --name $(BACKEND_AZURE_STORAGE_ACCOUNT_CONTAINER_NAME) --account-name $(BACKEND_AZURE_STORAGE_ACCOUNT_NAME) --auth-mode login --output tsv) + if [ "$container_exists" == "True" ]; then + echo "##[debug] Container $(BACKEND_AZURE_STORAGE_ACCOUNT_CONTAINER_NAME) exists, deleting it..." + #az storage container delete --name $(BACKEND_AZURE_STORAGE_ACCOUNT_CONTAINER_NAME) --account-name $(BACKEND_AZURE_STORAGE_ACCOUNT_NAME) --resource-group $(BACKEND_AZURE_RESOURCE_GROUP_NAME) --auth-mode login --yes + else + echo "##[debug] Container $(BACKEND_AZURE_STORAGE_ACCOUNT_CONTAINER_NAME) does not exist." + fi diff --git a/.azuredevops/templates/steps/tf_plan.yaml b/.azuredevops/templates/steps/tf_plan.yaml index 436e28b8..d67ff634 100644 --- a/.azuredevops/templates/steps/tf_plan.yaml +++ b/.azuredevops/templates/steps/tf_plan.yaml @@ -19,7 +19,7 @@ steps: provider: azurerm command: plan workingDirectory: $(TF_DIRECTORY) - commandOptions: -input=false -var-file=$(tfVarsFile) -out=$(Build.ArtifactStagingDirectory)/$(ENVIRONMENT).tfplan + commandOptions: -input=false -var-file=$(tfVarsFile) $(tfCommandOptions) -out=$(Build.ArtifactStagingDirectory)/$(ENVIRONMENT).tfplan environmentServiceNameAzureRM: $(SERVICE_CONNECTION) - task: PublishBuildArtifacts@1 diff --git a/infrastructure/modules/container-registry/main.tf b/infrastructure/modules/container-registry/main.tf index c66f0ae0..d0067c5c 100644 --- a/infrastructure/modules/container-registry/main.tf +++ b/infrastructure/modules/container-registry/main.tf @@ -19,7 +19,7 @@ resource "azurerm_container_registry" "acr" { -------------------------------------------------------------------------------------------------- */ module "private_endpoint_container_registry" { - count = var.private_endpoint_properties.private_endpoint_enabled ? 1 : 0 + count = var.private_endpoint_properties != null ? 1 : 0 source = "../private-endpoint" diff --git a/infrastructure/modules/container-registry/variables.tf b/infrastructure/modules/container-registry/variables.tf index 8c0f3bf0..ed0e09c2 100644 --- a/infrastructure/modules/container-registry/variables.tf +++ b/infrastructure/modules/container-registry/variables.tf @@ -29,8 +29,16 @@ variable "private_endpoint_properties" { private_service_connection_is_manual = optional(bool, false) }) + # Validate that if private_endpoint_enabled is true, private_dns_zone_ids and private_endpoint_subnet_id are both provided validation { - condition = var.private_endpoint_properties.private_endpoint_enabled == false || (length(var.private_endpoint_properties.private_dns_zone_ids) > 0 && length(var.private_endpoint_properties.private_endpoint_subnet_id) > 0) + condition = ( + can(var.private_endpoint_properties == null) || + (can(var.private_endpoint_properties.private_endpoint_enabled) && var.private_endpoint_properties.private_endpoint_enabled == false) || + (can(var.private_endpoint_properties.private_endpoint_enabled) && var.private_endpoint_properties.private_endpoint_enabled == true && + can(length(var.private_endpoint_properties.private_dns_zone_ids)) && + length(var.private_endpoint_properties.private_dns_zone_ids) > 0 && + can(length(var.private_endpoint_properties.private_endpoint_subnet_id)) && + length(var.private_endpoint_properties.private_endpoint_subnet_id) > 0)) error_message = "Both private_dns_zone_ids and private_endpoint_subnet_id must be provided if private_endpoint_enabled is true." } } diff --git a/infrastructure/modules/event-grid-topic/variables.tf b/infrastructure/modules/event-grid-topic/variables.tf index cf6f83d9..7caae1d9 100644 --- a/infrastructure/modules/event-grid-topic/variables.tf +++ b/infrastructure/modules/event-grid-topic/variables.tf @@ -50,7 +50,14 @@ variable "private_endpoint_properties" { }) validation { - condition = var.private_endpoint_properties.private_endpoint_enabled == false || (length(var.private_endpoint_properties.private_dns_zone_ids) > 0 && length(var.private_endpoint_properties.private_endpoint_subnet_id) > 0) + condition = ( + can(var.private_endpoint_properties == null) || + (can(var.private_endpoint_properties.private_endpoint_enabled) && var.private_endpoint_properties.private_endpoint_enabled == false) || + (can(var.private_endpoint_properties.private_endpoint_enabled) && var.private_endpoint_properties.private_endpoint_enabled == true && + can(length(var.private_endpoint_properties.private_dns_zone_ids)) && + length(var.private_endpoint_properties.private_dns_zone_ids) > 0 && + can(length(var.private_endpoint_properties.private_endpoint_subnet_id)) && + length(var.private_endpoint_properties.private_endpoint_subnet_id) > 0)) error_message = "Both private_dns_zone_ids and private_endpoint_subnet_id must be provided if private_endpoint_enabled is true." } } diff --git a/infrastructure/modules/event-hub/main.tf b/infrastructure/modules/event-hub/main.tf index d77e32e8..669a64f6 100644 --- a/infrastructure/modules/event-hub/main.tf +++ b/infrastructure/modules/event-hub/main.tf @@ -69,7 +69,7 @@ resource "azurerm_eventhub_consumer_group" "consumer_group" { -------------------------------------------------------------------------------------------------- */ module "private_endpoint_eventhub" { - count = var.private_endpoint_properties.private_endpoint_enabled ? 1 : 0 + count = var.private_endpoint_properties != null ? 1 : 0 source = "../private-endpoint" diff --git a/infrastructure/modules/event-hub/variables.tf b/infrastructure/modules/event-hub/variables.tf index 6b62ee7d..30d56f0b 100644 --- a/infrastructure/modules/event-hub/variables.tf +++ b/infrastructure/modules/event-hub/variables.tf @@ -84,8 +84,15 @@ variable "private_endpoint_properties" { }) validation { - condition = var.private_endpoint_properties.private_endpoint_enabled == false || (length(var.private_endpoint_properties.private_dns_zone_ids_eventhub) > 0 && length(var.private_endpoint_properties.private_endpoint_subnet_id) > 0) - error_message = "Both private_dns_zone_ids and private_endpoint_subnet_id must be provided if private_endpoint_enabled is true." + condition = ( + can(var.private_endpoint_properties == null) || + (can(var.private_endpoint_properties.private_endpoint_enabled) && var.private_endpoint_properties.private_endpoint_enabled == false) || + (can(var.private_endpoint_properties.private_endpoint_enabled) && var.private_endpoint_properties.private_endpoint_enabled == true && + can(length(var.private_endpoint_properties.private_dns_zone_ids_eventhub)) && + length(var.private_endpoint_properties.private_dns_zone_ids_eventhub) > 0 && + can(length(var.private_endpoint_properties.private_endpoint_subnet_id)) && + length(var.private_endpoint_properties.private_endpoint_subnet_id) > 0)) + error_message = "Both private_dns_zone_ids_eventhub and private_endpoint_subnet_id must be provided if private_endpoint_enabled is true." } } diff --git a/infrastructure/modules/function-app/main.tf b/infrastructure/modules/function-app/main.tf index 9e43bd9b..02a33d6f 100644 --- a/infrastructure/modules/function-app/main.tf +++ b/infrastructure/modules/function-app/main.tf @@ -80,7 +80,7 @@ resource "azurerm_linux_function_app" "function_app" { -------------------------------------------------------------------------------------------------- */ module "private_endpoint" { - count = var.private_endpoint_properties.private_endpoint_enabled ? 1 : 0 + count = var.private_endpoint_properties != null ? 1 : 0 source = "../private-endpoint" diff --git a/infrastructure/modules/function-app/variables.tf b/infrastructure/modules/function-app/variables.tf index 020781a5..3ef9e2e1 100644 --- a/infrastructure/modules/function-app/variables.tf +++ b/infrastructure/modules/function-app/variables.tf @@ -183,8 +183,16 @@ variable "private_endpoint_properties" { private_service_connection_is_manual = optional(bool, false) }) + # Validation rule does not work when var.private_endpoint_properties is null validation { - condition = var.private_endpoint_properties.private_endpoint_enabled == false || (length(var.private_endpoint_properties.private_dns_zone_ids) > 0 && length(var.private_endpoint_properties.private_endpoint_subnet_id) > 0) + condition = ( + can(var.private_endpoint_properties == null) || + (can(var.private_endpoint_properties.private_endpoint_enabled) && var.private_endpoint_properties.private_endpoint_enabled == false) || + (can(var.private_endpoint_properties.private_endpoint_enabled) && var.private_endpoint_properties.private_endpoint_enabled == true && + can(length(var.private_endpoint_properties.private_dns_zone_ids)) && + length(var.private_endpoint_properties.private_dns_zone_ids) > 0 && + can(length(var.private_endpoint_properties.private_endpoint_subnet_id)) && + length(var.private_endpoint_properties.private_endpoint_subnet_id) > 0)) error_message = "Both private_dns_zone_ids and private_endpoint_subnet_id must be provided if private_endpoint_enabled is true." } } diff --git a/infrastructure/modules/key-vault/main.tf b/infrastructure/modules/key-vault/main.tf index 4befc8db..37da8370 100644 --- a/infrastructure/modules/key-vault/main.tf +++ b/infrastructure/modules/key-vault/main.tf @@ -24,7 +24,7 @@ resource "azurerm_key_vault" "keyvault" { -------------------------------------------------------------------------------------------------- */ module "private_endpoint_keyvault" { - count = var.private_endpoint_properties.private_endpoint_enabled ? 1 : 0 + count = var.private_endpoint_properties != null ? 1 : 0 source = "../private-endpoint" diff --git a/infrastructure/modules/key-vault/variables.tf b/infrastructure/modules/key-vault/variables.tf index 526b0524..34fd79d4 100644 --- a/infrastructure/modules/key-vault/variables.tf +++ b/infrastructure/modules/key-vault/variables.tf @@ -48,6 +48,19 @@ variable "private_endpoint_properties" { private_endpoint_resource_group_name = optional(string, "") private_service_connection_is_manual = optional(bool, false) }) + + # Validation rule does not work when var.private_endpoint_properties is null + validation { + condition = ( + can(var.private_endpoint_properties == null) || + (can(var.private_endpoint_properties.private_endpoint_enabled) && var.private_endpoint_properties.private_endpoint_enabled == false) || + (can(var.private_endpoint_properties.private_endpoint_enabled) && var.private_endpoint_properties.private_endpoint_enabled == true && + can(length(var.private_endpoint_properties.private_dns_zone_ids_keyvault)) && + length(var.private_endpoint_properties.private_dns_zone_ids_keyvault) > 0 && + can(length(var.private_endpoint_properties.private_endpoint_subnet_id)) && + length(var.private_endpoint_properties.private_endpoint_subnet_id) > 0)) + error_message = "Both private_dns_zone_ids and private_endpoint_subnet_id must be provided if private_endpoint_enabled is true." + } } variable "public_network_access_enabled" { diff --git a/infrastructure/modules/postgresql-flexible/main.tf b/infrastructure/modules/postgresql-flexible/main.tf index c62be548..897a1a3c 100644 --- a/infrastructure/modules/postgresql-flexible/main.tf +++ b/infrastructure/modules/postgresql-flexible/main.tf @@ -74,7 +74,7 @@ resource "azurerm_postgresql_flexible_server_configuration" "postgresql_flexible -------------------------------------------------------------------------------------------------- */ module "private_endpoint_postgresql_flexible_server" { - count = var.private_endpoint_properties.private_endpoint_enabled ? 1 : 0 + count = var.private_endpoint_properties != null ? 1 : 0 source = "../private-endpoint" diff --git a/infrastructure/modules/postgresql-flexible/variables.tf b/infrastructure/modules/postgresql-flexible/variables.tf index 8810238c..ac080638 100644 --- a/infrastructure/modules/postgresql-flexible/variables.tf +++ b/infrastructure/modules/postgresql-flexible/variables.tf @@ -152,6 +152,19 @@ variable "private_endpoint_properties" { private_endpoint_resource_group_name = optional(string, "") private_service_connection_is_manual = optional(bool, false) }) + + # Validation rule does not work when var.private_endpoint_properties is null + validation { + condition = ( + can(var.private_endpoint_properties == null) || + (can(var.private_endpoint_properties.private_endpoint_enabled) && var.private_endpoint_properties.private_endpoint_enabled == false) || + (can(var.private_endpoint_properties.private_endpoint_enabled) && var.private_endpoint_properties.private_endpoint_enabled == true && + can(length(var.private_endpoint_properties.private_dns_zone_ids_postgresql)) && + length(var.private_endpoint_properties.private_dns_zone_ids_postgresql) > 0 && + can(length(var.private_endpoint_properties.private_endpoint_subnet_id)) && + length(var.private_endpoint_properties.private_endpoint_subnet_id) > 0)) + error_message = "Both private_dns_zone_ids_postgresql and private_endpoint_subnet_id must be provided if private_endpoint_enabled is true." + } } diff --git a/infrastructure/modules/sql-server/main.tf b/infrastructure/modules/sql-server/main.tf index d16ae8d0..cd913a83 100644 --- a/infrastructure/modules/sql-server/main.tf +++ b/infrastructure/modules/sql-server/main.tf @@ -41,7 +41,7 @@ resource "azurerm_mssql_firewall_rule" "firewall_rule" { Private Endpoint Configuration for SQL Server -------------------------------------------------------------------------------------------------- */ module "private_endpoint_sql_server" { - count = var.private_endpoint_properties.private_endpoint_enabled ? 1 : 0 + count = var.private_endpoint_properties != null ? 1 : 0 source = "../private-endpoint" diff --git a/infrastructure/modules/sql-server/rbac.tf b/infrastructure/modules/sql-server/rbac.tf index 94fa4c71..e98c817f 100644 --- a/infrastructure/modules/sql-server/rbac.tf +++ b/infrastructure/modules/sql-server/rbac.tf @@ -9,8 +9,6 @@ module "rbac_assignments" { scope = var.storage_account_id } -data "azurerm_client_config" "current" {} - locals { rbac_roles = { storage_account_contributor = "Storage Account Contributor" diff --git a/infrastructure/modules/sql-server/variables.tf b/infrastructure/modules/sql-server/variables.tf index f0835c9d..aa3cf78c 100644 --- a/infrastructure/modules/sql-server/variables.tf +++ b/infrastructure/modules/sql-server/variables.tf @@ -57,6 +57,19 @@ variable "private_endpoint_properties" { private_endpoint_resource_group_name = optional(string, "") private_service_connection_is_manual = optional(bool, false) }) + + # Validation rule does not work when var.private_endpoint_properties is null + validation { + condition = ( + can(var.private_endpoint_properties == null) || + (can(var.private_endpoint_properties.private_endpoint_enabled) && var.private_endpoint_properties.private_endpoint_enabled == false) || + (can(var.private_endpoint_properties.private_endpoint_enabled) && var.private_endpoint_properties.private_endpoint_enabled == true && + can(length(var.private_endpoint_properties.private_dns_zone_ids_sql)) && + length(var.private_endpoint_properties.private_dns_zone_ids_sql) > 0 && + can(length(var.private_endpoint_properties.private_endpoint_subnet_id)) && + length(var.private_endpoint_properties.private_endpoint_subnet_id) > 0)) + error_message = "Both private_dns_zone_ids_sql and private_endpoint_subnet_id must be provided if private_endpoint_enabled is true." + } } variable "public_network_access_enabled" { diff --git a/infrastructure/modules/storage/main.tf b/infrastructure/modules/storage/main.tf index c266bee6..6ace08a6 100644 --- a/infrastructure/modules/storage/main.tf +++ b/infrastructure/modules/storage/main.tf @@ -35,7 +35,7 @@ resource "azurerm_storage_container" "container" { -------------------------------------------------------------------------------------------------- */ module "private_endpoint_blob_storage" { - count = var.private_endpoint_properties.private_endpoint_enabled ? 1 : 0 + count = var.private_endpoint_properties != null ? 1 : 0 source = "../private-endpoint" @@ -60,7 +60,7 @@ module "private_endpoint_blob_storage" { } module "private_endpoint_queue_storage" { - count = var.private_endpoint_properties.private_endpoint_enabled ? 1 : 0 + count = var.private_endpoint_properties != null ? 1 : 0 source = "../private-endpoint" diff --git a/infrastructure/modules/storage/variables.tf b/infrastructure/modules/storage/variables.tf index d2619808..2fb555f6 100644 --- a/infrastructure/modules/storage/variables.tf +++ b/infrastructure/modules/storage/variables.tf @@ -77,8 +77,18 @@ variable "private_endpoint_properties" { private_service_connection_is_manual = optional(bool, false) }) + # Validation rule does not work when var.private_endpoint_properties is null validation { - condition = var.private_endpoint_properties.private_endpoint_enabled == false || (length(var.private_endpoint_properties.private_dns_zone_ids_blob) > 0 && length(var.private_endpoint_properties.private_dns_zone_ids_queue) > 0 && length(var.private_endpoint_properties.private_endpoint_subnet_id) > 0) + condition = ( + can(var.private_endpoint_properties == null) || + (can(var.private_endpoint_properties.private_endpoint_enabled) && var.private_endpoint_properties.private_endpoint_enabled == false) || + (can(var.private_endpoint_properties.private_endpoint_enabled) && var.private_endpoint_properties.private_endpoint_enabled == true && + can(length(var.private_endpoint_properties.private_dns_zone_ids_blob)) && + length(var.private_endpoint_properties.private_dns_zone_ids_blob) > 0 && + can(length(var.private_endpoint_properties.private_dns_zone_ids_queue)) && + length(var.private_endpoint_properties.private_dns_zone_ids_queue) > 0 && + can(length(var.private_endpoint_properties.private_endpoint_subnet_id)) && + length(var.private_endpoint_properties.private_endpoint_subnet_id) > 0)) error_message = "Both private_dns_zone_ids and private_endpoint_subnet_id must be provided if private_endpoint_enabled is true." } }