Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Firewall Policy #3107

Merged
merged 11 commits into from
Jan 24, 2023
21 changes: 21 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,28 @@
<!-- markdownlint-disable MD041 -->
## 0.9.0 (Unreleased)

**BREAKING CHANGES & MIGRATIONS**:

* Move to Azure **Firewall Policy** [#3107](https://github.com/microsoft/AzureTRE/pull/3107). This is a major version for the firewall shared service and will fail to automatically upgrade. You should follow these steps to complete it:
1. Let the system try to do the upgrade (via CI or `make tre-deploy`). It will fail but it's fine since now we have the new version published and registered.
2. Make a temporary network change with either of the following options:
* Azure Portal: find your TRE resource group and select the route table resource (named `rt-YOUR_TRE_ID`).
In the overview screen, find the `ResourceProcessorSubnet` (should be last in the subnet list), click on the `...` and select `Dissociate`.
* Azure CLI:
```shell
az network vnet subnet update --resource-group rg-YOUR_TRE_ID --vnet-name vnet-YOUR_TRE_ID --name ResourceProcessorSubnet --remove routeTable
```
4. Issue a patch API request to `force-update` the firewall to its new version.

One way to accomplish this is with the Swagger endpoint (/api/docs).
![Force-update a service](./docs/assets/firewall-policy-migrate1.png)

If this endpoint is not on in your deployment - include `enable_swagger` in your `config.yaml` (see the sample file), or temporarly via the API resource on azure (named `api-YOUR_TRE-ID`) -> Configuration -> `ENABLE_SWAGGER` item.
![Update API setting](./docs/assets/firewall-policy-migrate2.png)


:warning: Any custom rules you have added manually will be **lost** and you'll need to add it back after the upgrade has been completed.

FEATURES:

ENHANCEMENTS:
Expand Down
58 changes: 29 additions & 29 deletions core/terraform/.terraform.lock.hcl

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions core/terraform/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@ terraform {
}
local = {
source = "hashicorp/local"
version = "~> 2.2.0"
version = "~> 2.3.0"
}
http = {
source = "hashicorp/http"
version = "~> 3.1.0"
version = "~> 3.2.0"
}
}

Expand Down
32 changes: 32 additions & 0 deletions core/terraform/migrate.sh
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,38 @@ if [ -n "${api_vnet_integration}" ]; then
terraform apply -input=false -auto-approve ${PLAN_FILE}"
fi

# support changing the resource processor subnet size
rp_subnet=$(echo "${terraform_show_json}" \
| jq -r 'select(.values.root_module.child_modules != null) .values.root_module.child_modules[] | select (.address=="module.network") | .resources[] | select(.address=="module.network.azurerm_subnet.resource_processor") | .values.id')
if [ -n "${rp_subnet}" ]; then
set +o errexit
terraform plan -target "module.network.azurerm_subnet.resource_processor" -detailed-exitcode
plan_exit_code=$?
set -o errexit

if [ "${plan_exit_code}" == "2" ]; then
echo "Migrating ${rp_subnet}"
PLAN_FILE="tfplan$$"
TS=$(date +"%s")
LOG_FILE="${TS}-tre-core-migrate-rp-subnet.log"

# This variables are loaded in for us
# shellcheck disable=SC2154
"${terraform_wrapper_path}" \
-g "${TF_VAR_mgmt_resource_group_name}" \
-s "${TF_VAR_mgmt_storage_account_name}" \
-n "${TF_VAR_terraform_state_container_name}" \
-k "${TRE_ID}" \
-l "${LOG_FILE}" \
-c "terraform plan -destroy -target module.resource_processor_vmss_porter[0] \
-target azurerm_private_endpoint.sbpe \
-target azurerm_private_endpoint.mongo \
-out ${PLAN_FILE} && \
terraform apply -input=false -auto-approve ${PLAN_FILE}"
fi
fi


# this isn't a classic migration, but impacts how terraform handles the deployment in the next phase
state_store_serverless=$(echo "${terraform_show_json}" \
| jq 'select(.values.root_module.resources != null) | .values.root_module.resources[] | select(.address=="azurerm_cosmosdb_account.tre_db_account") | any(.values.capabilities[]; .name=="EnableServerless")')
Expand Down
16 changes: 10 additions & 6 deletions core/terraform/network/locals.tf
Original file line number Diff line number Diff line change
@@ -1,22 +1,26 @@
locals {
core_services_vnet_subnets = cidrsubnets(var.core_address_space, 4, 4, 4, 4, 2, 4, 4, 4, 4, 2)
# .1
core_services_vnet_subnets = cidrsubnets(var.core_address_space, 4, 4, 4, 4, 2, 4, 4, 4, 4, 4, 4, 4, 4)
# Addresses examples are based on /22 CIDR
# .0
firewall_subnet_address_space = local.core_services_vnet_subnets[0] # .0 - .63
app_gw_subnet_address_prefix = local.core_services_vnet_subnets[1] # .64 - .127
bastion_subnet_address_prefix = local.core_services_vnet_subnets[2] # .128 - .191
web_app_subnet_address_prefix = local.core_services_vnet_subnets[3] # .192 - .254

# .2
# .1
shared_services_subnet_address_prefix = local.core_services_vnet_subnets[4] # .0 - .254

# replacing the aci
# .2
airlock_processor_subnet_address_prefix = local.core_services_vnet_subnets[5] # .0 - .63
airlock_storage_subnet_address_prefix = local.core_services_vnet_subnets[6] # .64 - .127
airlock_events_subnet_address_prefix = local.core_services_vnet_subnets[7] # .128 - .191
airlock_notifications_subnet_address_prefix = local.core_services_vnet_subnets[8] # .128 - .191
airlock_notifications_subnet_address_prefix = local.core_services_vnet_subnets[8] # .192 - .254

# .3
resource_processor_subnet_address_prefix = local.core_services_vnet_subnets[9] # .0 - .254
resource_processor_subnet_address_prefix = local.core_services_vnet_subnets[9] # .0 - .63
firewall_management_subnet_address_prefix = local.core_services_vnet_subnets[10] # .64 - .127
# FREE = local.core_services_vnet_subnets[11] # .128 - .191
# FREE = local.core_services_vnet_subnets[12] # .192 - .254

tre_core_tags = {
tre_id = var.tre_id
Expand Down
28 changes: 27 additions & 1 deletion core/terraform/network/network.tf
Original file line number Diff line number Diff line change
Expand Up @@ -130,14 +130,22 @@ resource "azurerm_subnet" "airlock_events" {
address_prefixes = [local.airlock_events_subnet_address_prefix]
# notice that private endpoints do not adhere to NSG rules
private_endpoint_network_policies_enabled = false
depends_on = [azurerm_subnet.airlock_events]
depends_on = [azurerm_subnet.airlock_storage]

# Eventgrid CAN'T send messages over private endpoints, hence we need to allow service endpoints to the service bus
# We are using service endpoints + managed identity to send these messaages
# https://docs.microsoft.com/en-us/azure/event-grid/consume-private-endpoints
service_endpoints = ["Microsoft.ServiceBus"]
}

resource "azurerm_subnet" "firewall_management" {
name = "AzureFirewallManagementSubnet"
virtual_network_name = azurerm_virtual_network.core.name
resource_group_name = var.resource_group_name
address_prefixes = [local.firewall_management_subnet_address_prefix]
depends_on = [azurerm_subnet.airlock_events]
}

resource "azurerm_ip_group" "resource_processor" {
name = "ipg-resource-processor"
location = var.location
Expand All @@ -146,3 +154,21 @@ resource "azurerm_ip_group" "resource_processor" {
tags = local.tre_core_tags
lifecycle { ignore_changes = [tags] }
}

resource "azurerm_ip_group" "shared" {
name = "ipg-shared"
location = var.location
resource_group_name = var.resource_group_name
cidrs = [local.shared_services_subnet_address_prefix]
tags = local.tre_core_tags
lifecycle { ignore_changes = [tags] }
}

resource "azurerm_ip_group" "webapp" {
name = "ipg-web-app"
location = var.location
resource_group_name = var.resource_group_name
cidrs = [local.web_app_subnet_address_prefix]
tags = local.tre_core_tags
lifecycle { ignore_changes = [tags] }
}
2 changes: 1 addition & 1 deletion core/terraform/network/network_security_groups.tf
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ resource "azurerm_subnet_network_security_group_association" "bastion" {
subnet_id = azurerm_subnet.bastion.id
network_security_group_id = azurerm_network_security_group.bastion.id
# depend on the last subnet we created in the vnet
depends_on = [azurerm_subnet.airlock_events]
depends_on = [azurerm_subnet.firewall_management]
}

# Network security group for Application Gateway
Expand Down
15 changes: 15 additions & 0 deletions core/terraform/notebooks.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
data "http" "firewall_workbook_json" {
url = "https://raw.githubusercontent.com/Azure/Azure-Network-Security/master/Azure%20Firewall/Workbook%20-%20Azure%20Firewall%20Monitor%20Workbook/Azure%20Firewall_Gallery.json"
}

resource "random_uuid" "firewall_workbook" {
}

resource "azurerm_application_insights_workbook" "firewall" {
name = random_uuid.firewall_workbook.result
location = azurerm_resource_group.core.location
resource_group_name = azurerm_resource_group.core.name
display_name = "Azure Firewall Workbook"
data_json = data.http.firewall_workbook_json.response_body
tags = local.tre_core_tags
}
4 changes: 4 additions & 0 deletions core/terraform/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ variable "acr_name" {
variable "core_address_space" {
type = string
description = "Core services VNET Address Space"
validation {
condition = parseint(element(split("/", var.core_address_space), 1), 10) > 0 && parseint(element(split("/", var.core_address_space), 1), 10) <= 22
error_message = "core_address_space size should be /22 or larger"
}
}

variable "tre_address_space" {
Expand Down
2 changes: 1 addition & 1 deletion core/version.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "0.5.3"
__version__ = "0.6.0"
5 changes: 3 additions & 2 deletions devops/scripts/control_tre.sh
Original file line number Diff line number Diff line change
Expand Up @@ -66,13 +66,14 @@ if [[ "$1" == *"start"* ]]; then

elif [[ "$1" == *"stop"* ]]; then
if [[ $(az network firewall list --output json --query "[?resourceGroup=='${core_rg_name}'&&name=='${fw_name}'] | length(@)") != 0 ]]; then
fw_sku=$(az network firewall show -n "${fw_name}" -g "${core_rg_name}" --query "sku.tier" -o tsv)
IPCONFIG_NAME=$(az network firewall ip-config list -f "${fw_name}" -g "${core_rg_name}" --query "[0].name" -o tsv)

if [ -n "$IPCONFIG_NAME" ]; then
if [ -n "$IPCONFIG_NAME" ] && [ "${fw_sku}" != "Basic" ]; then
echo "Deleting Firewall ip-config: $IPCONFIG_NAME"
az network firewall ip-config delete -f "${fw_name}" -n "$IPCONFIG_NAME" -g "${core_rg_name}" &
else
echo "No Firewall ip-config found"
echo "No Firewall ip-config found or SKU (${fw_sku}) doesn't allow deallocation"
fi
fi

Expand Down
Binary file added docs/assets/firewall-policy-migrate1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/assets/firewall-policy-migrate2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 6 additions & 0 deletions templates/shared_services/firewall/parameters.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,12 @@
"source": {
"env": "NETWORK_RULE_COLLECTIONS"
}
},
{
"name": "sku_tier",
"source": {
"env": "SKU_TIER"
}
}
]
}
9 changes: 8 additions & 1 deletion templates/shared_services/firewall/porter.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
schemaVersion: 1.0.0
name: tre-shared-service-firewall
version: 0.8.0
version: 0.8.1 # TODO: update before merge
tamirkamara marked this conversation as resolved.
Show resolved Hide resolved
description: "An Azure TRE Firewall shared service"
dockerfile: Dockerfile.tmpl
registry: azuretre
Expand Down Expand Up @@ -45,6 +45,10 @@ parameters:
type: string
default: "W10=" # b64 for []
description: "Network rule collection array"
- name: sku_tier
type: string
default: Standard
description: The firewall and its policy SKU tier

mixins:
- terraform:
Expand All @@ -58,6 +62,7 @@ install:
tre_resource_id: ${ bundle.parameters.id }
api_driven_rule_collections_b64: ${ bundle.parameters.rule_collections }
api_driven_network_rule_collections_b64: ${ bundle.parameters.network_rule_collections }
sku_tier: ${ bundle.parameters.sku_tier }
backendConfig:
resource_group_name: ${ bundle.parameters.tfstate_resource_group_name }
storage_account_name: ${ bundle.parameters.tfstate_storage_account_name }
Expand All @@ -72,6 +77,7 @@ upgrade:
tre_resource_id: ${ bundle.parameters.id }
api_driven_rule_collections_b64: ${ bundle.parameters.rule_collections }
api_driven_network_rule_collections_b64: ${ bundle.parameters.network_rule_collections }
sku_tier: ${ bundle.parameters.sku_tier }
backendConfig:
resource_group_name: ${ bundle.parameters.tfstate_resource_group_name }
storage_account_name: ${ bundle.parameters.tfstate_storage_account_name }
Expand All @@ -86,6 +92,7 @@ uninstall:
tre_resource_id: ${ bundle.parameters.id }
api_driven_rule_collections_b64: ${ bundle.parameters.rule_collections }
api_driven_network_rule_collections_b64: ${ bundle.parameters.network_rule_collections }
sku_tier: ${ bundle.parameters.sku_tier }
backendConfig:
resource_group_name: ${ bundle.parameters.tfstate_resource_group_name }
storage_account_name: ${ bundle.parameters.tfstate_storage_account_name }
Expand Down
Loading