diff --git a/.github/actions/devcontainer_run_command/action.yml b/.github/actions/devcontainer_run_command/action.yml index d4d9926e9d..55157e1716 100644 --- a/.github/actions/devcontainer_run_command/action.yml +++ b/.github/actions/devcontainer_run_command/action.yml @@ -129,6 +129,10 @@ inputs: description: "Firewall SKU" required: false default: "" + APP_GATEWAY_SKU: + description: "Application Gateway SKU" + required: false + default: "" runs: using: composite @@ -239,6 +243,7 @@ runs: -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_app_gateway_sku=${{ inputs.APP_GATEWAY_SKU }} \ -e E2E_TESTS_NUMBER_PROCESSES="${{ inputs.E2E_TESTS_NUMBER_PROCESSES }}" \ '${{ inputs.CI_CACHE_ACR_NAME }}${{ env.ACR_DOMAIN_SUFFIX }}/tredev:${{ inputs.DEVCONTAINER_TAG }}' \ bash -c "${{ inputs.COMMAND }}" diff --git a/.github/workflows/deploy_tre_reusable.yml b/.github/workflows/deploy_tre_reusable.yml index 1ab13c964a..6056819ebe 100644 --- a/.github/workflows/deploy_tre_reusable.yml +++ b/.github/workflows/deploy_tre_reusable.yml @@ -358,6 +358,7 @@ jobs: RESOURCE_PROCESSOR_NUMBER_PROCESSES_PER_INSTANCE: ${{ vars.RESOURCE_PROCESSOR_NUMBER_PROCESSES_PER_INSTANCE }} RP_BUNDLE_VALUES: ${{ vars.RP_BUNDLE_VALUES }} FIREWALL_SKU: ${{ vars.FIREWALL_SKU}} + APP_GATEWAY_SKU: ${{ vars.APP_GATEWAY_SKU }} - name: API Healthcheck uses: ./.github/actions/devcontainer_run_command diff --git a/CHANGELOG.md b/CHANGELOG.md index 1f972e0315..bd0f873674 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,7 @@ FEATURES: ENHANCEMENTS: - +* Expose APP_SERVICE_SKU build variable to allow enablement of App Gateway WAF ([#4111](https://github.com/microsoft/AzureTRE/pull/4111)) BUG FIXES: COMPONENTS: diff --git a/config.sample.yaml b/config.sample.yaml index 77ce40d68c..8b613a580c 100644 --- a/config.sample.yaml +++ b/config.sample.yaml @@ -43,6 +43,7 @@ tre: # Uncomment the following to disable deployment of the Web UI. # deploy_ui: false firewall_sku: Standard + app_gateway_sku: Standard_v2 # Uncomment to deploy to a custom domain # custom_domain: __CHANGE_ME__ diff --git a/config_schema.json b/config_schema.json index f388319883..8885822acb 100644 --- a/config_schema.json +++ b/config_schema.json @@ -89,6 +89,10 @@ "description": "SKU of the Azure Firewall.", "type": "string" }, + "app_gateway_sku": { + "description": "SKU of the Application Gateway.", + "type": "string" + }, "custom_domain": { "description": "Custom domain name.", "type": "string" diff --git a/core/terraform/appgateway/appgateway.tf b/core/terraform/appgateway/appgateway.tf index 6f743fbe6b..c5dac2aab9 100644 --- a/core/terraform/appgateway/appgateway.tf +++ b/core/terraform/appgateway/appgateway.tf @@ -26,11 +26,13 @@ resource "azurerm_application_gateway" "agw" { tags = local.tre_core_tags sku { - name = "Standard_v2" - tier = "Standard_v2" + name = coalesce(var.app_gateway_sku, "Standard_v2") + tier = coalesce(var.app_gateway_sku, "Standard_v2") capacity = 1 } + firewall_policy_id = var.app_gateway_sku == "WAF_v2" ? azurerm_web_application_firewall_policy.waf[0].id : null + # User-assign managed identify id required to access certificate in KeyVault identity { type = "UserAssigned" @@ -120,6 +122,12 @@ resource "azurerm_application_gateway" "agw" { path = "/api/ping" timeout = "30" unhealthy_threshold = "3" + + match { + status_code = [ + "200-399" + ] + } } # Public HTTPS listener @@ -198,6 +206,40 @@ resource "azurerm_application_gateway" "agw" { } +resource "azurerm_web_application_firewall_policy" "waf" { + + // only create WAF policy when App Gateway sku.tier == "WAF_v2" + count = var.app_gateway_sku == "WAF_v2" ? 1 : 0 + + name = "wafpolicy-${var.tre_id}" + resource_group_name = var.resource_group_name + location = var.location + + policy_settings { + enabled = true + mode = "Detection" + } + + managed_rules { + managed_rule_set { + type = "OWASP" + version = 3.2 + } + } + + // once created ignore policy_settings and rulesets allow to be managed outside of here + lifecycle { ignore_changes = [policy_settings, managed_rules] } + + // terraform doesn't handle the downgrade from WAF_v2 > Standard_v2 SKU, this is required to detatch the policy from the app gateway before deletion of the policy + provisioner "local-exec" { + when = destroy + command = <