From 0a4e0d482f6a8e17dc26dbdc600b9f2a13c8182a Mon Sep 17 00:00:00 2001 From: Elad Iwanir <13205761+eladiw@users.noreply.github.com> Date: Thu, 16 Jun 2022 21:40:24 +0300 Subject: [PATCH] Airlock processor networking (vnet integration and airlock subnet) (#2040) * Airlock networking, including: 1. Airlock subnet in the core vnet 2. Airlock processor is now vnet integrated * moving the airlock storage accounts to a dedicated subnet * adding private endpoint for all event grid topics * adding inbound rule to allow airlock processor to reach the workspaces * Adding an AirlockEventSubnet All eventgrids are in the AirlockEventSubnets All airlock storage are in the AirlockStorageSubnet The airlock function is in the AirlockProcessorSubnet --- airlock_processor/_version.py | 2 +- .../terraform/airlock/airlock_processor.tf | 27 ++++-- .../terraform/airlock/eventgrid_topics.tf | 86 +++++++++++++------ templates/core/terraform/airlock/identity.tf | 2 +- .../terraform/airlock/storage_accounts.tf | 10 +-- templates/core/terraform/airlock/variables.tf | 10 ++- templates/core/terraform/main.tf | 27 +++--- .../terraform/modules_move_definitions.tf | 7 +- templates/core/terraform/network/dns_zones.tf | 19 ++++ templates/core/terraform/network/locals.tf | 27 ++++-- templates/core/terraform/network/network.tf | 36 ++++++++ .../network/network_security_groups.tf | 19 ++++ templates/core/terraform/network/output.tf | 12 +++ .../workspaces/base/terraform/network/data.tf | 6 ++ .../base/terraform/network/security.tf | 17 ++++ 15 files changed, 247 insertions(+), 60 deletions(-) diff --git a/airlock_processor/_version.py b/airlock_processor/_version.py index 27fdca497..81f0fdecc 100644 --- a/airlock_processor/_version.py +++ b/airlock_processor/_version.py @@ -1 +1 @@ -__version__ = "0.0.3" +__version__ = "0.0.4" diff --git a/templates/core/terraform/airlock/airlock_processor.tf b/templates/core/terraform/airlock/airlock_processor.tf index e9b757074..88899a8c9 100644 --- a/templates/core/terraform/airlock/airlock_processor.tf +++ b/templates/core/terraform/airlock/airlock_processor.tf @@ -6,17 +6,27 @@ locals { version = replace(replace(replace(data.local_file.airlock_processor_version.content, "__version__ = \"", ""), "\"", ""), "\n", "") } -# re-using the web api app plan -data "azurerm_app_service_plan" "core" { - name = "plan-${var.tre_id}" - resource_group_name = var.resource_group_name -} - data "azurerm_application_insights" "core" { name = "appi-${var.tre_id}" resource_group_name = var.resource_group_name } +resource "azurerm_service_plan" "airlock_plan" { + name = "plan-airlock-${var.tre_id}" + resource_group_name = var.resource_group_name + location = var.location + os_type = "Linux" + sku_name = var.airlock_app_service_plan_sku_size + tags = local.tre_core_tags + worker_count = 1 + + lifecycle { ignore_changes = [tags] } +} + +resource "azurerm_app_service_virtual_network_swift_connection" "airlock-integrated-vnet" { + app_service_id = azurerm_linux_function_app.airlock_function_app.id + subnet_id = var.airlock_processor_subnet_id +} resource "azurerm_storage_account" "sa_airlock_processor_func_app" { name = local.airlock_function_sa_name @@ -35,7 +45,7 @@ resource "azurerm_linux_function_app" "airlock_function_app" { location = var.location storage_account_name = azurerm_storage_account.sa_airlock_processor_func_app.name - service_plan_id = data.azurerm_app_service_plan.core.id + service_plan_id = azurerm_service_plan.airlock_plan.id storage_account_access_key = azurerm_storage_account.sa_airlock_processor_func_app.primary_access_key tags = local.tre_core_tags @@ -57,12 +67,15 @@ resource "azurerm_linux_function_app" "airlock_function_app" { "MANAGED_IDENTITY_CLIENT_ID" = azurerm_user_assigned_identity.airlock_id.client_id "AZURE_SUBSCRIPTION_ID" = var.arm_subscription_id "TRE_ID" = var.tre_id + "WEBSITE_CONTENTOVERVNET" = 1 } site_config { always_on = var.enable_local_debugging ? true : false container_registry_managed_identity_client_id = azurerm_user_assigned_identity.airlock_id.client_id container_registry_use_managed_identity = true + vnet_route_all_enabled = true + application_stack { docker { registry_url = var.docker_registry_server diff --git a/templates/core/terraform/airlock/eventgrid_topics.tf b/templates/core/terraform/airlock/eventgrid_topics.tf index b62a1d7dd..e2f83df88 100644 --- a/templates/core/terraform/airlock/eventgrid_topics.tf +++ b/templates/core/terraform/airlock/eventgrid_topics.tf @@ -1,14 +1,42 @@ +data "azurerm_private_dns_zone" "eventgrid" { + name = "privatelink.eventgrid.azure.net" + resource_group_name = var.resource_group_name +} + # Event grid topics resource "azurerm_eventgrid_topic" "step_result" { - name = local.step_result_topic_name - location = var.location - resource_group_name = var.resource_group_name + name = local.step_result_topic_name + location = var.location + resource_group_name = var.resource_group_name + public_network_access_enabled = false tags = { - Publishers = "Airlock Orchestrator;" + Publishers = "Airlock Processor;" } } + +resource "azurerm_private_endpoint" "eg_step_result" { + name = "pe-eg-step-result-${var.tre_id}" + location = var.location + resource_group_name = var.resource_group_name + subnet_id = var.airlock_events_subnet_id + lifecycle { ignore_changes = [tags] } + + private_dns_zone_group { + name = "private-dns-zone-group" + private_dns_zone_ids = [data.azurerm_private_dns_zone.eventgrid.id] + } + + private_service_connection { + name = "psc-eg-${var.tre_id}" + private_connection_resource_id = azurerm_eventgrid_topic.step_result.id + is_manual_connection = false + subresource_names = ["topic"] + } +} + + resource "azurerm_eventgrid_topic" "status_changed" { name = local.status_changed_topic_name location = var.location @@ -20,23 +48,17 @@ resource "azurerm_eventgrid_topic" "status_changed" { } } -# Event grid status_changed private endpoint -resource "azurerm_private_dns_zone" "eventgrid" { - name = "privatelink.eventgrid.azure.net" - resource_group_name = var.resource_group_name - lifecycle { ignore_changes = [tags] } -} -resource "azurerm_private_endpoint" "egpe" { - name = "pe-eg-${var.tre_id}" +resource "azurerm_private_endpoint" "eg_status_changed" { + name = "pe-eg-status-changed-${var.tre_id}" location = var.location resource_group_name = var.resource_group_name - subnet_id = var.shared_subnet_id + subnet_id = var.airlock_events_subnet_id lifecycle { ignore_changes = [tags] } private_dns_zone_group { name = "private-dns-zone-group" - private_dns_zone_ids = [azurerm_private_dns_zone.eventgrid.id] + private_dns_zone_ids = [data.azurerm_private_dns_zone.eventgrid.id] } private_service_connection { @@ -47,13 +69,6 @@ resource "azurerm_private_endpoint" "egpe" { } } -resource "azurerm_private_dns_zone_virtual_network_link" "eg_topic_dns_link" { - name = "eg_topic_dns_link" - resource_group_name = var.resource_group_name - private_dns_zone_name = azurerm_private_dns_zone.eventgrid.name - virtual_network_id = var.virtual_network_id - lifecycle { ignore_changes = [tags] } -} # System topic resource "azurerm_eventgrid_system_topic" "import_inprogress_blob_created" { @@ -114,9 +129,11 @@ resource "azurerm_eventgrid_system_topic" "export_approved_blob_created" { # Custom topic (for scanning) resource "azurerm_eventgrid_topic" "scan_result" { - name = local.scan_result_topic_name - location = var.location - resource_group_name = var.resource_group_name + name = local.scan_result_topic_name + location = var.location + resource_group_name = var.resource_group_name + public_network_access_enabled = false + tags = { Publishers = "airlock;custom scanning service;" @@ -125,6 +142,27 @@ resource "azurerm_eventgrid_topic" "scan_result" { lifecycle { ignore_changes = [tags] } } + +resource "azurerm_private_endpoint" "eg_scan_result" { + name = "pe-eg-scan-result-${var.tre_id}" + location = var.location + resource_group_name = var.resource_group_name + subnet_id = var.airlock_events_subnet_id + lifecycle { ignore_changes = [tags] } + + private_dns_zone_group { + name = "private-dns-zone-group" + private_dns_zone_ids = [data.azurerm_private_dns_zone.eventgrid.id] + } + + private_service_connection { + name = "psc-eg-${var.tre_id}" + private_connection_resource_id = azurerm_eventgrid_topic.scan_result.id + is_manual_connection = false + subresource_names = ["topic"] + } +} + ## Subscriptions resource "azurerm_eventgrid_event_subscription" "step_result" { diff --git a/templates/core/terraform/airlock/identity.tf b/templates/core/terraform/airlock/identity.tf index 402d3c983..c27f69444 100644 --- a/templates/core/terraform/airlock/identity.tf +++ b/templates/core/terraform/airlock/identity.tf @@ -49,7 +49,7 @@ resource "azurerm_role_assignment" "eventgrid_data_sender" { } resource "azurerm_role_assignment" "sa_import_external" { - scope = azurerm_storage_account.sa_external_import.id + scope = azurerm_storage_account.sa_import_external.id role_definition_name = "Contributor" principal_id = azurerm_user_assigned_identity.airlock_id.principal_id } diff --git a/templates/core/terraform/airlock/storage_accounts.tf b/templates/core/terraform/airlock/storage_accounts.tf index edf8f0b24..85fcaf5f9 100644 --- a/templates/core/terraform/airlock/storage_accounts.tf +++ b/templates/core/terraform/airlock/storage_accounts.tf @@ -1,5 +1,5 @@ # 'External' storage account - drop location for import -resource "azurerm_storage_account" "sa_external_import" { +resource "azurerm_storage_account" "sa_import_external" { name = local.import_external_storage_name location = var.location resource_group_name = var.resource_group_name @@ -72,11 +72,11 @@ data "azurerm_private_dns_zone" "blobcore" { resource_group_name = var.resource_group_name } -resource "azurerm_private_endpoint" "stg_ip_import_pe" { +resource "azurerm_private_endpoint" "stg_import_inprogress_pe" { name = "stg-ip-import-blob-${var.tre_id}" location = var.location resource_group_name = var.resource_group_name - subnet_id = var.shared_subnet_id + subnet_id = var.airlock_storage_subnet_id lifecycle { ignore_changes = [tags] } @@ -119,11 +119,11 @@ resource "azurerm_storage_account" "sa_import_rejected" { lifecycle { ignore_changes = [tags] } } -resource "azurerm_private_endpoint" "stgipimportpe" { +resource "azurerm_private_endpoint" "stg_import_rejected_pe" { name = "stg-import-rej-blob-${var.tre_id}" location = var.location resource_group_name = var.resource_group_name - subnet_id = var.shared_subnet_id + subnet_id = var.airlock_storage_subnet_id private_dns_zone_group { name = "private-dns-zone-group-stg-import-rej" diff --git a/templates/core/terraform/airlock/variables.tf b/templates/core/terraform/airlock/variables.tf index cc750f56b..fbf748d06 100644 --- a/templates/core/terraform/airlock/variables.tf +++ b/templates/core/terraform/airlock/variables.tf @@ -1,7 +1,8 @@ variable "tre_id" {} variable "location" {} variable "resource_group_name" {} -variable "shared_subnet_id" {} +variable "airlock_storage_subnet_id" {} +variable "airlock_events_subnet_id" {} variable "enable_local_debugging" {} variable "virtual_network_id" {} variable "api_principal_id" {} @@ -32,3 +33,10 @@ variable "arm_subscription_id" { type = string default = "" } + +variable "airlock_app_service_plan_sku_size" { + type = string + default = "P1v3" +} + +variable "airlock_processor_subnet_id" {} diff --git a/templates/core/terraform/main.tf b/templates/core/terraform/main.tf index b2c5f58db..a07eff57a 100644 --- a/templates/core/terraform/main.tf +++ b/templates/core/terraform/main.tf @@ -80,18 +80,21 @@ module "appgateway" { } module "airlock_resources" { - source = "./airlock" - tre_id = var.tre_id - location = var.location - resource_group_name = azurerm_resource_group.core.name - shared_subnet_id = module.network.shared_subnet_id - virtual_network_id = module.network.core_vnet_id - enable_local_debugging = var.enable_local_debugging - docker_registry_server = var.docker_registry_server - mgmt_resource_group_name = var.mgmt_resource_group_name - mgmt_acr_name = var.acr_name - api_principal_id = azurerm_user_assigned_identity.id.principal_id - arm_subscription_id = var.arm_subscription_id + source = "./airlock" + tre_id = var.tre_id + location = var.location + resource_group_name = azurerm_resource_group.core.name + airlock_storage_subnet_id = module.network.airlock_storage_subnet_id + airlock_events_subnet_id = module.network.airlock_events_subnet_id + virtual_network_id = module.network.core_vnet_id + enable_local_debugging = var.enable_local_debugging + docker_registry_server = var.docker_registry_server + mgmt_resource_group_name = var.mgmt_resource_group_name + mgmt_acr_name = var.acr_name + api_principal_id = azurerm_user_assigned_identity.id.principal_id + arm_subscription_id = var.arm_subscription_id + airlock_app_service_plan_sku_size = var.api_app_service_plan_sku_size + airlock_processor_subnet_id = module.network.airlock_processor_subnet_id depends_on = [ azurerm_servicebus_namespace.sb, module.network diff --git a/templates/core/terraform/modules_move_definitions.tf b/templates/core/terraform/modules_move_definitions.tf index dc0c8f940..36a3f36c3 100644 --- a/templates/core/terraform/modules_move_definitions.tf +++ b/templates/core/terraform/modules_move_definitions.tf @@ -225,4 +225,9 @@ moved { moved { from = module.bastion.azurerm_bastion_host.bastion to = azurerm_bastion_host.bastion -} \ No newline at end of file +} + +moved { + from = module.airlock.azurerm_private_dns_zone.eventgrid + to = module.network.azurerm_private_dns_zone.eventgrid +} diff --git a/templates/core/terraform/network/dns_zones.tf b/templates/core/terraform/network/dns_zones.tf index 8a2a6b1f3..497a977fc 100644 --- a/templates/core/terraform/network/dns_zones.tf +++ b/templates/core/terraform/network/dns_zones.tf @@ -237,3 +237,22 @@ resource "azurerm_private_dns_zone" "nexus" { lifecycle { ignore_changes = [tags] } } + +resource "azurerm_private_dns_zone" "eventgrid" { + name = "privatelink.eventgrid.azure.net" + resource_group_name = var.resource_group_name + tags = local.tre_core_tags + + lifecycle { ignore_changes = [tags] } +} + + +resource "azurerm_private_dns_zone_virtual_network_link" "eventgridlink" { + name = "eventgrid-link" + resource_group_name = var.resource_group_name + private_dns_zone_name = azurerm_private_dns_zone.eventgrid.name + virtual_network_id = azurerm_virtual_network.core.id + tags = local.tre_core_tags + + lifecycle { ignore_changes = [tags] } +} diff --git a/templates/core/terraform/network/locals.tf b/templates/core/terraform/network/locals.tf index d25759b16..34a64da93 100644 --- a/templates/core/terraform/network/locals.tf +++ b/templates/core/terraform/network/locals.tf @@ -1,12 +1,23 @@ locals { - core_services_vnet_subnets = cidrsubnets(var.core_address_space, 4, 4, 4, 4, 2, 2, 2) - firewall_subnet_address_space = local.core_services_vnet_subnets[0] # .0 - .62 - 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 - shared_services_subnet_address_prefix = local.core_services_vnet_subnets[4] # .0 - .254 - aci_subnet_address_prefix = local.core_services_vnet_subnets[5] # .0 - .254 - resource_processor_subnet_address_prefix = local.core_services_vnet_subnets[6] # .0 - .254 + core_services_vnet_subnets = cidrsubnets(var.core_address_space, 4, 4, 4, 4, 2, 4, 4, 4, 4, 2) + # .1 + 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 + shared_services_subnet_address_prefix = local.core_services_vnet_subnets[4] # .0 - .254 + + # replacing the aci + 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 + # free [8] + + # .3 + resource_processor_subnet_address_prefix = local.core_services_vnet_subnets[9] # .0 - .254 + tre_core_tags = { tre_id = var.tre_id tre_core_service_id = var.tre_id diff --git a/templates/core/terraform/network/network.tf b/templates/core/terraform/network/network.tf index a45039abb..ae19dc288 100644 --- a/templates/core/terraform/network/network.tf +++ b/templates/core/terraform/network/network.tf @@ -65,3 +65,39 @@ resource "azurerm_subnet" "resource_processor" { # notice that private endpoints do not adhere to NSG rules enforce_private_link_endpoint_network_policies = true } + +resource "azurerm_subnet" "airlock_processor" { + name = "AirlockProcessorSubnet" + virtual_network_name = azurerm_virtual_network.core.name + resource_group_name = var.resource_group_name + address_prefixes = [local.airlock_processor_subnet_address_prefix] + # notice that private endpoints do not adhere to NSG rules + enforce_private_link_endpoint_network_policies = true + + delegation { + name = "delegation" + + service_delegation { + name = "Microsoft.Web/serverFarms" + actions = ["Microsoft.Network/virtualNetworks/subnets/action"] + } + } +} + +resource "azurerm_subnet" "airlock_storage" { + name = "AirlockStorageSubnet" + virtual_network_name = azurerm_virtual_network.core.name + resource_group_name = var.resource_group_name + address_prefixes = [local.airlock_storage_subnet_address_prefix] + # notice that private endpoints do not adhere to NSG rules + enforce_private_link_endpoint_network_policies = true +} + +resource "azurerm_subnet" "airlock_events" { + name = "AirlockEventsSubnet" + virtual_network_name = azurerm_virtual_network.core.name + resource_group_name = var.resource_group_name + address_prefixes = [local.airlock_events_subnet_address_prefix] + # notice that private endpoints do not adhere to NSG rules + enforce_private_link_endpoint_network_policies = true +} diff --git a/templates/core/terraform/network/network_security_groups.tf b/templates/core/terraform/network/network_security_groups.tf index 3119767ab..4570edfd3 100644 --- a/templates/core/terraform/network/network_security_groups.tf +++ b/templates/core/terraform/network/network_security_groups.tf @@ -169,3 +169,22 @@ resource "azurerm_subnet_network_security_group_association" "resource_processor subnet_id = azurerm_subnet.resource_processor.id network_security_group_id = azurerm_network_security_group.default_rules.id } + + +resource "azurerm_subnet_network_security_group_association" "airlock_processor" { + subnet_id = azurerm_subnet.airlock_processor.id + network_security_group_id = azurerm_network_security_group.default_rules.id +} + + +resource "azurerm_subnet_network_security_group_association" "airlock_storage" { + subnet_id = azurerm_subnet.airlock_storage.id + network_security_group_id = azurerm_network_security_group.default_rules.id +} + + +resource "azurerm_subnet_network_security_group_association" "airlock_events" { + subnet_id = azurerm_subnet.airlock_events.id + network_security_group_id = azurerm_network_security_group.default_rules.id +} + diff --git a/templates/core/terraform/network/output.tf b/templates/core/terraform/network/output.tf index 2616b925e..f018fe75a 100644 --- a/templates/core/terraform/network/output.tf +++ b/templates/core/terraform/network/output.tf @@ -22,6 +22,18 @@ output "shared_subnet_id" { value = azurerm_subnet.shared.id } +output "airlock_processor_subnet_id" { + value = azurerm_subnet.airlock_processor.id +} + +output "airlock_storage_subnet_id" { + value = azurerm_subnet.airlock_storage.id +} + +output "airlock_events_subnet_id" { + value = azurerm_subnet.airlock_events.id +} + output "private_dns_zone_azurewebsites_id" { value = azurerm_private_dns_zone.azurewebsites.id } diff --git a/templates/workspaces/base/terraform/network/data.tf b/templates/workspaces/base/terraform/network/data.tf index 8f293553a..1e3efbb97 100644 --- a/templates/workspaces/base/terraform/network/data.tf +++ b/templates/workspaces/base/terraform/network/data.tf @@ -27,6 +27,12 @@ data "azurerm_subnet" "resourceprocessor" { name = "ResourceProcessorSubnet" } +data "azurerm_subnet" "airlockprocessor" { + resource_group_name = local.core_resource_group_name + virtual_network_name = local.core_vnet + name = "AirlockProcessorSubnet" +} + data "azurerm_route_table" "rt" { name = "rt-${var.tre_id}" resource_group_name = local.core_resource_group_name diff --git a/templates/workspaces/base/terraform/network/security.tf b/templates/workspaces/base/terraform/network/security.tf index 2735e4ace..487e774fb 100644 --- a/templates/workspaces/base/terraform/network/security.tf +++ b/templates/workspaces/base/terraform/network/security.tf @@ -172,6 +172,23 @@ resource "azurerm_network_security_rule" "allow-inbound-from-resourceprocessor" source_port_range = "*" } + +resource "azurerm_network_security_rule" "allow-inbound-from-airlockprocessor" { + access = "Allow" + destination_address_prefixes = azurerm_subnet.services.address_prefixes + destination_port_range = "443" + direction = "Inbound" + name = "allow-inbound-from-airlockprocessor" + network_security_group_name = azurerm_network_security_group.ws.name + priority = 140 + protocol = "Tcp" + resource_group_name = var.ws_resource_group_name + source_address_prefixes = [ + data.azurerm_subnet.airlockprocessor.address_prefix + ] + source_port_range = "*" +} + resource "azurerm_network_security_rule" "allow-inbound-from-webapp-to-services" { access = "Allow" destination_port_ranges = [