diff --git a/.github/actions/devcontainer_run_command/action.yml b/.github/actions/devcontainer_run_command/action.yml index a57f120f65..89b92c4945 100644 --- a/.github/actions/devcontainer_run_command/action.yml +++ b/.github/actions/devcontainer_run_command/action.yml @@ -286,7 +286,7 @@ runs: -e UI_FOOTER_TEXT="${{ inputs.UI_FOOTER_TEXT }}" \ -e TF_VAR_resource_processor_number_processes_per_instance="${{ (inputs.RESOURCE_PROCESSOR_NUMBER_PROCESSES_PER_INSTANCE != '' && inputs.RESOURCE_PROCESSOR_NUMBER_PROCESSES_PER_INSTANCE) || 5 }}" \ - -e TF_VAR_firewall_sku=${{ inputs.FIREWALL_SKU }} \ + -e TF_VAR_firewall_sku=${{ inputs.FIREWALL_SKU != '' && inputs.FIREWALL_SKU || 'Standard' }} \ -e TF_VAR_app_gateway_sku=${{ inputs.APP_GATEWAY_SKU }} \ -e TF_VAR_enable_cmk_encryption="${{ (inputs.ENABLE_CMK_ENCRYPTION != '' && inputs.ENABLE_CMK_ENCRYPTION) || 'false' }}" \ diff --git a/.github/workflows/deploy_tre_reusable.yml b/.github/workflows/deploy_tre_reusable.yml index 3a092e8cf9..ca36d9a0bc 100644 --- a/.github/workflows/deploy_tre_reusable.yml +++ b/.github/workflows/deploy_tre_reusable.yml @@ -300,7 +300,12 @@ jobs: strategy: fail-fast: true matrix: - target: [build-and-push-api, build-and-push-resource-processor, build-and-push-airlock-processor] + target: + [ + build-and-push-api, + build-and-push-resource-processor, + build-and-push-airlock-processor + ] steps: - name: Checkout @@ -414,38 +419,38 @@ jobs: strategy: matrix: include: - - {BUNDLE_TYPE: "workspace", - BUNDLE_DIR: "./templates/workspaces/base"} - - {BUNDLE_TYPE: "workspace", - BUNDLE_DIR: "./templates/workspaces/unrestricted"} - - {BUNDLE_TYPE: "workspace", - BUNDLE_DIR: "./templates/workspaces/airlock-import-review"} - - {BUNDLE_TYPE: "workspace_service", - BUNDLE_DIR: "./templates/workspace_services/guacamole"} - - {BUNDLE_TYPE: "workspace_service", - BUNDLE_DIR: "./templates/workspace_services/azureml"} - - {BUNDLE_TYPE: "workspace_service", - BUNDLE_DIR: "./templates/workspace_services/gitea"} - - {BUNDLE_TYPE: "workspace_service", - BUNDLE_DIR: "./templates/workspace_services/mysql"} - - {BUNDLE_TYPE: "workspace_service", - BUNDLE_DIR: "./templates/workspace_services/health-services"} - - {BUNDLE_TYPE: "workspace_service", - BUNDLE_DIR: "./templates/workspace_services/databricks"} - - {BUNDLE_TYPE: "workspace_service", - BUNDLE_DIR: "./templates/workspace_services/ohdsi"} - - {BUNDLE_TYPE: "workspace_service", - BUNDLE_DIR: "./templates/workspace_services/azuresql"} - - {BUNDLE_TYPE: "workspace_service", - BUNDLE_DIR: "./templates/workspace_services/openai"} - - {BUNDLE_TYPE: "user_resource", - BUNDLE_DIR: "./templates/workspace_services/guacamole/user_resources/guacamole-azure-windowsvm"} - - {BUNDLE_TYPE: "user_resource", - BUNDLE_DIR: "./templates/workspace_services/guacamole/user_resources/guacamole-azure-linuxvm"} - - {BUNDLE_TYPE: "user_resource", - BUNDLE_DIR: "./templates/workspace_services/guacamole/user_resources/guacamole-azure-export-reviewvm"} - - {BUNDLE_TYPE: "user_resource", - BUNDLE_DIR: "./templates/workspace_services/guacamole/user_resources/guacamole-azure-import-reviewvm"} + - BUNDLE_TYPE: "workspace" + BUNDLE_DIR: "./templates/workspaces/base" + - BUNDLE_TYPE: "workspace" + BUNDLE_DIR: "./templates/workspaces/unrestricted" + - BUNDLE_TYPE: "workspace" + BUNDLE_DIR: "./templates/workspaces/airlock-import-review" + - BUNDLE_TYPE: "workspace_service" + BUNDLE_DIR: "./templates/workspace_services/guacamole" + - BUNDLE_TYPE: "workspace_service" + BUNDLE_DIR: "./templates/workspace_services/azureml" + - BUNDLE_TYPE: "workspace_service" + BUNDLE_DIR: "./templates/workspace_services/gitea" + - BUNDLE_TYPE: "workspace_service" + BUNDLE_DIR: "./templates/workspace_services/mysql" + - BUNDLE_TYPE: "workspace_service" + BUNDLE_DIR: "./templates/workspace_services/health-services" + - BUNDLE_TYPE: "workspace_service" + BUNDLE_DIR: "./templates/workspace_services/databricks" + - BUNDLE_TYPE: "workspace_service" + BUNDLE_DIR: "./templates/workspace_services/ohdsi" + - BUNDLE_TYPE: "workspace_service" + BUNDLE_DIR: "./templates/workspace_services/azuresql" + - BUNDLE_TYPE: "workspace_service" + BUNDLE_DIR: "./templates/workspace_services/openai" + - BUNDLE_TYPE: "user_resource" + BUNDLE_DIR: "./templates/workspace_services/guacamole/user_resources/guacamole-azure-windowsvm" + - BUNDLE_TYPE: "user_resource" + BUNDLE_DIR: "./templates/workspace_services/guacamole/user_resources/guacamole-azure-linuxvm" + - BUNDLE_TYPE: "user_resource" + BUNDLE_DIR: "./templates/workspace_services/guacamole/user_resources/guacamole-azure-export-reviewvm" + - BUNDLE_TYPE: "user_resource" + BUNDLE_DIR: "./templates/workspace_services/guacamole/user_resources/guacamole-azure-import-reviewvm" environment: ${{ inputs.environmentName }} steps: - name: Checkout @@ -481,22 +486,22 @@ jobs: strategy: matrix: include: - - {BUNDLE_TYPE: "shared_service", - BUNDLE_DIR: "./templates/shared_services/firewall/"} - - {BUNDLE_TYPE: "shared_service", - BUNDLE_DIR: "./templates/shared_services/gitea/"} - - {BUNDLE_TYPE: "shared_service", - BUNDLE_DIR: "./templates/shared_services/admin-vm/"} - - {BUNDLE_TYPE: "shared_service", - BUNDLE_DIR: "./templates/shared_services/airlock_notifier/"} - - {BUNDLE_TYPE: "shared_service", - BUNDLE_DIR: "./templates/shared_services/certs/"} - - {BUNDLE_TYPE: "shared_service", - BUNDLE_DIR: "./templates/shared_services/cyclecloud/"} - - {BUNDLE_TYPE: "shared_service", - BUNDLE_DIR: "./templates/shared_services/sonatype-nexus-vm/"} - - {BUNDLE_TYPE: "shared_service", - BUNDLE_DIR: "./templates/shared_services/databricks-auth/"} + - BUNDLE_TYPE: "shared_service" + BUNDLE_DIR: "./templates/shared_services/firewall/" + - BUNDLE_TYPE: "shared_service" + BUNDLE_DIR: "./templates/shared_services/gitea/" + - BUNDLE_TYPE: "shared_service" + BUNDLE_DIR: "./templates/shared_services/admin-vm/" + - BUNDLE_TYPE: "shared_service" + BUNDLE_DIR: "./templates/shared_services/airlock_notifier/" + - BUNDLE_TYPE: "shared_service" + BUNDLE_DIR: "./templates/shared_services/certs/" + - BUNDLE_TYPE: "shared_service" + BUNDLE_DIR: "./templates/shared_services/cyclecloud/" + - BUNDLE_TYPE: "shared_service" + BUNDLE_DIR: "./templates/shared_services/sonatype-nexus-vm/" + - BUNDLE_TYPE: "shared_service" + BUNDLE_DIR: "./templates/shared_services/databricks-auth/" environment: ${{ inputs.environmentName }} steps: - name: Checkout @@ -532,22 +537,22 @@ jobs: strategy: matrix: include: - - {BUNDLE_TYPE: "shared_service", - BUNDLE_DIR: "./templates/shared_services/firewall"} - - {BUNDLE_TYPE: "shared_service", - BUNDLE_DIR: "./templates/shared_services/gitea"} - - {BUNDLE_TYPE: "shared_service", - BUNDLE_DIR: "./templates/shared_services/admin-vm/"} - - {BUNDLE_TYPE: "shared_service", - BUNDLE_DIR: "./templates/shared_services/airlock_notifier/"} - - {BUNDLE_TYPE: "shared_service", - BUNDLE_DIR: "./templates/shared_services/certs/"} - - {BUNDLE_TYPE: "shared_service", - BUNDLE_DIR: "./templates/shared_services/cyclecloud/"} - - {BUNDLE_TYPE: "shared_service", - BUNDLE_DIR: "./templates/shared_services/sonatype-nexus-vm/"} - - {BUNDLE_TYPE: "shared_service", - BUNDLE_DIR: "./templates/shared_services/databricks-auth/"} + - BUNDLE_TYPE: "shared_service" + BUNDLE_DIR: "./templates/shared_services/firewall" + - BUNDLE_TYPE: "shared_service" + BUNDLE_DIR: "./templates/shared_services/gitea" + - BUNDLE_TYPE: "shared_service" + BUNDLE_DIR: "./templates/shared_services/admin-vm/" + - BUNDLE_TYPE: "shared_service" + BUNDLE_DIR: "./templates/shared_services/airlock_notifier/" + - BUNDLE_TYPE: "shared_service" + BUNDLE_DIR: "./templates/shared_services/certs/" + - BUNDLE_TYPE: "shared_service" + BUNDLE_DIR: "./templates/shared_services/cyclecloud/" + - BUNDLE_TYPE: "shared_service" + BUNDLE_DIR: "./templates/shared_services/sonatype-nexus-vm/" + - BUNDLE_TYPE: "shared_service" + BUNDLE_DIR: "./templates/shared_services/databricks-auth/" environment: ${{ inputs.environmentName }} steps: - name: Checkout @@ -590,28 +595,28 @@ jobs: matrix: include: # bundles type can be inferred from the bundle dir (but this is more explicit) - - {BUNDLE_TYPE: "workspace", - BUNDLE_DIR: "./templates/workspaces/base"} - - {BUNDLE_TYPE: "workspace", - BUNDLE_DIR: "./templates/workspaces/unrestricted"} - - {BUNDLE_TYPE: "workspace", - BUNDLE_DIR: "./templates/workspaces/airlock-import-review"} - - {BUNDLE_TYPE: "workspace_service", - BUNDLE_DIR: "./templates/workspace_services/guacamole"} - - {BUNDLE_TYPE: "workspace_service", - BUNDLE_DIR: "./templates/workspace_services/azureml"} - - {BUNDLE_TYPE: "workspace_service", - BUNDLE_DIR: "./templates/workspace_services/gitea"} - - {BUNDLE_TYPE: "workspace_service", - BUNDLE_DIR: "./templates/workspace_services/mysql"} - - {BUNDLE_TYPE: "workspace_service", - BUNDLE_DIR: "./templates/workspace_services/health-services"} - - {BUNDLE_TYPE: "workspace_service", - BUNDLE_DIR: "./templates/workspace_services/databricks"} - - {BUNDLE_TYPE: "workspace_service", - BUNDLE_DIR: "./templates/workspace_services/ohdsi"} - - {BUNDLE_TYPE: "workspace_service", - BUNDLE_DIR: "./templates/workspace_services/azuresql"} + - BUNDLE_TYPE: "workspace" + BUNDLE_DIR: "./templates/workspaces/base" + - BUNDLE_TYPE: "workspace" + BUNDLE_DIR: "./templates/workspaces/unrestricted" + - BUNDLE_TYPE: "workspace" + BUNDLE_DIR: "./templates/workspaces/airlock-import-review" + - BUNDLE_TYPE: "workspace_service" + BUNDLE_DIR: "./templates/workspace_services/guacamole" + - BUNDLE_TYPE: "workspace_service" + BUNDLE_DIR: "./templates/workspace_services/azureml" + - BUNDLE_TYPE: "workspace_service" + BUNDLE_DIR: "./templates/workspace_services/gitea" + - BUNDLE_TYPE: "workspace_service" + BUNDLE_DIR: "./templates/workspace_services/mysql" + - BUNDLE_TYPE: "workspace_service" + BUNDLE_DIR: "./templates/workspace_services/health-services" + - BUNDLE_TYPE: "workspace_service" + BUNDLE_DIR: "./templates/workspace_services/databricks" + - BUNDLE_TYPE: "workspace_service" + BUNDLE_DIR: "./templates/workspace_services/ohdsi" + - BUNDLE_TYPE: "workspace_service" + BUNDLE_DIR: "./templates/workspace_services/azuresql" environment: ${{ inputs.environmentName }} steps: @@ -655,18 +660,18 @@ jobs: strategy: matrix: include: - - {BUNDLE_TYPE: "user_resource", - BUNDLE_DIR: "./templates/workspace_services/guacamole/user_resources/guacamole-azure-windowsvm", - WORKSPACE_SERVICE_NAME: "tre-service-guacamole"} - - {BUNDLE_TYPE: "user_resource", - BUNDLE_DIR: "./templates/workspace_services/guacamole/user_resources/guacamole-azure-linuxvm", - WORKSPACE_SERVICE_NAME: "tre-service-guacamole"} - - {BUNDLE_TYPE: "user_resource", - BUNDLE_DIR: "./templates/workspace_services/guacamole/user_resources/guacamole-azure-export-reviewvm", - WORKSPACE_SERVICE_NAME: "tre-service-guacamole"} - - {BUNDLE_TYPE: "user_resource", - BUNDLE_DIR: "./templates/workspace_services/guacamole/user_resources/guacamole-azure-import-reviewvm", - WORKSPACE_SERVICE_NAME: "tre-service-guacamole"} + - BUNDLE_TYPE: "user_resource" + BUNDLE_DIR: "./templates/workspace_services/guacamole/user_resources/guacamole-azure-windowsvm" + WORKSPACE_SERVICE_NAME: "tre-service-guacamole" + - BUNDLE_TYPE: "user_resource" + BUNDLE_DIR: "./templates/workspace_services/guacamole/user_resources/guacamole-azure-linuxvm" + WORKSPACE_SERVICE_NAME: "tre-service-guacamole" + - BUNDLE_TYPE: "user_resource" + BUNDLE_DIR: "./templates/workspace_services/guacamole/user_resources/guacamole-azure-export-reviewvm" + WORKSPACE_SERVICE_NAME: "tre-service-guacamole" + - BUNDLE_TYPE: "user_resource" + BUNDLE_DIR: "./templates/workspace_services/guacamole/user_resources/guacamole-azure-import-reviewvm" + WORKSPACE_SERVICE_NAME: "tre-service-guacamole" environment: ${{ inputs.environmentName }} steps: - name: Checkout @@ -731,7 +736,6 @@ jobs: TEST_ACCOUNT_CLIENT_SECRET: "${{ secrets.TEST_ACCOUNT_CLIENT_SECRET }}" TRE_ID: ${{ secrets.TRE_ID }} LOCATION: ${{ vars.LOCATION }} - FIREWALL_SKU: ${{ vars.FIREWALL_SKU}} - name: State Store Migrations uses: ./.github/actions/devcontainer_run_command @@ -832,7 +836,8 @@ jobs: if: ${{ inputs.e2eTestsCustomSelector != '' }} runs-on: ubuntu-latest environment: ${{ inputs.environmentName }} - needs: [deploy_shared_services, register_bundles, register_user_resource_bundles] + needs: + [deploy_shared_services, register_bundles, register_user_resource_bundles] timeout-minutes: 300 steps: - name: Checkout diff --git a/CHANGELOG.md b/CHANGELOG.md index ee95c8c7ad..1f05f8ff44 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## 0.24.0 [Unreleased] ENHANCEMENTS: +* Migrate Azure Firewall and Route Tables to Core Terraform ([#4342](https://github.com/microsoft/AzureTRE/pull/4342)) BUG FIXES: * Fix "log analytics workspaces not found" error when deploying Databricks workspace service ([#4585](https://github.com/microsoft/AzureTRE/pull/4585)) diff --git a/Makefile b/Makefile index 7f14180ba7..2a8905e98d 100644 --- a/Makefile +++ b/Makefile @@ -43,12 +43,6 @@ build-and-push-airlock-processor: build-airlock-processor push-airlock-processor help: ## 💬 This help message :) @grep -E '[a-zA-Z_-]+:.*?## .*$$' $(firstword $(MAKEFILE_LIST)) | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-25s\033[0m %s\n", $$1, $$2}' -# Description: Migrate the firewall state from the core deployment to the shared services deployment. -# This is a one-time operation and should only be run when you are moving from the core deployment to the shared services deployment. -# This command will remove the firewall state from the core deployment and import it into the shared services deployment. -# Example: make migrate-firewall-state -migrate-firewall-state: prepare-tf-state - # Description: Bootstrap Terraform # Example: make bootstrap bootstrap: @@ -135,18 +129,6 @@ push-resource-processor-vm-porter-image: push-airlock-processor: $(call push_image,"airlock-processor","${MAKEFILE_DIR}/airlock_processor/_version.py") -# Description: Prepare terraform state for migration -# # These targets are for a graceful migration of Firewall -# # from terraform state in Core to a Shared Service. -# # See https://github.com/microsoft/AzureTRE/issues/1177 -# Example: make prepare-tf-state -prepare-tf-state: - $(call target_title, "Preparing terraform state") \ - && . ${MAKEFILE_DIR}/devops/scripts/check_dependencies.sh nodocker,env \ - && pushd ${MAKEFILE_DIR}/core/terraform > /dev/null && ../../shared_services/firewall/terraform/remove_state.sh && popd > /dev/null \ - && pushd ${MAKEFILE_DIR}/templates/shared_services/firewall/terraform > /dev/null && ./import_state.sh && popd > /dev/null -# / End migration targets - # Description: Deploy the core infrastructure of TRE. # This will create the core resource group (named rg-) with the necessary resources. # Example: make deploy-core @@ -442,8 +424,7 @@ deploy-shared-service: firewall-install: . ${MAKEFILE_DIR}/devops/scripts/check_dependencies.sh env \ && $(MAKE) bundle-build bundle-publish bundle-register deploy-shared-service \ - DIR=${MAKEFILE_DIR}/templates/shared_services/firewall/ BUNDLE_TYPE=shared_service \ - PROPS="$${FIREWALL_SKU+--firewall_sku $${FIREWALL_SKU} }$${FIREWALL_FORCE_TUNNEL_IP+--firewall_force_tunnel_ip $${FIREWALL_FORCE_TUNNEL_IP} }" + DIR=${MAKEFILE_DIR}/templates/shared_services/firewall/ BUNDLE_TYPE=shared_service # Description: Upload the static website to the storage account # Example: make static-web-upload diff --git a/templates/shared_services/firewall/terraform/firewall.tf b/core/terraform/firewall/firewall.tf similarity index 74% rename from templates/shared_services/firewall/terraform/firewall.tf rename to core/terraform/firewall/firewall.tf index 6f4dedc816..d3fc045146 100644 --- a/templates/shared_services/firewall/terraform/firewall.tf +++ b/core/terraform/firewall/firewall.tf @@ -2,10 +2,10 @@ resource "azurerm_public_ip" "fwtransit" { count = var.firewall_force_tunnel_ip != "" ? 0 : 1 name = "pip-fw-${var.tre_id}" resource_group_name = local.core_resource_group_name - location = data.azurerm_resource_group.rg.location + location = var.location allocation_method = "Static" sku = "Standard" - tags = local.tre_shared_service_tags + tags = var.tre_core_tags lifecycle { ignore_changes = [tags, zones] } } @@ -18,27 +18,26 @@ moved { resource "azurerm_public_ip" "fwmanagement" { count = (var.firewall_force_tunnel_ip != "" || local.effective_firewall_sku == "Basic") ? 1 : 0 name = "pip-fw-management-${var.tre_id}" - resource_group_name = local.core_resource_group_name - location = data.azurerm_resource_group.rg.location + resource_group_name = var.resource_group_name + location = var.location allocation_method = "Static" sku = "Standard" - tags = local.tre_shared_service_tags + tags = var.tre_core_tags lifecycle { ignore_changes = [tags, zones] } } - resource "azurerm_firewall" "fw" { name = local.firewall_name resource_group_name = local.core_resource_group_name - location = data.azurerm_resource_group.rg.location + location = var.location sku_tier = local.effective_firewall_sku sku_name = "AZFW_VNet" firewall_policy_id = azurerm_firewall_policy.root.id - tags = local.tre_shared_service_tags + tags = var.tre_core_tags ip_configuration { name = "fw-ip-configuration" - subnet_id = data.azurerm_subnet.firewall.id + subnet_id = var.firewall_subnet_id public_ip_address_id = var.firewall_force_tunnel_ip != "" ? null : azurerm_public_ip.fwtransit[0].id } @@ -46,7 +45,7 @@ resource "azurerm_firewall" "fw" { for_each = (var.firewall_force_tunnel_ip != "" || local.effective_firewall_sku == "Basic") ? [1] : [] content { name = "mgmtconfig" - subnet_id = data.azurerm_subnet.firewall_management.id + subnet_id = var.firewall_management_subnet_id public_ip_address_id = azurerm_public_ip.fwmanagement[0].id } } @@ -61,7 +60,7 @@ data "azurerm_monitor_diagnostic_categories" "firewall" { resource "azurerm_monitor_diagnostic_setting" "firewall" { name = "diagnostics-fw-${var.tre_id}" target_resource_id = azurerm_firewall.fw.id - log_analytics_workspace_id = data.azurerm_log_analytics_workspace.tre.id + log_analytics_workspace_id = var.log_analytics_workspace_id log_analytics_destination_type = "Dedicated" dynamic "enabled_log" { @@ -79,10 +78,10 @@ resource "azurerm_monitor_diagnostic_setting" "firewall" { resource "azurerm_firewall_policy" "root" { name = local.firewall_policy_name - resource_group_name = local.core_resource_group_name - location = data.azurerm_resource_group.rg.location + resource_group_name = var.resource_group_name + location = var.location sku = local.effective_firewall_sku - tags = local.tre_shared_service_tags + tags = var.tre_core_tags lifecycle { ignore_changes = [tags] } } diff --git a/core/terraform/firewall/locals.tf b/core/terraform/firewall/locals.tf new file mode 100644 index 0000000000..478bc7f750 --- /dev/null +++ b/core/terraform/firewall/locals.tf @@ -0,0 +1,24 @@ +locals { + core_resource_group_name = "rg-${var.tre_id}" + firewall_name = "fw-${var.tre_id}" + firewall_diagnostic_categories_enabled = [ + "AZFWApplicationRule", + "AZFWApplicationRuleAggregation", + "AZFWDnsProxy", + "AZFWDnsQuery", + "AZFWFatFlow", + "AZFWFlowTrace", + "AZFWIdpsSignature", + "AZFWInternalFqdnResolutionFailure", + "AZFWNatRule", + "AZFWNatRuleAggregation", + "AZFWNetworkRule", + "AZFWNetworkRuleAggregation", + "AZFWThreatIntel" + ] + + firewall_policy_name = "fw-policy-${var.tre_id}" + + default_firewall_sku = "Standard" + effective_firewall_sku = coalesce(var.firewall_sku, local.default_firewall_sku) +} diff --git a/core/terraform/firewall/main.tf b/core/terraform/firewall/main.tf new file mode 100644 index 0000000000..a4eb095f9c --- /dev/null +++ b/core/terraform/firewall/main.tf @@ -0,0 +1,9 @@ +terraform { + # In modules we should only specify the min version + required_providers { + azurerm = { + source = "hashicorp/azurerm" + version = ">= 3.117" + } + } +} diff --git a/core/terraform/firewall/outputs.tf b/core/terraform/firewall/outputs.tf new file mode 100644 index 0000000000..f765318766 --- /dev/null +++ b/core/terraform/firewall/outputs.tf @@ -0,0 +1,7 @@ +output "private_ip_address" { + value = azurerm_firewall.fw.ip_configuration[0].private_ip_address +} + +output "firewall_policy_id" { + value = azurerm_firewall_policy.root.id +} diff --git a/core/terraform/firewall/rules.tf b/core/terraform/firewall/rules.tf new file mode 100644 index 0000000000..da27f04121 --- /dev/null +++ b/core/terraform/firewall/rules.tf @@ -0,0 +1,197 @@ +resource "azurerm_firewall_policy_rule_collection_group" "core" { + name = "rcg-core" + firewall_policy_id = azurerm_firewall_policy.root.id + priority = 500 + + network_rule_collection { + name = "nrc-general" + priority = 201 + action = "Allow" + + rule { + name = "time" + protocols = [ + "UDP" + ] + destination_addresses = [ + "*" + ] + destination_ports = [ + "123" + ] + source_addresses = [ + "*" + ] + } + } + + network_rule_collection { + name = "nrc-resource-processor-subnet" + priority = 202 + action = "Allow" + + rule { + name = "azure-services" + protocols = [ + "TCP" + ] + destination_addresses = [ + "AzureActiveDirectory", + "AzureResourceManager", + + // Needed when a workspace key vault is created before its private endpoint + "AzureKeyVault.${var.location}" + ] + destination_ports = [ + "443" + ] + source_ip_groups = [var.resource_processor_ip_group_id] + } + } + + network_rule_collection { + name = "nrc-web-app-subnet" + priority = 203 + action = "Allow" + + rule { + name = "azure-services" + protocols = [ + "TCP" + ] + destination_addresses = [ + "AzureActiveDirectory", + "AzureResourceManager" + ] + destination_ports = [ + "443" + ] + source_ip_groups = [var.web_app_ip_group_id] + } + } + + application_rule_collection { + name = "arc-resource-processor-subnet" + priority = 301 + action = "Allow" + + rule { + name = "os-package-sources" + protocols { + port = "443" + type = "Https" + } + protocols { + port = "80" + type = "Http" + } + destination_fqdns = [ + "packages.microsoft.com", + "keyserver.ubuntu.com", + "api.snapcraft.io", + "azure.archive.ubuntu.com", + "security.ubuntu.com", + "entropy.ubuntu.com", + ] + source_ip_groups = [var.resource_processor_ip_group_id] + } + + rule { + name = "docker-sources" + protocols { + port = "443" + type = "Https" + } + protocols { + port = "80" + type = "Http" + } + destination_fqdns = [ + "download.docker.com", + "registry-1.docker.io", + "auth.docker.io", + ] + source_ip_groups = [var.resource_processor_ip_group_id] + } + # This rule is needed to support Gov Cloud. + # The az cli uses msal lib which requires access to this fqdn for authentication. + rule { + name = "microsoft-login" + protocols { + port = "443" + type = "Https" + } + destination_fqdns = [ + "login.microsoftonline.com", + ] + source_ip_groups = [var.resource_processor_ip_group_id] + } + + + } + + application_rule_collection { + name = "arc-shared-subnet" + priority = 302 + action = "Allow" + + rule { + name = "nexus-bootstrap" + protocols { + port = "443" + type = "Https" + } + protocols { + port = "80" + type = "Http" + } + destination_fqdns = [ + "keyserver.ubuntu.com", + "packages.microsoft.com", + "download.docker.com", + "azure.archive.ubuntu.com" + ] + source_ip_groups = [var.shared_services_ip_group_id] + } + } + + application_rule_collection { + name = "arc-web-app-subnet" + priority = 303 + action = "Allow" + + rule { + name = "microsoft-graph" + protocols { + port = "443" + type = "Https" + } + destination_fqdns = [ + var.microsoft_graph_fqdn + ] + source_ip_groups = [var.web_app_ip_group_id] + } + } + + application_rule_collection { + name = "arc-airlock-processor-subnet" + priority = 304 + action = "Allow" + + rule { + name = "functions-runtime" + protocols { + port = "443" + type = "Https" + } + destination_fqdns = [ + "functionscdn.azureedge.net" + ] + source_ip_groups = [var.airlock_processor_ip_group_id] + } + } + + depends_on = [ + azurerm_firewall.fw + ] +} diff --git a/core/terraform/firewall/variables.tf b/core/terraform/firewall/variables.tf new file mode 100644 index 0000000000..458bd0bf1e --- /dev/null +++ b/core/terraform/firewall/variables.tf @@ -0,0 +1,66 @@ +variable "tre_id" { + type = string + description = "Unique TRE ID" +} + +variable "location" { + type = string +} + +variable "resource_group_name" { + type = string +} + +variable "firewall_sku" { + type = string + default = "" +} + +variable "firewall_subnet_id" { + type = string + description = "Subnet ID for the firewall" +} + +variable "firewall_management_subnet_id" { + type = string + description = "Subnet ID for the firewall management" +} + +variable "firewall_force_tunnel_ip" { + type = string + default = "" +} + +variable "tre_core_tags" { + type = map(string) + description = "Tags to apply to all resources" +} + +variable "microsoft_graph_fqdn" { + type = string + description = "Microsoft Graph FQDN" +} + +variable "log_analytics_workspace_id" { + type = string +} + +variable "resource_processor_ip_group_id" { + type = string + description = "Resource Processor IP Group" +} + +variable "web_app_ip_group_id" { + type = string + description = "Web App IP Group" +} + +variable "airlock_processor_ip_group_id" { + type = string + description = "Airlock Processor IP Group" +} + +variable "shared_services_ip_group_id" { + type = string + description = "Shared Services IP Group" +} diff --git a/core/terraform/main.tf b/core/terraform/main.tf index 28f360a1f5..846ac91643 100644 --- a/core/terraform/main.tf +++ b/core/terraform/main.tf @@ -92,6 +92,24 @@ module "network" { arm_environment = var.arm_environment } +module "firewall" { + source = "./firewall" + tre_id = var.tre_id + firewall_sku = var.firewall_sku + firewall_subnet_id = module.network.azure_firewall_subnet_id + firewall_force_tunnel_ip = var.firewall_force_tunnel_ip + location = var.location + resource_group_name = azurerm_resource_group.core.name + tre_core_tags = local.tre_core_tags + microsoft_graph_fqdn = regex("(?:(?P[^:/?#]+):)?(?://(?P[^/?#:]*))?", module.terraform_azurerm_environment_configuration.microsoft_graph_endpoint).fqdn + log_analytics_workspace_id = module.azure_monitor.log_analytics_workspace_id + firewall_management_subnet_id = module.network.firewall_management_subnet_id + resource_processor_ip_group_id = module.network.resource_processor_ip_group_id + shared_services_ip_group_id = module.network.shared_services_ip_group_id + web_app_ip_group_id = module.network.web_app_ip_group_id + airlock_processor_ip_group_id = module.network.airlock_processor_ip_group_id +} + module "appgateway" { source = "./appgateway" tre_id = var.tre_id @@ -186,7 +204,6 @@ module "resource_processor_vmss_porter" { resource_processor_vmss_sku = var.resource_processor_vmss_sku arm_environment = var.arm_environment logging_level = var.logging_level - firewall_sku = var.firewall_sku rp_bundle_values = var.rp_bundle_values enable_cmk_encryption = var.enable_cmk_encryption key_store_id = local.key_store_id @@ -195,6 +212,7 @@ module "resource_processor_vmss_porter" { auto_grant_workspace_consent = var.auto_grant_workspace_consent enable_airlock_malware_scanning = var.enable_airlock_malware_scanning airlock_malware_scan_result_topic_name = module.airlock_resources.airlock_malware_scan_result_topic_name + firewall_policy_id = module.firewall.firewall_policy_id depends_on = [ module.network, diff --git a/core/terraform/migrate.sh b/core/terraform/migrate.sh index 46b9c85504..92884efcd7 100755 --- a/core/terraform/migrate.sh +++ b/core/terraform/migrate.sh @@ -19,6 +19,64 @@ get_resource_id() { ' } +# Remove a resource from the Terraform state if it exists in the state +function remove_if_present() { + echo -n "Checking $1 ..." + ESCAPED_ADDRESS=$(printf '%q' "${1}") + found=$(echo "$tf_state_list" | grep -q ^"$ESCAPED_ADDRESS"$; echo $?) + + if [[ $found -eq 0 ]]; then + echo " removing" + terraform state rm "$1" + else + echo " not present" + fi +} + +# Import a resource if it exists in Azure but doesn't exist in Terraform +function import_if_exists() { + ADDRESS=$1 + ID=$2 + + # Check if the resource exists in Terraform + echo "Checking if ${ADDRESS} exists in Terraform state..." + ESCAPED_ADDRESS=$(printf '%q' "${ADDRESS}") + TF_RESOURCE_EXISTS=$(echo "$tf_state_list" | grep -q ^"${ESCAPED_ADDRESS}"$; echo $?) + + if [[ ${TF_RESOURCE_EXISTS} -eq 0 ]]; then + echo "${ADDRESS} already in TF State, ignoring..." + return + fi + + # Some resources, e.g. Firewall rules and Diagnostics, don't show up in `az resource show`, + # so we need a way to set up a custom command for them + if [[ $# -eq 3 ]]; then + # If a command is provided, use it to check if the resource exists in Azure + CMD=$3 + else + # Default command to check if the resource exists in Azure + CMD="az resource show --ids ${ID}" + fi + + echo "Checking if ${ADDRESS} exists in Azure..." + # Temporarily disable errexit to capture command failure + set +o errexit + ${CMD} > /dev/null + AZ_RESOURCE_EXISTS=$? + set -o errexit # Restore errexit + + + # If resource exists in Terraform, it's already managed -- don't do anything + # If resource doesn't exist in Terraform and doesn't exist in Azure, it will be created -- don't do anything + # If resource doesn't exist in Terraform but exist in Azure, we need to import it + if [[ ${TF_RESOURCE_EXISTS} -ne 0 && ${AZ_RESOURCE_EXISTS} -eq 0 ]]; then + echo "IMPORTING ${ADDRESS} ${ID}" + terraform import -var "tre_id=${TRE_ID}" -var "location=${LOCATION}" "${ADDRESS}" "${ID}" + else + echo "Resource ${ADDRESS} does not exist in Azure or is already managed by Terraform, skipping import." + fi +} + # Configure AzureRM provider to use Azure AD to connect to storage accounts export ARM_STORAGE_USE_AZUREAD=true @@ -34,6 +92,8 @@ terraform init -input=false -backend=true -reconfigure \ -backend-config="container_name=${TF_VAR_terraform_state_container_name}" \ -backend-config="key=${TRE_ID}" +tf_state_list="$(terraform state list)" + echo "*** Migrating TF Resources... ***" terraform refresh @@ -101,3 +161,79 @@ else echo "No old resources found in the state, skipping migration." echo "*** Migration Skipped ***" fi + + + +# Remove the firewall adn other resources from the shared service state and import it into the core state. +# https://github.com/microsoft/AzureTRE/pull/4342 +echo "REMOVING STATE FOR FIREWALL..." + +pushd ../../templates/shared_services/firewall/terraform + +# shellcheck disable=SC1091 +terraform init -input=false -backend=true -reconfigure -upgrade \ + -backend-config="resource_group_name=${TF_VAR_mgmt_resource_group_name}" \ + -backend-config="storage_account_name=${TF_VAR_mgmt_storage_account_name}" \ + -backend-config="container_name=${TF_VAR_terraform_state_container_name}" \ + -backend-config="key=${TRE_ID}-shared-service-firewall" + +tf_state_list="$(terraform state list)" + +# routetable.tf +remove_if_present azurerm_route_table.rt +remove_if_present azurerm_subnet_route_table_association.rt_shared_subnet_association +remove_if_present azurerm_subnet_route_table_association.rt_resource_processor_subnet_association +remove_if_present azurerm_subnet_route_table_association.rt_web_app_subnet_association +remove_if_present azurerm_subnet_route_table_association.rt_airlock_processor_subnet_association +remove_if_present azurerm_subnet_route_table_association.rt_airlock_storage_subnet_association +remove_if_present azurerm_subnet_route_table_association.rt_airlock_events_subnet_association + +# rules.tf +remove_if_present azurerm_firewall_network_rule_collection.core + +# firewall.tf +remove_if_present azurerm_public_ip.fwtransit[0] +remove_if_present azurerm_public_ip.fwmanagement[0] +remove_if_present azurerm_firewall.fw +remove_if_present azurerm_monitor_diagnostic_categories.firewall +remove_if_present azurerm_monitor_diagnostic_setting.firewall +remove_if_present azurerm_firewall_policy_rule_collection_group.core +remove_if_present azurerm_firewall_policy.root + +popd > /dev/null + + +echo "IMPORTING STATE FOR FIREWALL..." + +tf_state_list="$(terraform state list)" +RESOURCE_GROUP_NAME="rg-${TRE_ID}" + +# if resource group exists +if az group show --name "${RESOURCE_GROUP_NAME}" > /dev/null 2>&1; then + echo "Resource group ${RESOURCE_GROUP_NAME} exists, proceeding with import." + + # Firewall + import_if_exists module.firewall.azurerm_firewall.fw "/subscriptions/${ARM_SUBSCRIPTION_ID}/resourceGroups/${RESOURCE_GROUP_NAME}/providers/Microsoft.Network/azureFirewalls/fw-${TRE_ID}" + + # Firewall IPs + if [[ "${FIREWALL_SKU:-}" == "Basic" ]]; then + import_if_exists module.firewall.azurerm_public_ip.fwmanagement[0] "/subscriptions/${ARM_SUBSCRIPTION_ID}/resourceGroups/${RESOURCE_GROUP_NAME}/providers/Microsoft.Network/publicIPAddresses/pip-fw-management-${TRE_ID}" + fi + + import_if_exists module.firewall.azurerm_public_ip.fwtransit[0] "/subscriptions/${ARM_SUBSCRIPTION_ID}/resourceGroups/${RESOURCE_GROUP_NAME}/providers/Microsoft.Network/publicIPAddresses/pip-fw-${TRE_ID}" + + # Firewall policy + import_if_exists module.firewall.azurerm_firewall_policy.root "/subscriptions/${ARM_SUBSCRIPTION_ID}/resourceGroups/${RESOURCE_GROUP_NAME}/providers/Microsoft.Network/firewallPolicies/fw-policy-${TRE_ID}" + import_if_exists module.firewall.azurerm_firewall_policy_rule_collection_group.core \ + "/subscriptions/${ARM_SUBSCRIPTION_ID}/resourceGroups/${RESOURCE_GROUP_NAME}/providers/Microsoft.Network/firewallPolicies/fw-policy-${TRE_ID}/ruleCollectionGroups/rcg-core" + + + # Diagnostic settings + import_if_exists module.firewall.azurerm_monitor_diagnostic_setting.firewall \ + "/subscriptions/${ARM_SUBSCRIPTION_ID}/resourceGroups/${RESOURCE_GROUP_NAME}/providers/Microsoft.Network/azureFirewalls/fw-${TRE_ID}|diagnostics-fw-${TRE_ID}" \ + "az monitor diagnostic-settings show --resource /subscriptions/${ARM_SUBSCRIPTION_ID}/resourceGroups/rg-${TRE_ID}/providers/microsoft.network/azureFirewalls/fw-${TRE_ID} --name diagnostics-fw-${TRE_ID}" + + # Route tables + import_if_exists azurerm_route_table.rt \ + "/subscriptions/${ARM_SUBSCRIPTION_ID}/resourceGroups/${RESOURCE_GROUP_NAME}/providers/Microsoft.Network/routeTables/rt-${TRE_ID}" +fi diff --git a/core/terraform/network/outputs.tf b/core/terraform/network/outputs.tf index 001af6aad1..7153ddbf70 100644 --- a/core/terraform/network/outputs.tf +++ b/core/terraform/network/outputs.tf @@ -10,6 +10,10 @@ output "azure_firewall_subnet_id" { value = "${azurerm_virtual_network.core.id}/subnets/AzureFirewallSubnet" } +output "firewall_management_subnet_id" { + value = "${azurerm_virtual_network.core.id}/subnets/AzureFirewallManagementSubnet" +} + output "app_gw_subnet_id" { value = "${azurerm_virtual_network.core.id}/subnets/AppGwSubnet" } @@ -91,3 +95,21 @@ output "eventgrid_private_dns_zone_id" { output "azurecr_dns_zone_id" { value = azurerm_private_dns_zone.azurecr.id } + +# IP Groups +output "resource_processor_ip_group_id" { + value = azurerm_ip_group.resource_processor.id +} + +output "shared_services_ip_group_id" { + value = azurerm_ip_group.shared.id +} + +output "airlock_processor_ip_group_id" { + value = azurerm_ip_group.airlock_processor.id +} + +output "web_app_ip_group_id" { + value = azurerm_ip_group.webapp.id +} + diff --git a/core/terraform/resource_processor/vmss_porter/locals.tf b/core/terraform/resource_processor/vmss_porter/locals.tf index ab6b69ff55..80067c4b68 100644 --- a/core/terraform/resource_processor/vmss_porter/locals.tf +++ b/core/terraform/resource_processor/vmss_porter/locals.tf @@ -13,7 +13,6 @@ locals { rp_bundle_values_all = merge(var.rp_bundle_values, { // Add any additional settings like ones from the config.yaml here // to make them available for bundles. - firewall_sku = var.firewall_sku enable_cmk_encryption = var.enable_cmk_encryption key_store_id = var.key_store_id ui_client_id = var.ui_client_id @@ -21,6 +20,7 @@ locals { enable_airlock_malware_scanning = var.enable_airlock_malware_scanning airlock_malware_scan_result_topic_name = var.airlock_malware_scan_result_topic_name core_api_client_id = var.core_api_client_id + firewall_policy_id = var.firewall_policy_id }) rp_bundle_values_dic = [for key in keys(local.rp_bundle_values_all) : "RP_BUNDLE_${key}=${local.rp_bundle_values_all[key]}"] rp_bundle_values_formatted = join("\n ", local.rp_bundle_values_dic) diff --git a/core/terraform/resource_processor/vmss_porter/variables.tf b/core/terraform/resource_processor/vmss_porter/variables.tf index a87b3cd3c2..342c27b207 100644 --- a/core/terraform/resource_processor/vmss_porter/variables.tf +++ b/core/terraform/resource_processor/vmss_porter/variables.tf @@ -75,9 +75,6 @@ variable "subscription_id" { variable "logging_level" { type = string } -variable "firewall_sku" { - type = string -} variable "rp_bundle_values" { type = map(string) } @@ -122,3 +119,8 @@ variable "mgmt_storage_account_id" { type = string description = "ID of the management storage account" } + +variable "firewall_policy_id" { + type = string + description = "ID of the firewall policy to use for the resource processor" +} diff --git a/core/terraform/routetable.tf b/core/terraform/routetable.tf new file mode 100644 index 0000000000..3901b521eb --- /dev/null +++ b/core/terraform/routetable.tf @@ -0,0 +1,95 @@ +resource "azurerm_route_table" "rt" { + name = "rt-${var.tre_id}" + resource_group_name = azurerm_resource_group.core.name + location = var.location + tags = local.tre_core_tags + + lifecycle { ignore_changes = [tags] } + + route { + name = "DefaultRoute" + address_prefix = "0.0.0.0/0" + next_hop_type = "VirtualAppliance" + next_hop_in_ip_address = module.firewall.private_ip_address + } +} + +resource "azurerm_subnet_route_table_association" "rt_shared_subnet_association" { + subnet_id = module.network.shared_subnet_id + route_table_id = azurerm_route_table.rt.id + + depends_on = [ + module.firewall + ] +} + +resource "azurerm_subnet_route_table_association" "rt_resource_processor_subnet_association" { + subnet_id = module.network.resource_processor_subnet_id + route_table_id = azurerm_route_table.rt.id + + # Not waiting for the rules will block traffic prematurally. + depends_on = [ + module.firewall + ] +} + +resource "azurerm_subnet_route_table_association" "rt_web_app_subnet_association" { + subnet_id = module.network.web_app_subnet_id + route_table_id = azurerm_route_table.rt.id + + depends_on = [ + module.firewall + ] +} + +resource "azurerm_subnet_route_table_association" "rt_airlock_processor_subnet_association" { + subnet_id = module.network.airlock_processor_subnet_id + route_table_id = azurerm_route_table.rt.id + + depends_on = [ + module.firewall + ] +} + +resource "azurerm_subnet_route_table_association" "rt_airlock_storage_subnet_association" { + subnet_id = module.network.airlock_storage_subnet_id + route_table_id = azurerm_route_table.rt.id + + depends_on = [ + module.firewall + ] +} + +resource "azurerm_subnet_route_table_association" "rt_airlock_events_subnet_association" { + subnet_id = module.network.airlock_events_subnet_id + route_table_id = azurerm_route_table.rt.id + + depends_on = [ + module.firewall + ] +} + + +resource "azurerm_route_table" "fw_tunnel_rt" { + count = var.firewall_force_tunnel_ip != "" ? 1 : 0 + name = "rt-fw-tunnel-${var.tre_id}" + resource_group_name = azurerm_resource_group.core.name + location = azurerm_resource_group.core.location + bgp_route_propagation_enabled = true + tags = local.tre_core_tags + lifecycle { ignore_changes = [tags] } + + route { + name = "ForceTunnelRoute" + address_prefix = "0.0.0.0/0" + next_hop_type = "VirtualAppliance" + next_hop_in_ip_address = var.firewall_force_tunnel_ip + } +} + +resource "azurerm_subnet_route_table_association" "rt_fw_tunnel_subnet_association" { + count = var.firewall_force_tunnel_ip != "" ? 1 : 0 + subnet_id = module.network.azure_firewall_subnet_id + route_table_id = azurerm_route_table.fw_tunnel_rt[0].id +} + diff --git a/core/terraform/variables.tf b/core/terraform/variables.tf index 3617323438..e813751745 100644 --- a/core/terraform/variables.tf +++ b/core/terraform/variables.tf @@ -186,6 +186,11 @@ variable "firewall_sku" { default = "" } +variable "firewall_force_tunnel_ip" { + type = string + default = "" +} + variable "app_gateway_sku" { description = "Application Gateway SKU" type = string diff --git a/core/version.txt b/core/version.txt index 903e77ce1b..5a313cc7ef 100644 --- a/core/version.txt +++ b/core/version.txt @@ -1 +1 @@ -__version__ = "0.15.1" +__version__ = "0.16.0" diff --git a/resource_processor/_version.py b/resource_processor/_version.py index 6dd4954d0d..8e377d6b3f 100644 --- a/resource_processor/_version.py +++ b/resource_processor/_version.py @@ -1 +1 @@ -__version__ = "0.12.4" +__version__ = "0.12.5" diff --git a/templates/shared_services/firewall/parameters.json b/templates/shared_services/firewall/parameters.json index 6a1df98da8..36029b65a3 100755 --- a/templates/shared_services/firewall/parameters.json +++ b/templates/shared_services/firewall/parameters.json @@ -46,12 +46,6 @@ "env": "NETWORK_RULE_COLLECTIONS" } }, - { - "name": "firewall_sku", - "source": { - "env": "FIREWALL_SKU" - } - }, { "name": "microsoft_graph_fqdn", "source": { diff --git a/templates/shared_services/firewall/porter.yaml b/templates/shared_services/firewall/porter.yaml index 50143f6bb2..0e80f1699d 100644 --- a/templates/shared_services/firewall/porter.yaml +++ b/templates/shared_services/firewall/porter.yaml @@ -1,7 +1,7 @@ --- schemaVersion: 1.0.0 name: tre-shared-service-firewall -version: 1.4.1 +version: 1.5.0 description: "An Azure TRE Firewall shared service" dockerfile: Dockerfile.tmpl registry: azuretre @@ -37,6 +37,9 @@ parameters: env: ARM_USE_MSI type: boolean default: false + - name: firewall_policy_id + type: string + description: "The ID of the Azure Firewall Policy to use" - name: rule_collections type: string default: "W10=" # b64 for [] @@ -45,18 +48,8 @@ parameters: type: string default: "W10=" # b64 for [] description: "Network rule collection array" - - name: firewall_sku - type: string - default: Standard - description: The firewall and its policy SKU tier - - name: microsoft_graph_fqdn - type: string - default: "graph.microsoft.com" - name: arm_environment type: string - - name: firewall_force_tunnel_ip - type: string - default: "" mixins: - terraform: @@ -67,12 +60,9 @@ install: description: "Deploy shared service" vars: tre_id: ${ bundle.parameters.tre_id } - tre_resource_id: ${ bundle.parameters.id } + firewall_policy_id: ${ bundle.parameters.firewall_policy_id } api_driven_rule_collections_b64: ${ bundle.parameters.rule_collections } api_driven_network_rule_collections_b64: ${ bundle.parameters.network_rule_collections } - firewall_sku: ${ bundle.parameters.firewall_sku } - microsoft_graph_fqdn: ${ bundle.parameters.microsoft_graph_fqdn } - firewall_force_tunnel_ip: ${ bundle.parameters.firewall_force_tunnel_ip } backendConfig: use_azuread_auth: "true" use_oidc: "true" @@ -86,12 +76,9 @@ upgrade: description: "Upgrade shared service" vars: tre_id: ${ bundle.parameters.tre_id } - tre_resource_id: ${ bundle.parameters.id } + firewall_policy_id: ${ bundle.parameters.firewall_policy_id } api_driven_rule_collections_b64: ${ bundle.parameters.rule_collections } api_driven_network_rule_collections_b64: ${ bundle.parameters.network_rule_collections } - firewall_sku: ${ bundle.parameters.firewall_sku } - microsoft_graph_fqdn: ${ bundle.parameters.microsoft_graph_fqdn } - firewall_force_tunnel_ip: ${ bundle.parameters.firewall_force_tunnel_ip } backendConfig: use_azuread_auth: "true" use_oidc: "true" @@ -105,12 +92,9 @@ uninstall: description: "Tear down shared service" vars: tre_id: ${ bundle.parameters.tre_id } - tre_resource_id: ${ bundle.parameters.id } + firewall_policy_id: ${ bundle.parameters.firewall_policy_id } api_driven_rule_collections_b64: ${ bundle.parameters.rule_collections } api_driven_network_rule_collections_b64: ${ bundle.parameters.network_rule_collections } - firewall_sku: ${ bundle.parameters.firewall_sku } - microsoft_graph_fqdn: ${ bundle.parameters.microsoft_graph_fqdn } - firewall_force_tunnel_ip: ${ bundle.parameters.firewall_force_tunnel_ip } backendConfig: use_azuread_auth: "true" use_oidc: "true" diff --git a/templates/shared_services/firewall/template_schema.json b/templates/shared_services/firewall/template_schema.json index 23b0f8a526..c92f7544c8 100644 --- a/templates/shared_services/firewall/template_schema.json +++ b/templates/shared_services/firewall/template_schema.json @@ -6,22 +6,6 @@ "description": "Provides Firewall shared service", "required": [], "properties": { - "firewall_sku": { - "type": "string", - "title": "Firewall SKU", - "description": "The SKU that will be used when deploying The Firewall.", - "default": "Standard", - "enum": [ - "Basic", - "Standard", - "Premium" - ] - }, - "firewall_force_tunnel_ip": { - "type": "string", - "title": "Force Tunnel IP", - "description": "Optionally specify an IP address to forward all traffic to" - }, "rule_collections": { "$id": "#properties/rule_collections", "title": "application rule collections", diff --git a/templates/shared_services/firewall/terraform/data.tf b/templates/shared_services/firewall/terraform/data.tf index 8eb3d9da07..8138a2563f 100644 --- a/templates/shared_services/firewall/terraform/data.tf +++ b/templates/shared_services/firewall/terraform/data.tf @@ -1,80 +1,3 @@ -data "azurerm_subnet" "firewall" { - name = "AzureFirewallSubnet" - virtual_network_name = "vnet-${var.tre_id}" - resource_group_name = local.core_resource_group_name -} - -data "azurerm_subnet" "firewall_management" { - name = "AzureFirewallManagementSubnet" - virtual_network_name = "vnet-${var.tre_id}" - resource_group_name = local.core_resource_group_name -} - -data "azurerm_subnet" "shared" { - name = "SharedSubnet" - virtual_network_name = "vnet-${var.tre_id}" - resource_group_name = local.core_resource_group_name -} - -data "azurerm_subnet" "resource_processor" { - name = "ResourceProcessorSubnet" - virtual_network_name = "vnet-${var.tre_id}" - resource_group_name = local.core_resource_group_name -} - -data "azurerm_subnet" "web_app" { - name = "WebAppSubnet" - virtual_network_name = "vnet-${var.tre_id}" - resource_group_name = local.core_resource_group_name -} - -data "azurerm_subnet" "airlock_processor" { - name = "AirlockProcessorSubnet" - virtual_network_name = "vnet-${var.tre_id}" - resource_group_name = local.core_resource_group_name -} - -data "azurerm_subnet" "airlock_storage" { - name = "AirlockStorageSubnet" - virtual_network_name = "vnet-${var.tre_id}" - resource_group_name = local.core_resource_group_name -} - -data "azurerm_subnet" "airlock_events" { - name = "AirlockEventsSubnet" - virtual_network_name = "vnet-${var.tre_id}" - resource_group_name = local.core_resource_group_name -} - -data "azurerm_log_analytics_workspace" "tre" { - name = "log-${var.tre_id}" - resource_group_name = local.core_resource_group_name -} - -data "azurerm_resource_group" "rg" { - name = local.core_resource_group_name -} - -data "azurerm_ip_group" "resource_processor" { - name = "ipg-resource-processor" - resource_group_name = local.core_resource_group_name -} - -data "azurerm_ip_group" "shared" { - name = "ipg-shared" - resource_group_name = local.core_resource_group_name -} - -data "azurerm_ip_group" "web" { - name = "ipg-web-app" - resource_group_name = local.core_resource_group_name -} - -data "azurerm_ip_group" "airlock_processor" { - name = "ipg-airlock-processor" - resource_group_name = local.core_resource_group_name -} - data "azurerm_ip_group" "referenced" { for_each = toset(distinct(flatten( [for collection in concat(local.api_driven_network_rule_collection, local.api_driven_application_rule_collection) : diff --git a/templates/shared_services/firewall/terraform/import_state.sh b/templates/shared_services/firewall/terraform/import_state.sh deleted file mode 100755 index ea27f7d513..0000000000 --- a/templates/shared_services/firewall/terraform/import_state.sh +++ /dev/null @@ -1,104 +0,0 @@ -#!/bin/bash -# shellcheck disable=SC2154 - -# See remove_state.sh for the purpose of these scripts -echo "IMPORTING STATE FOR FIREWALL..." - -# check for the existence of the RG. If it's not there it's because we're in CI and building from scratch - we can skip this script -set +e -RESOURCE_GROUP_ID="rg-${TRE_ID}" -if ! az group show -n "$RESOURCE_GROUP_ID"; then - echo "RG not found, skipping import_state" - exit 0 -fi - -set -e - -# Initialise state for Terraform -terraform init -input=false -backend=true -reconfigure -upgrade \ - -backend-config="resource_group_name=${TF_VAR_mgmt_resource_group_name}" \ - -backend-config="storage_account_name=${TF_VAR_mgmt_storage_account_name}" \ - -backend-config="container_name=${TF_VAR_terraform_state_container_name}" \ - -backend-config="key=${TRE_ID}-shared-service-firewall" - -# Import a resource if it exists in Azure but doesn't exist in Terraform -tf_state_list="$(terraform state list)" -function import_if_exists() { - ADDRESS=$1 - ID=$2 - CMD=$3 - - # Check if the resource exists in Terraform - TF_RESOURCE_EXISTS=$(echo "$tf_state_list" | grep -q ^"${ADDRESS}"$; echo $?) - - if [[ ${TF_RESOURCE_EXISTS} -eq 0 ]]; then - echo "${ADDRESS} already in TF State, ignoring..." - return - fi - - # Some resources, e.g. Firewall rules and Diagnostics, don't show up in `az resource show`, - # so we need a way to set up a custom command for them - if [[ -z ${CMD} ]]; then - CMD="az resource show --ids ${ID}" - fi - ${CMD} > /dev/null - AZ_RESOURCE_EXISTS=$? - - # If resource exists in Terraform, it's already managed -- don't do anything - # If resource doesn't exist in Terraform and doesn't exist in Azure, it will be created -- don't do anything - # If resource doesn't exist in Terraform but exist in Azure, we need to import it - if [[ ${TF_RESOURCE_EXISTS} -ne 0 && ${AZ_RESOURCE_EXISTS} -eq 0 ]]; then - echo "IMPORTING ${ADDRESS} ${ID}" - terraform import -var "tre_id=${TRE_ID}" -var "location=${LOCATION}" "${ADDRESS}" "${ID}" - fi -} - -import_if_exists azurerm_firewall.fw "/subscriptions/${ARM_SUBSCRIPTION_ID}/resourceGroups/${RESOURCE_GROUP_ID}/providers/Microsoft.Network/azureFirewalls/fw-${TRE_ID}" || echo "Resource already exists" - -# Firewall rules -import_if_exists azurerm_firewall_application_rule_collection.resource_processor_subnet \ - "/subscriptions/${ARM_SUBSCRIPTION_ID}/resourceGroups/${RESOURCE_GROUP_ID}/providers/Microsoft.Network/azureFirewalls/fw-${TRE_ID}/applicationRuleCollections/arc-resource_processor_subnet" \ - "az network firewall show --ids /subscriptions/${ARM_SUBSCRIPTION_ID}/resourceGroups/${RESOURCE_GROUP_ID}/providers/Microsoft.Network/azureFirewalls/fw-${TRE_ID}/applicationRuleCollections/arc-resource_processor_subnet" - -import_if_exists azurerm_firewall_application_rule_collection.shared_subnet \ - "/subscriptions/${ARM_SUBSCRIPTION_ID}/resourceGroups/${RESOURCE_GROUP_ID}/providers/Microsoft.Network/azureFirewalls/fw-${TRE_ID}/applicationRuleCollections/arc-shared_subnet" \ - "az network firewall show --ids /subscriptions/${ARM_SUBSCRIPTION_ID}/resourceGroups/${RESOURCE_GROUP_ID}/providers/Microsoft.Network/azureFirewalls/fw-${TRE_ID}/applicationRuleCollections/arc-shared_subnet" - -import_if_exists azurerm_firewall_application_rule_collection.web_app_subnet \ - "/subscriptions/${ARM_SUBSCRIPTION_ID}/resourceGroups/${RESOURCE_GROUP_ID}/providers/Microsoft.Network/azureFirewalls/fw-${TRE_ID}/applicationRuleCollections/arc-web_app_subnet" \ - "az network firewall show --ids /subscriptions/${ARM_SUBSCRIPTION_ID}/resourceGroups/${RESOURCE_GROUP_ID}/providers/Microsoft.Network/azureFirewalls/fw-${TRE_ID}/applicationRuleCollections/arc-web_app_subnet" - -import_if_exists azurerm_firewall_network_rule_collection.general \ - "/subscriptions/${ARM_SUBSCRIPTION_ID}/resourceGroups/${RESOURCE_GROUP_ID}/providers/Microsoft.Network/azureFirewalls/fw-${TRE_ID}/networkRuleCollections/general" \ - "az network firewall show --ids /subscriptions/${ARM_SUBSCRIPTION_ID}/resourceGroups/${RESOURCE_GROUP_ID}/providers/Microsoft.Network/azureFirewalls/fw-${TRE_ID}/networkRuleCollections/general" - -import_if_exists azurerm_firewall_network_rule_collection.resource_processor_subnet \ - "/subscriptions/${ARM_SUBSCRIPTION_ID}/resourceGroups/${RESOURCE_GROUP_ID}/providers/Microsoft.Network/azureFirewalls/fw-${TRE_ID}/networkRuleCollections/nrc-resource_processor_subnet" \ - "az network firewall show --ids /subscriptions/${ARM_SUBSCRIPTION_ID}/resourceGroups/${RESOURCE_GROUP_ID}/providers/Microsoft.Network/azureFirewalls/fw-${TRE_ID}/networkRuleCollections/nrc-resource_processor_subnet" - -import_if_exists azurerm_firewall_network_rule_collection.web_app_subnet \ - "/subscriptions/${ARM_SUBSCRIPTION_ID}/resourceGroups/${RESOURCE_GROUP_ID}/providers/Microsoft.Network/azureFirewalls/fw-${TRE_ID}/networkRuleCollections/nrc-web_app_subnet" \ - "az network firewall show --ids /subscriptions/${ARM_SUBSCRIPTION_ID}/resourceGroups/${RESOURCE_GROUP_ID}/providers/Microsoft.Network/azureFirewalls/fw-${TRE_ID}/networkRuleCollections/nrc-web_app_subnet" - - -# Diagnostic settings -import_if_exists azurerm_monitor_diagnostic_setting.firewall \ - "/subscriptions/${ARM_SUBSCRIPTION_ID}/resourceGroups/${RESOURCE_GROUP_ID}/providers/Microsoft.Network/azureFirewalls/fw-${TRE_ID}|diagnostics-firewall-${TRE_ID}" \ - "az monitor diagnostic-settings show --resource /subscriptions/${ARM_SUBSCRIPTION_ID}/resourceGroups/rg-${TRE_ID}/providers/microsoft.network/azureFirewalls/fw-${TRE_ID} --name diagnostics-firewall-${TRE_ID}" - - -import_if_exists azurerm_public_ip.fwpip "/subscriptions/${ARM_SUBSCRIPTION_ID}/resourceGroups/${RESOURCE_GROUP_ID}/providers/Microsoft.Network/publicIPAddresses/pip-fw-${TRE_ID}" - - -import_if_exists azurerm_subnet_route_table_association.rt_web_app_subnet_association \ - "/subscriptions/${ARM_SUBSCRIPTION_ID}/resourceGroups/${RESOURCE_GROUP_ID}/providers/Microsoft.Network/virtualNetworks/vnet-${TRE_ID}/subnets/WebAppSubnet" - -# Route tables -import_if_exists azurerm_route_table.rt \ - "/subscriptions/${ARM_SUBSCRIPTION_ID}/resourceGroups/${RESOURCE_GROUP_ID}/providers/Microsoft.Network/routeTables/rt-${TRE_ID}" - -import_if_exists azurerm_subnet_route_table_association.rt_shared_subnet_association \ - "/subscriptions/${ARM_SUBSCRIPTION_ID}/resourceGroups/${RESOURCE_GROUP_ID}/providers/Microsoft.Network/virtualNetworks/vnet-${TRE_ID}/subnets/SharedSubnet" - -import_if_exists azurerm_subnet_route_table_association.rt_resource_processor_subnet_association \ - "/subscriptions/${ARM_SUBSCRIPTION_ID}/resourceGroups/${RESOURCE_GROUP_ID}/providers/Microsoft.Network/virtualNetworks/vnet-${TRE_ID}/subnets/ResourceProcessorSubnet" diff --git a/templates/shared_services/firewall/terraform/locals.tf b/templates/shared_services/firewall/terraform/locals.tf index e7d232167a..b1b47b706d 100644 --- a/templates/shared_services/firewall/terraform/locals.tf +++ b/templates/shared_services/firewall/terraform/locals.tf @@ -1,30 +1,6 @@ locals { core_resource_group_name = "rg-${var.tre_id}" - firewall_name = "fw-${var.tre_id}" - firewall_diagnostic_categories_enabled = [ - "AZFWApplicationRule", - "AZFWApplicationRuleAggregation", - "AZFWDnsQuery", - "AZFWFatFlow", - "AZFWFlowTrace", - "AZFWIdpsSignature", - "AZFWInternalFqdnResolutionFailure", - "AZFWNatRule", - "AZFWNatRuleAggregation", - "AZFWNetworkRule", - "AZFWNetworkRuleAggregation", - "AZFWThreatIntel" - ] - tre_shared_service_tags = { - tre_id = var.tre_id - tre_shared_service_id = var.tre_resource_id - } api_driven_application_rule_collection = jsondecode(base64decode(var.api_driven_rule_collections_b64)) api_driven_network_rule_collection = jsondecode(base64decode(var.api_driven_network_rule_collections_b64)) - - firewall_policy_name = "fw-policy-${var.tre_id}" - - default_firewall_sku = "Standard" - effective_firewall_sku = coalesce(var.firewall_sku, local.default_firewall_sku) } diff --git a/templates/shared_services/firewall/terraform/remove_state.sh b/templates/shared_services/firewall/terraform/remove_state.sh deleted file mode 100755 index 3b68a8c2ec..0000000000 --- a/templates/shared_services/firewall/terraform/remove_state.sh +++ /dev/null @@ -1,43 +0,0 @@ -#!/bin/bash -# shellcheck disable=SC2154 - -# This script works together with the import_state.sh script to manually remove the firewall state from the core deployment -# and import it into the firewall deployment. It's used for migration purposes only and will be removed when clients are all -# using the shared services model -echo "REMOVING STATE FOR FIREWALL..." - -set -e - -terraform init -input=false -backend=true -reconfigure -upgrade \ - -backend-config="resource_group_name=${TF_VAR_mgmt_resource_group_name}" \ - -backend-config="storage_account_name=${TF_VAR_mgmt_storage_account_name}" \ - -backend-config="container_name=${TF_VAR_terraform_state_container_name}" \ - -backend-config="key=${TRE_ID}" - -tf_state_list="$(terraform state list)" -function remove_if_present() { - echo -n "Checking $1 ..." - found=$(echo "$tf_state_list" | grep -q ^"$1"$; echo $?) - - if [[ $found -eq 0 ]]; then - echo " removing" - terraform state rm "$1" - else - echo " not present" - fi -} - -remove_if_present azurerm_route_table.rt -remove_if_present azurerm_subnet_route_table_association.rt_resource_processor_subnet_association -remove_if_present azurerm_subnet_route_table_association.rt_shared_subnet_association -remove_if_present azurerm_subnet_route_table_association.rt_web_app_subnet_association -remove_if_present module.firewall -remove_if_present module.firewall.azurerm_public_ip.fwpip -remove_if_present module.firewall.azurerm_monitor_diagnostic_setting.firewall -remove_if_present module.firewall.azurerm_firewall_network_rule_collection.web_app_subnet -remove_if_present module.firewall.azurerm_firewall_network_rule_collection.resource_processor_subnet -remove_if_present module.firewall.azurerm_firewall_network_rule_collection.general -remove_if_present module.firewall.azurerm_firewall_application_rule_collection.web_app_subnet -remove_if_present module.firewall.azurerm_firewall_application_rule_collection.shared_subnet -remove_if_present module.firewall.azurerm_firewall_application_rule_collection.resource_processor_subnet -remove_if_present module.firewall.azurerm_firewall.fw diff --git a/templates/shared_services/firewall/terraform/routetable.tf b/templates/shared_services/firewall/terraform/routetable.tf deleted file mode 100644 index 23202788eb..0000000000 --- a/templates/shared_services/firewall/terraform/routetable.tf +++ /dev/null @@ -1,114 +0,0 @@ -resource "azurerm_route_table" "rt" { - name = "rt-${var.tre_id}" - resource_group_name = local.core_resource_group_name - location = data.azurerm_resource_group.rg.location - bgp_route_propagation_enabled = true - tags = local.tre_shared_service_tags - - lifecycle { ignore_changes = [tags] } - - route { - name = "DefaultRoute" - address_prefix = "0.0.0.0/0" - next_hop_type = "VirtualAppliance" - next_hop_in_ip_address = azurerm_firewall.fw.ip_configuration[0].private_ip_address - } -} - -resource "azurerm_subnet_route_table_association" "rt_shared_subnet_association" { - subnet_id = data.azurerm_subnet.shared.id - route_table_id = azurerm_route_table.rt.id - - depends_on = [ - azurerm_firewall.fw, - azurerm_firewall_policy_rule_collection_group.core, - azurerm_firewall_policy_rule_collection_group.dynamic_network, - azurerm_firewall_policy_rule_collection_group.dynamic_application - ] -} - -resource "azurerm_subnet_route_table_association" "rt_resource_processor_subnet_association" { - subnet_id = data.azurerm_subnet.resource_processor.id - route_table_id = azurerm_route_table.rt.id - - # Not waiting for the rules will block traffic prematurally. - depends_on = [ - azurerm_firewall.fw, - azurerm_firewall_policy_rule_collection_group.core, - azurerm_firewall_policy_rule_collection_group.dynamic_network, - azurerm_firewall_policy_rule_collection_group.dynamic_application - ] -} - -resource "azurerm_subnet_route_table_association" "rt_web_app_subnet_association" { - subnet_id = data.azurerm_subnet.web_app.id - route_table_id = azurerm_route_table.rt.id - - depends_on = [ - azurerm_firewall.fw, - azurerm_firewall_policy_rule_collection_group.core, - azurerm_firewall_policy_rule_collection_group.dynamic_network, - azurerm_firewall_policy_rule_collection_group.dynamic_application - ] -} - -resource "azurerm_subnet_route_table_association" "rt_airlock_processor_subnet_association" { - subnet_id = data.azurerm_subnet.airlock_processor.id - route_table_id = azurerm_route_table.rt.id - - depends_on = [ - azurerm_firewall.fw, - azurerm_firewall_policy_rule_collection_group.core, - azurerm_firewall_policy_rule_collection_group.dynamic_network, - azurerm_firewall_policy_rule_collection_group.dynamic_application - ] -} - -resource "azurerm_subnet_route_table_association" "rt_airlock_storage_subnet_association" { - subnet_id = data.azurerm_subnet.airlock_storage.id - route_table_id = azurerm_route_table.rt.id - - depends_on = [ - azurerm_firewall.fw, - azurerm_firewall_policy_rule_collection_group.core, - azurerm_firewall_policy_rule_collection_group.dynamic_network, - azurerm_firewall_policy_rule_collection_group.dynamic_application - ] -} - -resource "azurerm_subnet_route_table_association" "rt_airlock_events_subnet_association" { - subnet_id = data.azurerm_subnet.airlock_events.id - route_table_id = azurerm_route_table.rt.id - - depends_on = [ - azurerm_firewall.fw, - azurerm_firewall_policy_rule_collection_group.core, - azurerm_firewall_policy_rule_collection_group.dynamic_network, - azurerm_firewall_policy_rule_collection_group.dynamic_application - ] -} - -resource "azurerm_route_table" "fw_tunnel_rt" { - count = var.firewall_force_tunnel_ip != "" ? 1 : 0 - name = "rt-fw-tunnel-${var.tre_id}" - resource_group_name = local.core_resource_group_name - location = data.azurerm_resource_group.rg.location - bgp_route_propagation_enabled = true - tags = local.tre_shared_service_tags - - lifecycle { ignore_changes = [tags] } - - route { - name = "ForceTunnelRoute" - address_prefix = "0.0.0.0/0" - next_hop_type = "VirtualAppliance" - next_hop_in_ip_address = var.firewall_force_tunnel_ip - } -} - -resource "azurerm_subnet_route_table_association" "rt_fw_tunnel_subnet_association" { - count = var.firewall_force_tunnel_ip != "" ? 1 : 0 - subnet_id = data.azurerm_subnet.firewall.id - route_table_id = azurerm_route_table.fw_tunnel_rt[0].id -} - diff --git a/templates/shared_services/firewall/terraform/rules.tf b/templates/shared_services/firewall/terraform/rules.tf index a29f4e885a..3745994610 100644 --- a/templates/shared_services/firewall/terraform/rules.tf +++ b/templates/shared_services/firewall/terraform/rules.tf @@ -1,205 +1,6 @@ -resource "azurerm_firewall_policy_rule_collection_group" "core" { - name = "rcg-core" - firewall_policy_id = azurerm_firewall_policy.root.id - priority = 500 - - network_rule_collection { - name = "nrc-general" - priority = 201 - action = "Allow" - - rule { - name = "time" - protocols = [ - "UDP" - ] - destination_addresses = [ - "*" - ] - destination_ports = [ - "123" - ] - source_addresses = [ - "*" - ] - } - } - - network_rule_collection { - name = "nrc-resource-processor-subnet" - priority = 202 - action = "Allow" - - rule { - name = "azure-services" - protocols = [ - "TCP" - ] - destination_addresses = [ - "AzureActiveDirectory", - "AzureResourceManager", - - // Needed when a workspace key vault is created before its private endpoint - "AzureKeyVault.${data.azurerm_resource_group.rg.location}" - ] - destination_ports = [ - "443" - ] - source_ip_groups = [data.azurerm_ip_group.resource_processor.id] - } - } - - network_rule_collection { - name = "nrc-web-app-subnet" - priority = 203 - action = "Allow" - - rule { - name = "azure-services" - protocols = [ - "TCP" - ] - destination_addresses = [ - "AzureActiveDirectory", - "AzureResourceManager" - ] - destination_ports = [ - "443" - ] - source_ip_groups = [data.azurerm_ip_group.web.id] - } - } - - application_rule_collection { - name = "arc-resource-processor-subnet" - priority = 301 - action = "Allow" - - rule { - name = "os-package-sources" - protocols { - port = "443" - type = "Https" - } - protocols { - port = "80" - type = "Http" - } - destination_fqdns = [ - "packages.microsoft.com", - "keyserver.ubuntu.com", - "api.snapcraft.io", - "azure.archive.ubuntu.com", - "security.ubuntu.com", - "entropy.ubuntu.com", - ] - source_ip_groups = [data.azurerm_ip_group.resource_processor.id] - } - - rule { - name = "docker-sources" - protocols { - port = "443" - type = "Https" - } - protocols { - port = "80" - type = "Http" - } - destination_fqdns = [ - "download.docker.com", - "registry-1.docker.io", - "auth.docker.io", - ] - source_ip_groups = [data.azurerm_ip_group.resource_processor.id] - } - # This rule is needed to support Gov Cloud. - # The az cli uses msal lib which requires access to this fqdn for authentication. - rule { - name = "microsoft-login" - protocols { - port = "443" - type = "Https" - } - destination_fqdns = [ - "login.microsoftonline.com", - ] - source_ip_groups = [data.azurerm_ip_group.resource_processor.id] - } - - - } - - application_rule_collection { - name = "arc-shared-subnet" - priority = 302 - action = "Allow" - - rule { - name = "nexus-bootstrap" - protocols { - port = "443" - type = "Https" - } - protocols { - port = "80" - type = "Http" - } - destination_fqdns = [ - "keyserver.ubuntu.com", - "packages.microsoft.com", - "download.docker.com", - "azure.archive.ubuntu.com" - ] - source_ip_groups = [data.azurerm_ip_group.shared.id] - } - } - - application_rule_collection { - name = "arc-web-app-subnet" - priority = 303 - action = "Allow" - - rule { - name = "microsoft-graph" - protocols { - port = "443" - type = "Https" - } - destination_fqdns = [ - var.microsoft_graph_fqdn - ] - source_ip_groups = [data.azurerm_ip_group.web.id] - } - } - - application_rule_collection { - name = "arc-airlock-processor-subnet" - priority = 304 - action = "Allow" - - rule { - name = "functions-runtime" - protocols { - port = "443" - type = "Https" - } - destination_fqdns = [ - "functionscdn.azureedge.net" - ] - source_ip_groups = [data.azurerm_ip_group.airlock_processor.id] - } - } - - depends_on = [ - azurerm_firewall.fw - ] -} - - resource "azurerm_firewall_policy_rule_collection_group" "dynamic_network" { name = "rcg-dynamic-network" - firewall_policy_id = azurerm_firewall_policy.root.id + firewall_policy_id = var.firewall_policy_id priority = 510 dynamic "network_rule_collection" { @@ -230,15 +31,11 @@ resource "azurerm_firewall_policy_rule_collection_group" "dynamic_network" { } } } - - depends_on = [ - azurerm_firewall_policy_rule_collection_group.core - ] } resource "azurerm_firewall_policy_rule_collection_group" "dynamic_application" { name = "rcg-dynamic-application" - firewall_policy_id = azurerm_firewall_policy.root.id + firewall_policy_id = var.firewall_policy_id priority = 520 dynamic "application_rule_collection" { diff --git a/templates/shared_services/firewall/terraform/variables.tf b/templates/shared_services/firewall/terraform/variables.tf index 1140c25f40..d73e6d53dc 100644 --- a/templates/shared_services/firewall/terraform/variables.tf +++ b/templates/shared_services/firewall/terraform/variables.tf @@ -3,14 +3,9 @@ variable "tre_id" { description = "Unique TRE ID" } -variable "microsoft_graph_fqdn" { +variable "firewall_policy_id" { type = string - description = "Microsoft Graph FQDN" -} - -variable "tre_resource_id" { - type = string - description = "Resource ID" + description = "ID of the firewall policy to use" } variable "api_driven_rule_collections_b64" { @@ -22,13 +17,3 @@ variable "api_driven_network_rule_collections_b64" { type = string default = "W10=" #b64 for [] } - -variable "firewall_sku" { - type = string - default = "" -} - -variable "firewall_force_tunnel_ip" { - type = string - default = "" -}