diff --git a/CHANGELOG.md b/CHANGELOG.md index 8fafc87bdb..3432f396cf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ ENHANCEMENTS: * Specify default_outbound_access_enabled = false setting for all subnets ([#4757](https://github.com/microsoft/AzureTRE/pull/4757)) * Pin all GitHub Actions workflow steps to full commit SHAs to prevent supply chain attacks plus update to latest releases ([#4886](https://github.com/microsoft/AzureTRE/pull/4886)) +* Configure airlock review VMs to use Nexus proxy for pip and conda package management ([#4009](https://github.com/microsoft/AzureTRE/issues/4009)) ## (0.28.0) (March 2, 2026) **BREAKING CHANGES** diff --git a/templates/workspace_services/guacamole/user_resources/guacamole-azure-export-reviewvm/porter.yaml b/templates/workspace_services/guacamole/user_resources/guacamole-azure-export-reviewvm/porter.yaml index b8fdcf7f0e..2c465b3ce9 100644 --- a/templates/workspace_services/guacamole/user_resources/guacamole-azure-export-reviewvm/porter.yaml +++ b/templates/workspace_services/guacamole/user_resources/guacamole-azure-export-reviewvm/porter.yaml @@ -1,7 +1,7 @@ --- schemaVersion: 1.0.0 name: tre-service-guacamole-export-reviewvm -version: 0.3.5 +version: 0.4.0 description: "An Azure TRE User Resource Template for reviewing Airlock export requests" dockerfile: Dockerfile.tmpl registry: azuretre diff --git a/templates/workspace_services/guacamole/user_resources/guacamole-azure-export-reviewvm/terraform/data.tf b/templates/workspace_services/guacamole/user_resources/guacamole-azure-export-reviewvm/terraform/data.tf index 5379f1a599..cd5998fffd 100644 --- a/templates/workspace_services/guacamole/user_resources/guacamole-azure-export-reviewvm/terraform/data.tf +++ b/templates/workspace_services/guacamole/user_resources/guacamole-azure-export-reviewvm/terraform/data.tf @@ -2,6 +2,11 @@ data "azurerm_resource_group" "ws" { name = "rg-${var.tre_id}-ws-${local.short_workspace_id}" } +data "azurerm_resource_group" "core" { + provider = azurerm.core + name = "rg-${var.tre_id}" +} + data "azurerm_virtual_network" "ws" { name = "vnet-${var.tre_id}-ws-${local.short_workspace_id}" resource_group_name = data.azurerm_resource_group.ws.name @@ -29,6 +34,12 @@ data "azurerm_linux_web_app" "guacamole" { resource_group_name = data.azurerm_resource_group.ws.name } +data "azurerm_public_ip" "app_gateway_ip" { + provider = azurerm.core + name = "pip-agw-${var.tre_id}" + resource_group_name = data.azurerm_resource_group.core.name +} + data "azurerm_private_endpoint_connection" "airlock_export_inprogress_pe" { name = "pe-sa-export-ip-blob-${local.short_workspace_id}" resource_group_name = data.azurerm_resource_group.ws.name diff --git a/templates/workspace_services/guacamole/user_resources/guacamole-azure-export-reviewvm/terraform/download_review_data.ps1 b/templates/workspace_services/guacamole/user_resources/guacamole-azure-export-reviewvm/terraform/download_review_data.ps1 index 76877d94e5..14fd1f93de 100644 --- a/templates/workspace_services/guacamole/user_resources/guacamole-azure-export-reviewvm/terraform/download_review_data.ps1 +++ b/templates/workspace_services/guacamole/user_resources/guacamole-azure-export-reviewvm/terraform/download_review_data.ps1 @@ -1,3 +1,35 @@ +$ErrorActionPreference = "Stop" + +# Configure pip to use Nexus proxy +$PipConfigFolderPath = "C:\ProgramData\pip\" +If(!(Test-Path $PipConfigFolderPath)) +{ + New-Item -ItemType Directory -Force -Path $PipConfigFolderPath +} + +$PipConfigFilePath = $PipConfigFolderPath + "pip.ini" + +$ConfigBody = @" +[global] +index = ${nexus_proxy_url}/repository/pypi/pypi +index-url = ${nexus_proxy_url}/repository/pypi/simple +trusted-host = ${nexus_proxy_url} +"@ + +# We need to write the ini file in UTF8 (No BOM) as pip won't understand Powershell's default encoding (unicode) +$Utf8NoBomEncoding = New-Object System.Text.UTF8Encoding $False +[System.IO.File]::WriteAllLines($PipConfigFilePath, $ConfigBody, $Utf8NoBomEncoding) + +### Anaconda Config +if( ${CondaConfig} -eq 1 ) +{ + conda config --add channels ${nexus_proxy_url}/repository/conda-mirror/main/ --system + conda config --add channels ${nexus_proxy_url}/repository/conda-repo/main/ --system + conda config --remove channels defaults --system + conda config --set channel_alias ${nexus_proxy_url}/repository/conda-mirror/ --system +} + +# Download review data $DownloadPath = $env:Public + "\Desktop\ReviewData" mkdir $DownloadPath az storage blob download-batch -d $DownloadPath -s '"${airlock_request_sas_url}"' diff --git a/templates/workspace_services/guacamole/user_resources/guacamole-azure-export-reviewvm/terraform/locals.tf b/templates/workspace_services/guacamole/user_resources/guacamole-azure-export-reviewvm/terraform/locals.tf index 33784b6275..2af4ee1aa8 100644 --- a/templates/workspace_services/guacamole/user_resources/guacamole-azure-export-reviewvm/terraform/locals.tf +++ b/templates/workspace_services/guacamole/user_resources/guacamole-azure-export-reviewvm/terraform/locals.tf @@ -27,6 +27,8 @@ locals { secure_boot_enabled = lookup(local.selected_image, "secure_boot_enabled", false) vtpm_enabled = lookup(local.selected_image, "vtpm_enabled", false) + nexus_proxy_url = "https://nexus-${data.azurerm_public_ip.app_gateway_ip.fqdn}" + cmk_name = "tre-encryption-${local.workspace_resource_name_suffix}" encryption_identity_name = "id-encryption-${var.tre_id}-${local.short_workspace_id}" } diff --git a/templates/workspace_services/guacamole/user_resources/guacamole-azure-export-reviewvm/terraform/main.tf b/templates/workspace_services/guacamole/user_resources/guacamole-azure-export-reviewvm/terraform/main.tf index 710c099764..fa9780671c 100644 --- a/templates/workspace_services/guacamole/user_resources/guacamole-azure-export-reviewvm/terraform/main.tf +++ b/templates/workspace_services/guacamole/user_resources/guacamole-azure-export-reviewvm/terraform/main.tf @@ -2,8 +2,9 @@ terraform { required_providers { azurerm = { - source = "hashicorp/azurerm" - version = "= 3.117.0" + source = "hashicorp/azurerm" + version = "= 3.117.0" + configuration_aliases = [azurerm.core] } random = { source = "hashicorp/random" @@ -43,3 +44,9 @@ provider "azurerm" { } storage_use_azuread = true } + +provider "azurerm" { + alias = "core" + features { + } +} diff --git a/templates/workspace_services/guacamole/user_resources/guacamole-azure-export-reviewvm/terraform/windowsvm.tf b/templates/workspace_services/guacamole/user_resources/guacamole-azure-export-reviewvm/terraform/windowsvm.tf index 78ef0b044b..9469f4c8e6 100644 --- a/templates/workspace_services/guacamole/user_resources/guacamole-azure-export-reviewvm/terraform/windowsvm.tf +++ b/templates/workspace_services/guacamole/user_resources/guacamole-azure-export-reviewvm/terraform/windowsvm.tf @@ -214,6 +214,8 @@ resource "azurerm_key_vault_secret" "windowsvm_password" { data "template_file" "download_review_data_script" { template = file("${path.module}/download_review_data.ps1") vars = { + nexus_proxy_url = local.nexus_proxy_url + CondaConfig = local.selected_image.conda_config ? 1 : 0 airlock_request_sas_url = var.airlock_request_sas_url } } diff --git a/templates/workspace_services/guacamole/user_resources/guacamole-azure-import-reviewvm/porter.yaml b/templates/workspace_services/guacamole/user_resources/guacamole-azure-import-reviewvm/porter.yaml index 685da7e5a3..603c6d3b20 100644 --- a/templates/workspace_services/guacamole/user_resources/guacamole-azure-import-reviewvm/porter.yaml +++ b/templates/workspace_services/guacamole/user_resources/guacamole-azure-import-reviewvm/porter.yaml @@ -1,7 +1,7 @@ --- schemaVersion: 1.0.0 name: tre-service-guacamole-import-reviewvm -version: 0.4.4 +version: 0.5.0 description: "An Azure TRE User Resource Template for reviewing Airlock import requests" dockerfile: Dockerfile.tmpl registry: azuretre diff --git a/templates/workspace_services/guacamole/user_resources/guacamole-azure-import-reviewvm/terraform/data.tf b/templates/workspace_services/guacamole/user_resources/guacamole-azure-import-reviewvm/terraform/data.tf index d3ce0f2eb3..4db7894169 100644 --- a/templates/workspace_services/guacamole/user_resources/guacamole-azure-import-reviewvm/terraform/data.tf +++ b/templates/workspace_services/guacamole/user_resources/guacamole-azure-import-reviewvm/terraform/data.tf @@ -2,6 +2,11 @@ data "azurerm_resource_group" "ws" { name = "rg-${var.tre_id}-ws-${local.short_workspace_id}" } +data "azurerm_resource_group" "core" { + provider = azurerm.core + name = "rg-${var.tre_id}" +} + data "azurerm_virtual_network" "ws" { name = "vnet-${var.tre_id}-ws-${local.short_workspace_id}" resource_group_name = data.azurerm_resource_group.ws.name @@ -23,6 +28,12 @@ data "azurerm_linux_web_app" "guacamole" { resource_group_name = data.azurerm_resource_group.ws.name } +data "azurerm_public_ip" "app_gateway_ip" { + provider = azurerm.core + name = "pip-agw-${var.tre_id}" + resource_group_name = data.azurerm_resource_group.core.name +} + data "azurerm_key_vault_key" "ws_encryption_key" { count = var.enable_cmk_encryption ? 1 : 0 name = local.cmk_name diff --git a/templates/workspace_services/guacamole/user_resources/guacamole-azure-import-reviewvm/terraform/download_review_data.ps1 b/templates/workspace_services/guacamole/user_resources/guacamole-azure-import-reviewvm/terraform/download_review_data.ps1 index 76877d94e5..14fd1f93de 100644 --- a/templates/workspace_services/guacamole/user_resources/guacamole-azure-import-reviewvm/terraform/download_review_data.ps1 +++ b/templates/workspace_services/guacamole/user_resources/guacamole-azure-import-reviewvm/terraform/download_review_data.ps1 @@ -1,3 +1,35 @@ +$ErrorActionPreference = "Stop" + +# Configure pip to use Nexus proxy +$PipConfigFolderPath = "C:\ProgramData\pip\" +If(!(Test-Path $PipConfigFolderPath)) +{ + New-Item -ItemType Directory -Force -Path $PipConfigFolderPath +} + +$PipConfigFilePath = $PipConfigFolderPath + "pip.ini" + +$ConfigBody = @" +[global] +index = ${nexus_proxy_url}/repository/pypi/pypi +index-url = ${nexus_proxy_url}/repository/pypi/simple +trusted-host = ${nexus_proxy_url} +"@ + +# We need to write the ini file in UTF8 (No BOM) as pip won't understand Powershell's default encoding (unicode) +$Utf8NoBomEncoding = New-Object System.Text.UTF8Encoding $False +[System.IO.File]::WriteAllLines($PipConfigFilePath, $ConfigBody, $Utf8NoBomEncoding) + +### Anaconda Config +if( ${CondaConfig} -eq 1 ) +{ + conda config --add channels ${nexus_proxy_url}/repository/conda-mirror/main/ --system + conda config --add channels ${nexus_proxy_url}/repository/conda-repo/main/ --system + conda config --remove channels defaults --system + conda config --set channel_alias ${nexus_proxy_url}/repository/conda-mirror/ --system +} + +# Download review data $DownloadPath = $env:Public + "\Desktop\ReviewData" mkdir $DownloadPath az storage blob download-batch -d $DownloadPath -s '"${airlock_request_sas_url}"' diff --git a/templates/workspace_services/guacamole/user_resources/guacamole-azure-import-reviewvm/terraform/locals.tf b/templates/workspace_services/guacamole/user_resources/guacamole-azure-import-reviewvm/terraform/locals.tf index 33784b6275..2af4ee1aa8 100644 --- a/templates/workspace_services/guacamole/user_resources/guacamole-azure-import-reviewvm/terraform/locals.tf +++ b/templates/workspace_services/guacamole/user_resources/guacamole-azure-import-reviewvm/terraform/locals.tf @@ -27,6 +27,8 @@ locals { secure_boot_enabled = lookup(local.selected_image, "secure_boot_enabled", false) vtpm_enabled = lookup(local.selected_image, "vtpm_enabled", false) + nexus_proxy_url = "https://nexus-${data.azurerm_public_ip.app_gateway_ip.fqdn}" + cmk_name = "tre-encryption-${local.workspace_resource_name_suffix}" encryption_identity_name = "id-encryption-${var.tre_id}-${local.short_workspace_id}" } diff --git a/templates/workspace_services/guacamole/user_resources/guacamole-azure-import-reviewvm/terraform/main.tf b/templates/workspace_services/guacamole/user_resources/guacamole-azure-import-reviewvm/terraform/main.tf index 710c099764..fa9780671c 100644 --- a/templates/workspace_services/guacamole/user_resources/guacamole-azure-import-reviewvm/terraform/main.tf +++ b/templates/workspace_services/guacamole/user_resources/guacamole-azure-import-reviewvm/terraform/main.tf @@ -2,8 +2,9 @@ terraform { required_providers { azurerm = { - source = "hashicorp/azurerm" - version = "= 3.117.0" + source = "hashicorp/azurerm" + version = "= 3.117.0" + configuration_aliases = [azurerm.core] } random = { source = "hashicorp/random" @@ -43,3 +44,9 @@ provider "azurerm" { } storage_use_azuread = true } + +provider "azurerm" { + alias = "core" + features { + } +} diff --git a/templates/workspace_services/guacamole/user_resources/guacamole-azure-import-reviewvm/terraform/windowsvm.tf b/templates/workspace_services/guacamole/user_resources/guacamole-azure-import-reviewvm/terraform/windowsvm.tf index 6d6fc53198..7361f4b219 100644 --- a/templates/workspace_services/guacamole/user_resources/guacamole-azure-import-reviewvm/terraform/windowsvm.tf +++ b/templates/workspace_services/guacamole/user_resources/guacamole-azure-import-reviewvm/terraform/windowsvm.tf @@ -135,6 +135,8 @@ resource "azurerm_key_vault_secret" "windowsvm_password" { data "template_file" "download_review_data_script" { template = file("${path.module}/download_review_data.ps1") vars = { + nexus_proxy_url = local.nexus_proxy_url + CondaConfig = local.selected_image.conda_config ? 1 : 0 airlock_request_sas_url = var.airlock_request_sas_url } }