diff --git a/templates/core/terraform/airlock/eventgrid_topics.tf b/templates/core/terraform/airlock/eventgrid_topics.tf new file mode 100644 index 0000000000..0ef1d82141 --- /dev/null +++ b/templates/core/terraform/airlock/eventgrid_topics.tf @@ -0,0 +1,148 @@ +# 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 + + tags = { + Publishers = "Airlock Orchestrator;" + } +} + +resource "azurerm_eventgrid_topic" "status_changed" { + name = local.status_changed_topic_name + location = var.location + resource_group_name = var.resource_group_name + + tags = { + Publishers = "TRE API;" + } +} + +# System topic +resource "azurerm_eventgrid_system_topic" "import_inprogress_blob_created" { + name = local.import_inprogress_sys_topic_name + location = var.location + resource_group_name = var.resource_group_name + source_arm_resource_id = azurerm_storage_account.sa_import_in_progress.id + topic_type = "Microsoft.Storage.StorageAccounts" + + tags = { + Publishers = "airlock;import-in-progress-sa" + } + + depends_on = [ + azurerm_storage_account.sa_import_in_progress + ] + + lifecycle { ignore_changes = [tags] } +} + + +resource "azurerm_eventgrid_system_topic" "import_rejected_blob_created" { + name = local.import_rejected_sys_topic_name + location = var.location + resource_group_name = var.resource_group_name + source_arm_resource_id = azurerm_storage_account.sa_import_rejected.id + topic_type = "Microsoft.Storage.StorageAccounts" + + tags = { + Publishers = "airlock;import-rejected-sa" + } + + depends_on = [ + azurerm_storage_account.sa_import_rejected + ] + + lifecycle { ignore_changes = [tags] } +} + +resource "azurerm_eventgrid_system_topic" "export_approved_blob_created" { + name = local.export_approved_sys_topic_name + location = var.location + resource_group_name = var.resource_group_name + source_arm_resource_id = azurerm_storage_account.sa_export_approved.id + topic_type = "Microsoft.Storage.StorageAccounts" + + tags = { + Publishers = "airlock;export-approved-sa" + } + + depends_on = [ + azurerm_storage_account.sa_export_approved + ] + + lifecycle { ignore_changes = [tags] } +} + + +# 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 + + tags = { + Publishers = "airlock;custom scanning service;" + } + + lifecycle { ignore_changes = [tags] } +} + +## Subscriptions + +resource "azurerm_eventgrid_event_subscription" "step_result" { + name = local.step_result_eventgrid_subscription_name + scope = azurerm_eventgrid_topic.step_result.id + + service_bus_queue_endpoint_id = azurerm_servicebus_queue.step_result.id + + depends_on = [ + azurerm_eventgrid_topic.step_result + ] +} + +resource "azurerm_eventgrid_event_subscription" "status_changed" { + name = local.status_changed_eventgrid_subscription_name + scope = azurerm_eventgrid_topic.status_changed.id + + service_bus_queue_endpoint_id = azurerm_servicebus_queue.status_changed.id + + depends_on = [ + azurerm_eventgrid_topic.status_changed + ] +} + +resource "azurerm_eventgrid_event_subscription" "import_inprogress_blob_created" { + name = local.import_inprogress_eventgrid_subscription_name + scope = azurerm_storage_account.sa_import_in_progress.id + + service_bus_queue_endpoint_id = azurerm_servicebus_queue.import_in_progress_blob_created.id + + depends_on = [ + azurerm_eventgrid_system_topic.import_inprogress_blob_created + ] +} + +resource "azurerm_eventgrid_event_subscription" "import_rejected_blob_created" { + name = local.import_rejected_eventgrid_subscription_name + scope = azurerm_storage_account.sa_import_rejected.id + + service_bus_queue_endpoint_id = azurerm_servicebus_queue.import_rejected_blob_created.id + + depends_on = [ + azurerm_eventgrid_system_topic.import_rejected_blob_created + ] +} + +resource "azurerm_eventgrid_event_subscription" "export_approved_blob_created" { + name = local.export_approved_eventgrid_subscription_name + scope = azurerm_storage_account.sa_export_approved.id + + service_bus_queue_endpoint_id = azurerm_servicebus_queue.export_approved_blob_created.id + + depends_on = [ + azurerm_eventgrid_system_topic.export_approved_blob_created + ] +} + diff --git a/templates/core/terraform/airlock/locals.tf b/templates/core/terraform/airlock/locals.tf new file mode 100644 index 0000000000..080b0e05d5 --- /dev/null +++ b/templates/core/terraform/airlock/locals.tf @@ -0,0 +1,36 @@ +locals { + # STorage AirLock EXternal + import_external_storage_name = lower(replace("stalexim${var.tre_id}", "-", "")) + # STorage AirLock InProgress IMport + import_in_progress_storage_name = lower(replace("stalipim${var.tre_id}", "-", "")) + # STorage AirLock REJected IMport + import_rejected_storage_name = lower(replace("stalrejim${var.tre_id}", "-", "")) + # STorage AirLock APProved EXPort + export_approved_storage_name = lower(replace("stalappexp${var.tre_id}", "-", "")) + + import_inprogress_sys_topic_name = "evgt-airlock-import-in-progress-${var.tre_id}" + import_rejected_sys_topic_name = "evgt-airlock-import-rejected-${var.tre_id}" + export_approved_sys_topic_name = "evgt-airlock-export-approved-${var.tre_id}" + + scan_result_topic_name = "evgt-airlock-scan-result-${var.tre_id}" + step_result_topic_name = "evgt-airlock-step-result-${var.tre_id}" + status_changed_topic_name = "evgt-airlock-status-changed-${var.tre_id}" + + step_result_queue_name = "airlock-step-result" + status_changed_queue_name = "airlock-status-changed" + scan_result_queue_name = "airlock-scan-result" + import_inprogress_queue_name = "airlock-import-in-progress-blob-created" + import_rejected_queue_name = "airlock-import-rejected-blob-created" + + import_approved_queue_name = "airlock-import-approved-blob-created" + export_inprogress_queue_name = "airlock-export-inprogress-blob-created" + export_rejected_queue_name = "airlock-export-rejected-blob-created" + export_approved_queue_name = "airlock-export-approved-blob-created" + + step_result_eventgrid_subscription_name = "evgs-airlock-update-status" + status_changed_eventgrid_subscription_name = "evgs-airlock-status-changed" + import_inprogress_eventgrid_subscription_name = "evgs-airlock-import-in-progress-blob-created" + import_rejected_eventgrid_subscription_name = "evgs-airlock-import-rejected-blob-created" + export_approved_eventgrid_subscription_name = "evgs-airlock-export-approved-blob-created" + +} diff --git a/templates/core/terraform/airlock/service_bus.tf b/templates/core/terraform/airlock/service_bus.tf new file mode 100644 index 0000000000..580ccb4bba --- /dev/null +++ b/templates/core/terraform/airlock/service_bus.tf @@ -0,0 +1,76 @@ +# Utilize the existing service bus - add new queue +data "azurerm_servicebus_namespace" "airlock_sb" { + name = "sb-${var.tre_id}" + resource_group_name = var.resource_group_name + +} + +resource "azurerm_servicebus_queue" "step_result" { + name = local.step_result_queue_name + namespace_id = data.azurerm_servicebus_namespace.airlock_sb.id + + enable_partitioning = false +} + +resource "azurerm_servicebus_queue" "status_changed" { + name = local.status_changed_queue_name + namespace_id = data.azurerm_servicebus_namespace.airlock_sb.id + + enable_partitioning = false +} + + +resource "azurerm_servicebus_queue" "import_in_progress_blob_created" { + name = local.import_inprogress_queue_name + namespace_id = data.azurerm_servicebus_namespace.airlock_sb.id + + enable_partitioning = false +} + + +resource "azurerm_servicebus_queue" "import_rejected_blob_created" { + name = local.import_rejected_queue_name + namespace_id = data.azurerm_servicebus_namespace.airlock_sb.id + + enable_partitioning = false +} + + +resource "azurerm_servicebus_queue" "scan_result" { + name = local.scan_result_queue_name + namespace_id = data.azurerm_servicebus_namespace.airlock_sb.id + + enable_partitioning = false +} + +resource "azurerm_servicebus_queue" "import_approved_blob_created" { + name = local.import_approved_queue_name + namespace_id = data.azurerm_servicebus_namespace.airlock_sb.id + + enable_partitioning = false +} + +resource "azurerm_servicebus_queue" "export_in_progress_blob_created" { + name = local.export_inprogress_queue_name + namespace_id = data.azurerm_servicebus_namespace.airlock_sb.id + + enable_partitioning = false +} + +resource "azurerm_servicebus_queue" "export_rejected_blob_created" { + name = local.export_rejected_queue_name + namespace_id = data.azurerm_servicebus_namespace.airlock_sb.id + + enable_partitioning = false +} + +# Approved export +resource "azurerm_servicebus_queue" "export_approved_blob_created" { + name = local.export_approved_queue_name + namespace_id = data.azurerm_servicebus_namespace.airlock_sb.id + + enable_partitioning = false +} + + + diff --git a/templates/core/terraform/airlock/storage_accounts.tf b/templates/core/terraform/airlock/storage_accounts.tf new file mode 100644 index 0000000000..4ddd07d9ea --- /dev/null +++ b/templates/core/terraform/airlock/storage_accounts.tf @@ -0,0 +1,141 @@ +# 'External' storage account - drop location for import +resource "azurerm_storage_account" "sa_external_import" { + name = local.import_external_storage_name + location = var.location + resource_group_name = var.resource_group_name + account_tier = "Standard" + account_replication_type = "GRS" + + # Don't allow anonymous access (unrelated to the 'public' networking rules) + allow_blob_public_access = false + + # Important! we rely on the fact that the blob craeted events are issued when the creation of the blobs are done. + # This is true ONLY when Hierarchical Namespace is DISABLED + is_hns_enabled = false + + tags = { + description = "airlock;import;external" + } + + lifecycle { ignore_changes = [tags] } +} + +# 'Approved' export +resource "azurerm_storage_account" "sa_export_approved" { + name = local.export_approved_storage_name + location = var.location + resource_group_name = var.resource_group_name + account_tier = "Standard" + account_replication_type = "GRS" + + # Don't allow anonymous access (unrelated to the 'public' networking rules) + allow_blob_public_access = false + + # Important! we rely on the fact that the blob craeted events are issued when the creation of the blobs are done. + # This is true ONLY when Hierarchical Namespace is DISABLED + is_hns_enabled = false + + tags = { + description = "airlock;export;approved" + } + + lifecycle { ignore_changes = [tags] } +} + +# 'In-Progress' storage account +resource "azurerm_storage_account" "sa_import_in_progress" { + name = local.import_in_progress_storage_name + location = var.location + resource_group_name = var.resource_group_name + account_tier = "Standard" + account_replication_type = "GRS" + allow_blob_public_access = false + + # Important! we rely on the fact that the blob craeted events are issued when the creation of the blobs are done. + # This is true ONLY when Hierarchical Namespace is DISABLED + is_hns_enabled = false + + tags = { + description = "airlock;import;in-progress" + } + + network_rules { + default_action = var.enable_local_debugging ? "Allow" : "Deny" + bypass = ["AzureServices"] + } + + lifecycle { ignore_changes = [tags] } +} + +data "azurerm_private_dns_zone" "blobcore" { + name = "privatelink.blob.core.windows.net" + resource_group_name = var.resource_group_name +} + +resource "azurerm_private_endpoint" "stg_ip_import_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 + + lifecycle { ignore_changes = [tags] } + + private_dns_zone_group { + name = "private-dns-zone-group-stg-import-ip" + private_dns_zone_ids = [data.azurerm_private_dns_zone.blobcore.id] + } + + private_service_connection { + name = "psc-stgipimport-${var.tre_id}" + private_connection_resource_id = azurerm_storage_account.sa_import_in_progress.id + is_manual_connection = false + subresource_names = ["Blob"] + } +} + + +# 'Rejected' storage account +resource "azurerm_storage_account" "sa_import_rejected" { + name = local.import_rejected_storage_name + location = var.location + resource_group_name = var.resource_group_name + account_tier = "Standard" + account_replication_type = "GRS" + allow_blob_public_access = false + + # Important! we rely on the fact that the blob craeted events are issued when the creation of the blobs are done. + # This is true ONLY when Hierarchical Namespace is DISABLED + is_hns_enabled = false + + tags = { + description = "airlock;import;rejected" + } + + network_rules { + default_action = var.enable_local_debugging ? "Allow" : "Deny" + bypass = ["AzureServices"] + } + + lifecycle { ignore_changes = [tags] } +} + +resource "azurerm_private_endpoint" "stgipimportpe" { + name = "stg-import-rej-blob-${var.tre_id}" + location = var.location + resource_group_name = var.resource_group_name + subnet_id = var.shared_subnet_id + + lifecycle { ignore_changes = [tags] } + + private_dns_zone_group { + name = "private-dns-zone-group-stg-import-rej" + private_dns_zone_ids = [data.azurerm_private_dns_zone.blobcore.id] + } + + private_service_connection { + name = "psc-stg-import-rej-${var.tre_id}" + private_connection_resource_id = azurerm_storage_account.sa_import_rejected.id + is_manual_connection = false + subresource_names = ["Blob"] + } +} diff --git a/templates/core/terraform/airlock/variables.tf b/templates/core/terraform/airlock/variables.tf new file mode 100644 index 0000000000..850cb96e1f --- /dev/null +++ b/templates/core/terraform/airlock/variables.tf @@ -0,0 +1,5 @@ +variable "tre_id" {} +variable "location" {} +variable "resource_group_name" {} +variable "shared_subnet_id" {} +variable "enable_local_debugging" {} diff --git a/templates/core/terraform/appgateway/staticweb.tf b/templates/core/terraform/appgateway/staticweb.tf index 79f9bdcbc9..0fe507e087 100644 --- a/templates/core/terraform/appgateway/staticweb.tf +++ b/templates/core/terraform/appgateway/staticweb.tf @@ -49,7 +49,7 @@ resource "azurerm_private_endpoint" "webpe" { } private_service_connection { - name = "psc-web--${local.staticweb_storage_name}" + name = "psc-web-${local.staticweb_storage_name}" private_connection_resource_id = azurerm_storage_account.staticweb.id is_manual_connection = false subresource_names = ["web"] diff --git a/templates/core/terraform/main.tf b/templates/core/terraform/main.tf index 8012cc6e3a..0eebb15722 100644 --- a/templates/core/terraform/main.tf +++ b/templates/core/terraform/main.tf @@ -72,6 +72,20 @@ 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 + enable_local_debugging = var.enable_local_debugging + + depends_on = [ + azurerm_servicebus_namespace.sb, + module.network + ] +} + module "resource_processor_vmss_porter" { count = var.resource_processor_type == "vmss_porter" ? 1 : 0 source = "./resource_processor/vmss_porter" diff --git a/templates/workspaces/base/porter.yaml b/templates/workspaces/base/porter.yaml index ab33b1912f..b5c077e387 100644 --- a/templates/workspaces/base/porter.yaml +++ b/templates/workspaces/base/porter.yaml @@ -1,6 +1,6 @@ --- name: tre-workspace-base -version: 0.3.3 +version: 0.3.4 description: "A base Azure TRE workspace" registry: azuretre diff --git a/templates/workspaces/base/terraform/airlock/eventgrid_topics.tf b/templates/workspaces/base/terraform/airlock/eventgrid_topics.tf new file mode 100644 index 0000000000..44ccf97b36 --- /dev/null +++ b/templates/workspaces/base/terraform/airlock/eventgrid_topics.tf @@ -0,0 +1,112 @@ +# System topics +resource "azurerm_eventgrid_system_topic" "import_approved_blob_created" { + name = local.import_approved_sys_topic_name + location = var.location + resource_group_name = var.ws_resource_group_name + source_arm_resource_id = azurerm_storage_account.sa_import_approved.id + topic_type = "Microsoft.Storage.StorageAccounts" + + tags = { + Publishers = "airlock;accepted-import-sa" + } + + depends_on = [ + azurerm_storage_account.sa_import_approved + ] + + lifecycle { ignore_changes = [tags] } +} + +resource "azurerm_eventgrid_system_topic" "export_inprogress_blob_created" { + name = local.export_inprogress_sys_topic_name + location = var.location + resource_group_name = var.ws_resource_group_name + source_arm_resource_id = azurerm_storage_account.sa_export_inprogress.id + topic_type = "Microsoft.Storage.StorageAccounts" + + tags = { + Publishers = "airlock;inprogress-export-sa" + } + + depends_on = [ + azurerm_storage_account.sa_export_inprogress + ] + + lifecycle { ignore_changes = [tags] } +} + + +resource "azurerm_eventgrid_system_topic" "export_rejected_blob_created" { + name = local.export_rejected_sys_topic_name + location = var.location + resource_group_name = var.ws_resource_group_name + source_arm_resource_id = azurerm_storage_account.sa_export_rejected.id + topic_type = "Microsoft.Storage.StorageAccounts" + + tags = { + Publishers = "airlock;rejected-export-sa" + } + + depends_on = [ + azurerm_storage_account.sa_export_rejected + ] + + lifecycle { ignore_changes = [tags] } +} + +data "azurerm_servicebus_namespace" "airlock_sb" { + name = "sb-${var.tre_id}" + resource_group_name = local.core_resource_group_name +} + +data "azurerm_servicebus_queue" "import_approved_blob_created" { + name = local.import_approved_queue_name + resource_group_name = local.core_resource_group_name + namespace_name = "sb-${var.tre_id}" +} + +data "azurerm_servicebus_queue" "export_in_progress_blob_created" { + name = local.export_inprogress_queue_name + resource_group_name = local.core_resource_group_name + namespace_name = "sb-${var.tre_id}" +} + +data "azurerm_servicebus_queue" "export_rejected_blob_created" { + name = local.export_rejected_queue_name + resource_group_name = local.core_resource_group_name + namespace_name = "sb-${var.tre_id}" +} + +## Subscriptions +resource "azurerm_eventgrid_event_subscription" "import_approved_blob_created" { + name = "import-approved-blob-created-${var.short_workspace_id}" + scope = azurerm_storage_account.sa_import_approved.id + + service_bus_queue_endpoint_id = data.azurerm_servicebus_queue.import_approved_blob_created.id + + depends_on = [ + azurerm_eventgrid_system_topic.import_approved_blob_created + ] +} + +resource "azurerm_eventgrid_event_subscription" "export_inprogress_blob_created" { + name = "export-inprogress-blob-created-${var.short_workspace_id}" + scope = azurerm_storage_account.sa_export_inprogress.id + + service_bus_queue_endpoint_id = data.azurerm_servicebus_queue.export_in_progress_blob_created.id + + depends_on = [ + azurerm_eventgrid_system_topic.export_inprogress_blob_created + ] +} + +resource "azurerm_eventgrid_event_subscription" "export_rejected_blob_created" { + name = "export-rejected-blob-created-${var.short_workspace_id}" + scope = azurerm_storage_account.sa_export_rejected.id + + service_bus_queue_endpoint_id = data.azurerm_servicebus_queue.export_rejected_blob_created.id + + depends_on = [ + azurerm_eventgrid_system_topic.export_rejected_blob_created + ] +} diff --git a/templates/workspaces/base/terraform/airlock/locals.tf b/templates/workspaces/base/terraform/airlock/locals.tf new file mode 100644 index 0000000000..698effb384 --- /dev/null +++ b/templates/workspaces/base/terraform/airlock/locals.tf @@ -0,0 +1,21 @@ +locals { + core_resource_group_name = "rg-${var.tre_id}" + workspace_resource_name_suffix = "${var.tre_id}-ws-${var.short_workspace_id}" + + import_approved_sys_topic_name = "evgt-airlock-import-approved-${local.workspace_resource_name_suffix}" + export_inprogress_sys_topic_name = "evgt-airlock-export-inprog-${local.workspace_resource_name_suffix}" + export_rejected_sys_topic_name = "evgt-airlock-export-rejected-${local.workspace_resource_name_suffix}" + + export_rejected_queue_name = "airlock-export-rejected-blob-created" + import_approved_queue_name = "airlock-import-approved-blob-created" + export_inprogress_queue_name = "airlock-export-inprogress-blob-created" + + # STorage AirLock APProved IMport + import_approved_storage_name = lower(replace("stalimapp${substr(local.workspace_resource_name_suffix, -8, -1)}", "-", "")) + # STorage AirLock INTernal EXport + export_internal_storage_name = lower(replace("stalexint${substr(local.workspace_resource_name_suffix, -8, -1)}", "-", "")) + # STorage AirLock InProgress EXport + export_inprogress_storage_name = lower(replace("stalexip${substr(local.workspace_resource_name_suffix, -8, -1)}", "-", "")) + # STorage AirLock REJected EXport + export_rejected_storage_name = lower(replace("stalexrej${substr(local.workspace_resource_name_suffix, -8, -1)}", "-", "")) +} diff --git a/templates/workspaces/base/terraform/airlock/storage_accounts.tf b/templates/workspaces/base/terraform/airlock/storage_accounts.tf new file mode 100644 index 0000000000..bd50a9056c --- /dev/null +++ b/templates/workspaces/base/terraform/airlock/storage_accounts.tf @@ -0,0 +1,172 @@ +# 'Approved' storage account +resource "azurerm_storage_account" "sa_import_approved" { + name = local.import_approved_storage_name + location = var.location + resource_group_name = var.ws_resource_group_name + account_tier = "Standard" + account_replication_type = "GRS" + allow_nested_items_to_be_public = false + + # Important! we rely on the fact that the blob craeted events are issued when the creation of the blobs are done. + # This is true ONLY when Hierarchical Namespace is DISABLED + is_hns_enabled = false + + tags = { + description = "airlock;import;approved" + } + + lifecycle { ignore_changes = [tags] } +} + +data "azurerm_private_dns_zone" "blobcore" { + name = "privatelink.blob.core.windows.net" + resource_group_name = local.core_resource_group_name +} + +resource "azurerm_private_endpoint" "import_approved_pe" { + name = "pe-sa-import-approved-blob-${var.short_workspace_id}" + location = var.location + resource_group_name = var.ws_resource_group_name + subnet_id = var.services_subnet_id + + lifecycle { ignore_changes = [tags] } + + private_dns_zone_group { + name = "private-dns-zone-group-sa-import-approved" + private_dns_zone_ids = [data.azurerm_private_dns_zone.blobcore.id] + } + + private_service_connection { + name = "psc-sa-import-approved-${var.short_workspace_id}" + private_connection_resource_id = azurerm_storage_account.sa_import_approved.id + is_manual_connection = false + subresource_names = ["Blob"] + } +} + + +# 'Drop' location for export +resource "azurerm_storage_account" "sa_export_internal" { + name = local.export_internal_storage_name + location = var.location + resource_group_name = var.ws_resource_group_name + account_tier = "Standard" + account_replication_type = "GRS" + allow_nested_items_to_be_public = false + + # Important! we rely on the fact that the blob craeted events are issued when the creation of the blobs are done. + # This is true ONLY when Hierarchical Namespace is DISABLED + is_hns_enabled = false + + tags = { + description = "airlock;export;internal" + } + + lifecycle { ignore_changes = [tags] } +} + + +resource "azurerm_private_endpoint" "export_internal_pe" { + name = "pe-sa-export-int-blob-${var.short_workspace_id}" + location = var.location + resource_group_name = var.ws_resource_group_name + subnet_id = var.services_subnet_id + + lifecycle { ignore_changes = [tags] } + + private_dns_zone_group { + name = "private-dns-zone-group-sa-export-int" + private_dns_zone_ids = [data.azurerm_private_dns_zone.blobcore.id] + } + + private_service_connection { + name = "psc-sa-export-int-${var.short_workspace_id}" + private_connection_resource_id = azurerm_storage_account.sa_export_internal.id + is_manual_connection = false + subresource_names = ["Blob"] + } +} + +# 'In-progress' location for export +resource "azurerm_storage_account" "sa_export_inprogress" { + name = local.export_inprogress_storage_name + location = var.location + resource_group_name = var.ws_resource_group_name + account_tier = "Standard" + account_replication_type = "GRS" + allow_nested_items_to_be_public = false + + # Important! we rely on the fact that the blob craeted events are issued when the creation of the blobs are done. + # This is true ONLY when Hierarchical Namespace is DISABLED + is_hns_enabled = false + + tags = { + description = "airlock;export;inprogress" + } + + lifecycle { ignore_changes = [tags] } +} + + +resource "azurerm_private_endpoint" "export_inprogress_pe" { + name = "pe-sa-ip-export-blob-${var.short_workspace_id}" + location = var.location + resource_group_name = var.ws_resource_group_name + subnet_id = var.services_subnet_id + + lifecycle { ignore_changes = [tags] } + + private_dns_zone_group { + name = "private-dns-zone-group-sa-export-ip" + private_dns_zone_ids = [data.azurerm_private_dns_zone.blobcore.id] + } + + private_service_connection { + name = "psc-sa-export-ip-${var.short_workspace_id}" + private_connection_resource_id = azurerm_storage_account.sa_export_inprogress.id + is_manual_connection = false + subresource_names = ["Blob"] + } +} + +# 'Rejected' location for export +resource "azurerm_storage_account" "sa_export_rejected" { + name = local.export_rejected_storage_name + location = var.location + resource_group_name = var.ws_resource_group_name + account_tier = "Standard" + account_replication_type = "GRS" + allow_nested_items_to_be_public = false + + # Important! we rely on the fact that the blob craeted events are issued when the creation of the blobs are done. + # This is true ONLY when Hierarchical Namespace is DISABLED + is_hns_enabled = false + + tags = { + description = "airlock;export;rejected" + } + + lifecycle { ignore_changes = [tags] } +} + + +resource "azurerm_private_endpoint" "export_rejected_pe" { + name = "pe-sa-export-rej-blob-${var.short_workspace_id}" + location = var.location + resource_group_name = var.ws_resource_group_name + subnet_id = var.services_subnet_id + + lifecycle { ignore_changes = [tags] } + + private_dns_zone_group { + name = "private-dns-zone-group-sa-export-rej" + private_dns_zone_ids = [data.azurerm_private_dns_zone.blobcore.id] + } + + private_service_connection { + name = "psc-sa-export-rej-${var.short_workspace_id}" + private_connection_resource_id = azurerm_storage_account.sa_export_rejected.id + is_manual_connection = false + subresource_names = ["Blob"] + } +} diff --git a/templates/workspaces/base/terraform/airlock/variables.tf b/templates/workspaces/base/terraform/airlock/variables.tf new file mode 100644 index 0000000000..7c9affab48 --- /dev/null +++ b/templates/workspaces/base/terraform/airlock/variables.tf @@ -0,0 +1,6 @@ +variable "location" {} +variable "tre_id" {} +variable "ws_resource_group_name" {} +variable "enable_local_debugging" {} +variable "services_subnet_id" {} +variable "short_workspace_id" {} diff --git a/templates/workspaces/base/terraform/workspace.tf b/templates/workspaces/base/terraform/workspace.tf index 45f8a84f30..76885bf653 100644 --- a/templates/workspaces/base/terraform/workspace.tf +++ b/templates/workspaces/base/terraform/workspace.tf @@ -34,3 +34,17 @@ module "aad" { azurerm_private_endpoint.kvpe ] } + +module "airlock" { + source = "./airlock" + location = var.location + tre_id = var.tre_id + ws_resource_group_name = azurerm_resource_group.ws.name + enable_local_debugging = true + services_subnet_id = module.network.services_subnet_id + short_workspace_id = local.short_workspace_id + + depends_on = [ + module.network, + ] +}