diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2334b86c52..5dde300dff 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,6 +9,8 @@ FEATURES:
ENHANCEMENTS:
* Security updates aligning to Dependabot, MS Defender for Cloud and Synk ([#3796](https://github.com/microsoft/AzureTRE/issues/3796))
BUG FIXES:
+* Fix issue where updates fail as read only is not configured consistently on schema fields ([#3691](https://github.com/microsoft/AzureTRE/issues/3691))
+* When geting avaialble address spaces allow those allocated to deleted workspaces to be reassigned ([#3691](https://github.com/microsoft/AzureTRE/issues/3691))
* Update Python packages, and fix breaking changes ([#3764](https://github.com/microsoft/AzureTRE/issues/3764))
* Enabling support for more than 20 users/groups in Workspace API ([#3759](https://github.com/microsoft/AzureTRE/pull/3759 ))
* Airlock Import Review workspace uses dedicated DNS zone to prevent conflict with core ([#3767](https://github.com/microsoft/AzureTRE/pull/3767))
diff --git a/airlock_processor/BlobCreatedTrigger/__init__.py b/airlock_processor/BlobCreatedTrigger/__init__.py
index b55d1ac583..419b0d46af 100644
--- a/airlock_processor/BlobCreatedTrigger/__init__.py
+++ b/airlock_processor/BlobCreatedTrigger/__init__.py
@@ -32,10 +32,11 @@ def main(msg: func.ServiceBusMessage,
logging.error("environment variable 'ENABLE_MALWARE_SCANNING' does not exists. Cannot continue.")
raise
- if enable_malware_scanning:
+ if enable_malware_scanning and constants.STORAGE_ACCOUNT_NAME_IMPORT_INPROGRESS in topic:
# If malware scanning is enabled, the fact that the blob was created can be dismissed.
# It will be consumed by the malware scanning service
logging.info('Malware scanning is enabled. no action to perform.')
+ send_delete_event(dataDeletionEvent, json_body, request_id)
return
else:
logging.info('Malware scanning is disabled. Completing the submitted stage (moving to in_review).')
@@ -66,6 +67,10 @@ def main(msg: func.ServiceBusMessage,
event_time=datetime.datetime.utcnow(),
data_version=constants.STEP_RESULT_EVENT_DATA_VERSION))
+ send_delete_event(dataDeletionEvent, json_body, request_id)
+
+
+def send_delete_event(dataDeletionEvent: func.Out[func.EventGridOutputEvent], json_body, request_id):
# check blob metadata to find the blob it was copied from
blob_client = get_blob_client_from_blob_info(
*get_blob_info_from_topic_and_subject(topic=json_body["topic"], subject=json_body["subject"]))
diff --git a/airlock_processor/ScanResultTrigger/__init__.py b/airlock_processor/ScanResultTrigger/__init__.py
index 32909921f0..0d1891b5a8 100644
--- a/airlock_processor/ScanResultTrigger/__init__.py
+++ b/airlock_processor/ScanResultTrigger/__init__.py
@@ -14,7 +14,7 @@ def main(msg: func.ServiceBusMessage,
logging.info("Python ServiceBus queue trigger processed message - Malware scan result arrived!")
body = msg.get_body().decode('utf-8')
- logging.info('Python ServiceBus queue trigger processed message: %s', body)
+ logging.info(f'Python ServiceBus queue trigger processed message: {body}')
status_message = None
try:
@@ -34,7 +34,7 @@ def main(msg: func.ServiceBusMessage,
try:
json_body = json.loads(body)
blob_uri = json_body["data"]["blobUri"]
- verdict = json_body["data"]["verdict"]
+ verdict = json_body["data"]["scanResultType"]
except KeyError as e:
logging.error("body was not as expected {}", e)
raise e
@@ -46,10 +46,10 @@ def main(msg: func.ServiceBusMessage,
# Otherwise, move the request to the blocked stage
completed_step = constants.STAGE_SUBMITTED
if verdict == constants.NO_THREATS:
- logging.info('No malware were found in request id %s, moving to %s stage', request_id, constants.STAGE_IN_REVIEW)
+ logging.info(f'No malware were found in request id {request_id}, moving to {constants.STAGE_IN_REVIEW} stage')
new_status = constants.STAGE_IN_REVIEW
else:
- logging.info('Malware was found in request id %s, moving to %s stage', request_id, constants.STAGE_BLOCKING_INPROGRESS)
+ logging.info(f'Malware was found in request id {request_id}, moving to {constants.STAGE_BLOCKING_INPROGRESS} stage')
new_status = constants.STAGE_BLOCKING_INPROGRESS
status_message = verdict
diff --git a/airlock_processor/_version.py b/airlock_processor/_version.py
index ed9d4d87b6..49e0fc1e09 100644
--- a/airlock_processor/_version.py
+++ b/airlock_processor/_version.py
@@ -1 +1 @@
-__version__ = "0.7.4"
+__version__ = "0.7.0"
diff --git a/api_app/api/routes/workspaces.py b/api_app/api/routes/workspaces.py
index 8607e9fcf6..9a7fc9fe9c 100644
--- a/api_app/api/routes/workspaces.py
+++ b/api_app/api/routes/workspaces.py
@@ -7,7 +7,7 @@
from api.dependencies.database import get_repository
from api.dependencies.workspaces import get_operation_by_id_from_path, get_workspace_by_id_from_path, get_deployed_workspace_by_id_from_path, get_deployed_workspace_service_by_id_from_path, get_workspace_service_by_id_from_path, get_user_resource_by_id_from_path
-from db.errors import MajorVersionUpdateDenied, TargetTemplateVersionDoesNotExist, UserNotAuthorizedToUseTemplate, VersionDowngradeDenied
+from db.errors import InvalidInput, MajorVersionUpdateDenied, TargetTemplateVersionDoesNotExist, UserNotAuthorizedToUseTemplate, VersionDowngradeDenied
from db.repositories.operations import OperationRepository
from db.repositories.resource_templates import ResourceTemplateRepository
from db.repositories.resources_history import ResourceHistoryRepository
@@ -107,6 +107,8 @@ async def create_workspace(workspace_create: WorkspaceInCreate, response: Respon
except UserNotAuthorizedToUseTemplate as e:
logging.exception("User not authorized to use template")
raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail=str(e))
+ except InvalidInput as e:
+ raise HTTPException(status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, detail=str(e))
operation = await save_and_deploy_resource(
resource=workspace,
diff --git a/api_app/db/repositories/workspaces.py b/api_app/db/repositories/workspaces.py
index 42a46c31db..23af53109b 100644
--- a/api_app/db/repositories/workspaces.py
+++ b/api_app/db/repositories/workspaces.py
@@ -140,11 +140,11 @@ async def validate_address_space(self, address_space):
if (address_space is None):
raise InvalidInput("Missing 'address_space' from properties.")
- allocated_networks = [x.properties["address_space"] for x in await self.get_workspaces()]
+ allocated_networks = [x.properties["address_space"] for x in await self.get_active_workspaces()]
return is_network_available(allocated_networks, address_space)
async def get_new_address_space(self, cidr_netmask: int = 24):
- workspaces = await self.get_workspaces()
+ workspaces = await self.get_active_workspaces()
networks = [[x.properties.get("address_space")] for x in workspaces]
networks = networks + [x.properties.get("address_spaces", []) for x in workspaces]
networks = [i for s in networks for i in s if i is not None]
diff --git a/api_app/services/schema_service.py b/api_app/services/schema_service.py
index f01e20385d..65e98012aa 100644
--- a/api_app/services/schema_service.py
+++ b/api_app/services/schema_service.py
@@ -50,9 +50,17 @@ def enrich_template(original_template, extra_properties, is_update: bool = False
# this will help the UI render fields appropriately and know what it can send in a PATCH
if is_update:
for prop in template["properties"].values():
- if "updateable" not in prop.keys() or prop["updateable"] is not True:
+ if not prop.get("updateable", False):
prop["readOnly"] = True
+ if "allOf" in template:
+ for conditional_property in template["allOf"]:
+ for condition in ["then", "else"]:
+ if condition in conditional_property and "properties" in conditional_property[condition]:
+ for prop in conditional_property[condition]["properties"].values():
+ if not prop.get("updateable", False):
+ prop["readOnly"] = True
+
# if there is an 'allOf' property which is empty, the validator fails - so remove the key
if "allOf" in template and template["allOf"] is None:
template.pop("allOf")
diff --git a/api_app/tests_ma/test_db/test_repositories/test_workpaces_repository.py b/api_app/tests_ma/test_db/test_repositories/test_workpaces_repository.py
index 7ae495fade..79b9a5176a 100644
--- a/api_app/tests_ma/test_db/test_repositories/test_workpaces_repository.py
+++ b/api_app/tests_ma/test_db/test_repositories/test_workpaces_repository.py
@@ -209,16 +209,16 @@ async def test_get_address_space_based_on_size_with_custom_address_space_and_mis
@pytest.mark.asyncio
-@patch('db.repositories.workspaces.WorkspaceRepository.get_workspaces')
+@patch('db.repositories.workspaces.WorkspaceRepository.get_active_workspaces')
@patch('core.config.RESOURCE_LOCATION', "useast2")
@patch('core.config.TRE_ID', "9876")
@patch('core.config.CORE_ADDRESS_SPACE', "10.1.0.0/22")
@patch('core.config.TRE_ADDRESS_SPACE', "10.0.0.0/12")
-async def test_get_address_space_based_on_size_with_address_space_only(get_workspaces_mock, workspace_repo, basic_workspace_request, workspace):
+async def test_get_address_space_based_on_size_with_address_space_only(get_active_workspaces_mock, workspace_repo, basic_workspace_request, workspace):
workspace_with_address_space = copy.deepcopy(workspace)
workspace_with_address_space.properties["address_space"] = "10.1.4.0/24"
- get_workspaces_mock.return_value = [workspace_with_address_space]
+ get_active_workspaces_mock.return_value = [workspace_with_address_space]
workspace_to_create = basic_workspace_request
address_space = await workspace_repo.get_address_space_based_on_size(workspace_to_create.properties)
@@ -226,12 +226,12 @@ async def test_get_address_space_based_on_size_with_address_space_only(get_works
@pytest.mark.asyncio
-@patch('db.repositories.workspaces.WorkspaceRepository.get_workspaces')
+@patch('db.repositories.workspaces.WorkspaceRepository.get_active_workspaces')
@patch('core.config.RESOURCE_LOCATION', "useast2")
@patch('core.config.TRE_ID', "9876")
@patch('core.config.CORE_ADDRESS_SPACE', "10.1.0.0/22")
@patch('core.config.TRE_ADDRESS_SPACE', "10.0.0.0/12")
-async def test_get_address_space_based_on_size_with_address_space_and_address_spaces(get_workspaces_mock, workspace_repo, basic_workspace_request, workspace):
+async def test_get_address_space_based_on_size_with_address_space_and_address_spaces(get_active_workspaces_mock, workspace_repo, basic_workspace_request, workspace):
workspace_with_address_space = copy.deepcopy(workspace)
workspace_with_address_space.properties["address_space"] = "10.1.4.0/24"
@@ -242,7 +242,7 @@ async def test_get_address_space_based_on_size_with_address_space_and_address_sp
workspace_with_both.properties["address_spaces"] = ["10.1.7.0/24", "10.1.8.0/24"]
workspace_with_both.properties["address_space"] = "10.1.7.0/24"
- get_workspaces_mock.return_value = [workspace_with_address_space, workspace_with_address_spaces, workspace_with_both]
+ get_active_workspaces_mock.return_value = [workspace_with_address_space, workspace_with_address_spaces, workspace_with_both]
workspace_to_create = basic_workspace_request
address_space = await workspace_repo.get_address_space_based_on_size(workspace_to_create.properties)
diff --git a/config.sample.yaml b/config.sample.yaml
index af790054a8..403c70c874 100644
--- a/config.sample.yaml
+++ b/config.sample.yaml
@@ -31,7 +31,7 @@ tre:
core_app_service_plan_sku: P1v2
resource_processor_vmss_sku: Standard_B2s
enable_swagger: true
- enable_airlock_malware_scanning: false
+ enable_airlock_malware_scanning: true
# TODO: move to RP default with https://github.com/microsoft/AzureTRE/issues/2948
workspace_app_service_plan_sku: P1v2
diff --git a/core/terraform/.terraform.lock.hcl b/core/terraform/.terraform.lock.hcl
index f8c3f1b7c8..ea690ac29e 100644
--- a/core/terraform/.terraform.lock.hcl
+++ b/core/terraform/.terraform.lock.hcl
@@ -1,6 +1,26 @@
# This file is maintained automatically by "terraform init".
# Manual edits may be lost in future updates.
+provider "registry.terraform.io/azure/azapi" {
+ version = "1.9.0"
+ constraints = "1.9.0"
+ hashes = [
+ "h1:zaLH2Owmj61RX2G1Cy6VDy8Ttfzx+lDsSCyiu5cXkm4=",
+ "zh:349569471fbf387feaaf8b88da1690669e201147c342f905e5eb03df42b3cf87",
+ "zh:54346d5fb78cbad3eb7cfd96e1dd7ce4f78666cabaaccfec6ee9437476330018",
+ "zh:64b799da915ea3a9a58ac7a926c6a31c59fd0d911687804d8e815eda88c5580b",
+ "zh:9336ed9e112555e0fda8af6be9ba21478e30117d79ba662233311d9560d2b7c6",
+ "zh:a8aace9897b28ea0b2dbd7a3be3df033e158af40412c9c7670be0956f216ed7e",
+ "zh:ab23df7de700d9e785009a4ca9ceb38ae1ab894a13f5788847f15d018556f415",
+ "zh:b4f13f0b13560a67d427c71c85246f8920f98987120341830071df4535842053",
+ "zh:e58377bf36d8a14d28178a002657865ee17446182dac03525fd43435e41a1b5c",
+ "zh:ea5db4acc6413fd0fe6b35981e58cdc9850f5f3118031cc3d2581de511aee6aa",
+ "zh:f0b32c06c6bd4e4af2c02a62be07b947766aeeb09289a03f21aba16c2fd3c60f",
+ "zh:f1518e766a90c257d7eb36d360dafaf311593a4a9352ff8db0bcfe0ed8cf45ae",
+ "zh:fa89e84cff0776b5b61ff27049b1d8ed52040bd58c81c4628890d644a6fb2989",
+ ]
+}
+
provider "registry.terraform.io/hashicorp/azurerm" {
version = "3.74.0"
constraints = ">= 3.8.0, >= 3.16.0, 3.74.0"
diff --git a/core/terraform/airlock/eventgrid_topics.tf b/core/terraform/airlock/eventgrid_topics.tf
index 5bbe26e219..991325d2e1 100644
--- a/core/terraform/airlock/eventgrid_topics.tf
+++ b/core/terraform/airlock/eventgrid_topics.tf
@@ -161,6 +161,36 @@ resource "azurerm_private_endpoint" "eg_data_deletion" {
}
}
+resource "azurerm_eventgrid_topic" "scan_result" {
+ count = var.enable_malware_scanning ? 1 : 0
+ name = local.scan_result_topic_name
+ location = var.location
+ resource_group_name = var.resource_group_name
+ # This is mandatory for the scan result to be published since private networks are not supported yet
+ public_network_access_enabled = true
+
+ identity {
+ type = "SystemAssigned"
+ }
+
+ tags = merge(var.tre_core_tags, {
+ Publishers = "Airlock Processor;"
+ })
+
+ lifecycle { ignore_changes = [tags] }
+}
+
+resource "azurerm_role_assignment" "servicebus_sender_scan_result" {
+ count = var.enable_malware_scanning ? 1 : 0
+ scope = var.airlock_servicebus.id
+ role_definition_name = "Azure Service Bus Data Sender"
+ principal_id = azurerm_eventgrid_topic.scan_result[0].identity[0].principal_id
+
+ depends_on = [
+ azurerm_eventgrid_topic.scan_result
+ ]
+}
+
# System topic
resource "azurerm_eventgrid_system_topic" "import_inprogress_blob_created" {
name = local.import_inprogress_sys_topic_name
@@ -395,6 +425,23 @@ resource "azurerm_eventgrid_event_subscription" "data_deletion" {
]
}
+resource "azurerm_eventgrid_event_subscription" "scan_result" {
+ count = var.enable_malware_scanning ? 1 : 0
+ name = local.scan_result_eventgrid_subscription_name
+ scope = azurerm_eventgrid_topic.scan_result[0].id
+
+ service_bus_queue_endpoint_id = azurerm_servicebus_queue.scan_result.id
+
+ delivery_identity {
+ type = "SystemAssigned"
+ }
+
+ depends_on = [
+ azurerm_eventgrid_topic.scan_result,
+ azurerm_role_assignment.servicebus_sender_scan_result
+ ]
+}
+
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
diff --git a/core/terraform/airlock/locals.tf b/core/terraform/airlock/locals.tf
index 6a108f79a9..37f7fdead0 100644
--- a/core/terraform/airlock/locals.tf
+++ b/core/terraform/airlock/locals.tf
@@ -23,6 +23,7 @@ locals {
status_changed_topic_name = "evgt-airlock-status-changed-${local.topic_name_suffix}"
notification_topic_name = "evgt-airlock-notification-${local.topic_name_suffix}"
data_deletion_topic_name = "evgt-airlock-data-deletion-${local.topic_name_suffix}"
+ scan_result_topic_name = "evgt-airlock-scan-result-${local.topic_name_suffix}"
step_result_queue_name = "airlock-step-result"
status_changed_queue_name = "airlock-status-changed"
@@ -35,6 +36,7 @@ locals {
step_result_eventgrid_subscription_name = "evgs-airlock-update-status"
status_changed_eventgrid_subscription_name = "evgs-airlock-status-changed"
data_deletion_eventgrid_subscription_name = "evgs-airlock-data-deletion"
+ scan_result_eventgrid_subscription_name = "evgs-airlock-scan-result"
import_inprogress_eventgrid_subscription_name = "evgs-airlock-import-in-progress-blob-created"
import_rejected_eventgrid_subscription_name = "evgs-airlock-import-rejected-blob-created"
import_blocked_eventgrid_subscription_name = "evgs-airlock-import-blocked-blob-created"
diff --git a/core/terraform/airlock/main.tf b/core/terraform/airlock/main.tf
index 89542d8ef7..cea72a09e8 100644
--- a/core/terraform/airlock/main.tf
+++ b/core/terraform/airlock/main.tf
@@ -5,6 +5,10 @@ terraform {
source = "hashicorp/azurerm"
version = ">= 3.16"
}
+ azapi = {
+ source = "Azure/azapi"
+ version = ">= 1.9.0"
+ }
local = {
source = "hashicorp/local"
version = ">= 2.2"
diff --git a/core/terraform/airlock/storage_accounts.tf b/core/terraform/airlock/storage_accounts.tf
index 3bfa4c7cdf..6a76b97f02 100644
--- a/core/terraform/airlock/storage_accounts.tf
+++ b/core/terraform/airlock/storage_accounts.tf
@@ -111,6 +111,32 @@ resource "azurerm_storage_account" "sa_import_in_progress" {
lifecycle { ignore_changes = [tags] }
}
+
+# Enable Airlock Malware Scanning on Core TRE
+resource "azapi_resource_action" "enable_defender_for_storage" {
+ count = var.enable_malware_scanning ? 1 : 0
+ type = "Microsoft.Security/defenderForStorageSettings@2022-12-01-preview"
+ resource_id = "${azurerm_storage_account.sa_import_in_progress.id}/providers/Microsoft.Security/defenderForStorageSettings/current"
+ method = "PUT"
+
+ body = jsonencode({
+ properties = {
+ isEnabled = true
+ malwareScanning = {
+ onUpload = {
+ isEnabled = true
+ capGBPerMonth = 5000
+ },
+ scanResultsEventGridTopicResourceId = azurerm_eventgrid_topic.scan_result[0].id
+ }
+ sensitiveDataDiscovery = {
+ isEnabled = false
+ }
+ overrideSubscriptionLevelSettings = true
+ }
+ })
+}
+
resource "azurerm_private_endpoint" "stg_import_inprogress_pe" {
name = "pe-stg-import-inprogress-blob-${var.tre_id}"
location = var.location
diff --git a/core/terraform/main.tf b/core/terraform/main.tf
index 3727a8ab01..a065e9fb8c 100644
--- a/core/terraform/main.tf
+++ b/core/terraform/main.tf
@@ -17,11 +17,19 @@ terraform {
source = "hashicorp/http"
version = "~> 3.2.0"
}
+ azapi = {
+ source = "Azure/azapi"
+ version = "~> 1.9.0"
+ }
}
backend "azurerm" {}
}
+provider "azapi" {
+ use_msi = var.arm_use_msi
+}
+
provider "azurerm" {
features {
key_vault {
diff --git a/core/terraform/variables.tf b/core/terraform/variables.tf
index 5766776051..4ccf9b8428 100644
--- a/core/terraform/variables.tf
+++ b/core/terraform/variables.tf
@@ -130,6 +130,13 @@ variable "arm_environment" {
description = "Used as an environment variable in the VMSS to set the Azure cloud for Terraform"
}
+variable "arm_use_msi" {
+ type = bool
+ default = false
+ description = "Used as an environment variable to determine if Terraform should use a managed identity"
+}
+
+
variable "stateful_resources_locked" {
type = bool
default = true
@@ -161,9 +168,6 @@ variable "public_deployment_ip_address" {
default = ""
}
-# Important note: it is NOT enough to simply enable the malware scanning on. Further, manual, steps are required
-# in order to actually set up the scanner. Setting this property to True without supplying a scanner will result
-# in airlock requests being stuck in the in-progress stage.
variable "enable_airlock_malware_scanning" {
type = bool
default = false
diff --git a/core/version.txt b/core/version.txt
index 8d8e3b7702..3e2f46a3a3 100644
--- a/core/version.txt
+++ b/core/version.txt
@@ -1 +1 @@
-__version__ = "0.8.9"
+__version__ = "0.9.0"
diff --git a/docs/azure-tre-overview/airlock.md b/docs/azure-tre-overview/airlock.md
index 7e4d86c707..791b024e71 100644
--- a/docs/azure-tre-overview/airlock.md
+++ b/docs/azure-tre-overview/airlock.md
@@ -66,7 +66,8 @@ This storage location is external for import (`stalimex`) or internal for export
The user will be able to upload a file to the provided storage location, using any tool of their preference: [Azure Storage Explorer](https://azure.microsoft.com/en-us/features/storage-explorer/) or [AzCopy](https://docs.microsoft.com/en-us/azure/storage/common/storage-use-azcopy-v10) which is a command line tool.
The user Submits the request (TRE API call) starting the data movement (to the `stalimip` - import in-progress or `stalexip` - export in-progress). The airlock request is now in state **Submitted**.
-If enabled, the Security Scanning is started. In the case that security flaws are found, the request state becomes **Blocking In-progress** while the data is moved to blocked storage (either import blocked `stalimblocked` or export blocked `stalexblocked`). In this case, the request is finalized with the state **Blocked By Scan**.
+If enabled, the Malware Scanning is started. The scan is done using Microsoft Defender for Storage, which is described in details [here](https://learn.microsoft.com/en-us/azure/defender-for-cloud/defender-for-storage-introduction).
+In the case that security flaws are found, the request state becomes **Blocking In-progress** while the data is moved to blocked storage (either import blocked `stalimblocked` or export blocked `stalexblocked`). In this case, the request is finalized with the state **Blocked By Scan**.
If the Security Scanning does not identify any security flaws, the request state becomes **In-Review**. Simultaneously, a notification is sent to the Airlock Manager user. The user needs to ask for the container URL using the TRE API (SAS token + URL with READ permission).
> The Security Scanning can be disabled, changing the request state from **Submitted** straight to **In-Review**.
diff --git a/docs/tre-admins/environment-variables.md b/docs/tre-admins/environment-variables.md
index a998198d81..0b56fd92b2 100644
--- a/docs/tre-admins/environment-variables.md
+++ b/docs/tre-admins/environment-variables.md
@@ -31,7 +31,7 @@
| `API_CLIENT_ID` | Generated when following [pre-deployment steps](./setup-instructions/setup-auth-entities.md) guide. Client id of the "TRE API". |
| `API_CLIENT_SECRET` | Generated when following [pre-deployment steps](./setup-instructions/setup-auth-entities.md) guide. Client secret of the "TRE API". |
| `STATEFUL_RESOURCES_LOCKED` | If set to `false` locks on stateful resources won't be created. A recommended setting for developers. |
-| `ENABLE_AIRLOCK_MALWARE_SCANNING` | If False, Airlock requests will skip the malware scanning stage. If set to True, Setting up a scanner manually is required! |
+| `ENABLE_AIRLOCK_MALWARE_SCANNING` | If False, Airlock requests will skip the malware scanning stage. If set to True, Defender for Storage will be enabled. |
| `ENABLE_LOCAL_DEBUGGING` | Set to `false` by default. Setting this to `true` will ensure that Azure resources are accessible from your local development machine. (e.g. ServiceBus and Cosmos) |
| `PUBLIC_DEPLOYMENT_IP_ADDRESS` | The public IP address of the machine that is deploying TRE. (Your desktop or the build agents). In certain locations a dynamic script to retrieve this from [https://ipecho.net/plain](https://ipecho.net/plain) does not work. If this is the case, then you can 'hardcode' your IP. |
| `RESOURCE_PROCESSOR_VMSS_SKU` | The SKU of the VMMS to use for the resource processing VM. |
diff --git a/templates/workspace_services/guacamole/guacamole-server/docker/Dockerfile b/templates/workspace_services/guacamole/guacamole-server/docker/Dockerfile
index f6089ef92a..c1ab1ca34a 100644
--- a/templates/workspace_services/guacamole/guacamole-server/docker/Dockerfile
+++ b/templates/workspace_services/guacamole/guacamole-server/docker/Dockerfile
@@ -11,9 +11,9 @@ RUN bash /tmp/maven_package_and_exit_succesfully.sh
FROM scratch as test-results
COPY --from=client_build /target/surefire-reports/* /
-FROM guacamole/guacd:1.5.2
+FROM guacamole/guacd:1.5.3
-ARG GUACAMOLE_AZURE_VERSION=0.3.3
+ARG GUACAMOLE_AZURE_VERSION=0.3.4
ENV DEBIAN_FRONTEND=noninteractive
@@ -26,7 +26,7 @@ RUN apk add --update --no-cache wget openssh openjdk11-jre \
ENV CATALINA_BASE=/usr/share/tomcat9/
RUN TOMCAT_ARCHIVE="tomcat.tar.gz" && \
- TOMCAT_VER="9.0.76" && \
+ TOMCAT_VER="9.0.83" && \
wget -O "$TOMCAT_ARCHIVE" -N "https://archive.apache.org/dist/tomcat/tomcat-9/v${TOMCAT_VER}/bin/apache-tomcat-${TOMCAT_VER}.tar.gz" --progress=dot:giga && \
tar xzf "$TOMCAT_ARCHIVE" && \
rm -f "$TOMCAT_ARCHIVE" && \
@@ -53,7 +53,7 @@ COPY ./docker/services /etc/services.d/
COPY --from=client_build /target/lib/* "${GUACAMOLE_LIB}"
COPY --from=client_build "/target/guacamole-auth-tre-${GUACAMOLE_AZURE_VERSION}.jar" "${GUACAMOLE_HOME}/extensions/"
-RUN wget -O "${GUACAMOLE_HOME}/guacamole.war" "http://apache.org/dyn/closer.cgi?action=download&filename=guacamole/1.5.2/binary/guacamole-1.5.2.war" --progress=dot:giga
+RUN wget -O "${GUACAMOLE_HOME}/guacamole.war" "http://apache.org/dyn/closer.cgi?action=download&filename=guacamole/1.5.3/binary/guacamole-1.5.3.war" --progress=dot:giga
ENV OAUTH2_PROXY_HOME=/etc/oauth2-proxy
RUN OAUTH2_PROXY_ARCHIVE=oauth2-proxy.tar.gz && \
@@ -64,7 +64,7 @@ RUN OAUTH2_PROXY_ARCHIVE=oauth2-proxy.tar.gz && \
COPY ./docker/index.jsp "$CATALINA_BASE"/webapps/ROOT/index.jsp
-RUN wget -O "/tmp/applicationinsights-agent.jar" "https://github.com/microsoft/ApplicationInsights-Java/releases/download/3.4.14/applicationinsights-agent-3.4.14.jar" --progress=dot:giga
+RUN wget -O "/tmp/applicationinsights-agent.jar" "https://github.com/microsoft/ApplicationInsights-Java/releases/download/3.4.18/applicationinsights-agent-3.4.18.jar" --progress=dot:giga
ENV CATALINA_OPTS="$CATALINA_OPTS -javaagent:/tmp/applicationinsights-agent.jar"
ENTRYPOINT [ "/init" ]
diff --git a/templates/workspace_services/guacamole/guacamole-server/docker/version.txt b/templates/workspace_services/guacamole/guacamole-server/docker/version.txt
index 777f190df0..8088f75131 100644
--- a/templates/workspace_services/guacamole/guacamole-server/docker/version.txt
+++ b/templates/workspace_services/guacamole/guacamole-server/docker/version.txt
@@ -1 +1 @@
-__version__ = "0.8.0"
+__version__ = "0.8.1"
diff --git a/templates/workspace_services/guacamole/guacamole-server/guacamole-auth-azure/pom.xml b/templates/workspace_services/guacamole/guacamole-server/guacamole-auth-azure/pom.xml
index a661366e6a..075cab92a8 100644
--- a/templates/workspace_services/guacamole/guacamole-server/guacamole-auth-azure/pom.xml
+++ b/templates/workspace_services/guacamole/guacamole-server/guacamole-auth-azure/pom.xml
@@ -6,7 +6,7 @@
org.apache.guacamole
guacamole-auth-tre
- 0.3.3
+ 0.3.4
jar
guacamole-azure-tre
@@ -41,7 +41,7 @@
org.apache.guacamole
guacamole-ext
- 1.5.2
+ 1.5.3
provided
@@ -59,7 +59,7 @@
org.json
json
- 20230618
+ 20231013
org.apache.httpcomponents
diff --git a/templates/workspace_services/guacamole/porter.yaml b/templates/workspace_services/guacamole/porter.yaml
index f58bafd202..18a50e9b83 100644
--- a/templates/workspace_services/guacamole/porter.yaml
+++ b/templates/workspace_services/guacamole/porter.yaml
@@ -1,7 +1,7 @@
---
schemaVersion: 1.0.0
name: tre-service-guacamole
-version: 0.10.5
+version: 0.10.6
description: "An Azure TRE service for Guacamole"
dockerfile: Dockerfile.tmpl
registry: azuretre
diff --git a/templates/workspaces/airlock-import-review/template_schema.json b/templates/workspaces/airlock-import-review/template_schema.json
index be6c1ccf01..e05a0d87e7 100644
--- a/templates/workspaces/airlock-import-review/template_schema.json
+++ b/templates/workspaces/airlock-import-review/template_schema.json
@@ -94,13 +94,15 @@
"client_id": {
"type": "string",
"title": "Application (Client) ID",
- "description": "The AAD Application Registration ID for the workspace."
+ "description": "The AAD Application Registration ID for the workspace.",
+ "updateable": true
},
"client_secret": {
"type": "string",
"title": "Application (Client) Secret",
"description": "The AAD Application Registration secret for the workspace. This value will be stored in the Workspace Key Vault.",
- "sensitive": true
+ "sensitive": true,
+ "updateable": true
}
},
"required": [
@@ -113,12 +115,14 @@
"type": "boolean",
"title": "Create AAD Groups for each workspace role",
"description": "Create AAD Groups for the workspace roles. If this is set to true, the workspace will create new AAD Groups.",
- "default": false
+ "default": false,
+ "updateable": true
},
"aad_redirect_uris": {
"type": "array",
"title": "AAD Redirect URIs",
"description": "Redirect URIs for the AAD app in Automatic Auth mode",
+ "updateable": true,
"items": {
"title": "items",
"type": "object",
diff --git a/templates/workspaces/base/porter.yaml b/templates/workspaces/base/porter.yaml
index ee0e27050c..f7a1802477 100644
--- a/templates/workspaces/base/porter.yaml
+++ b/templates/workspaces/base/porter.yaml
@@ -1,7 +1,7 @@
---
schemaVersion: 1.0.0
name: tre-workspace-base
-version: 1.5.1
+version: 1.5.3
description: "A base Azure TRE workspace"
dockerfile: Dockerfile.tmpl
registry: azuretre
diff --git a/templates/workspaces/base/template_schema.json b/templates/workspaces/base/template_schema.json
index 2ae9c9d504..3d6cdf0e16 100644
--- a/templates/workspaces/base/template_schema.json
+++ b/templates/workspaces/base/template_schema.json
@@ -81,7 +81,8 @@
"type": "boolean",
"title": "Configure Review VMs",
"description": "Allow TRE to automatically create and delete review VMs for airlock approvals",
- "default": false
+ "default": false,
+ "updateable": true
}
}
}
@@ -108,6 +109,7 @@
"title": "Airlock Review Config",
"default": null,
"description": "Configuration for Airlock Review feature. Needs to be set up after workspace creation",
+ "updateable": true,
"properties": {
"import": {
"title": "Import Review Settings",
@@ -206,13 +208,15 @@
"client_id": {
"type": "string",
"title": "Application (Client) ID",
- "description": "The AAD Application Registration ID for the workspace."
+ "description": "The AAD Application Registration ID for the workspace.",
+ "updateable": true
},
"client_secret": {
"type": "string",
"title": "Application (Client) Secret",
"description": "The AAD Application Registration secret for the workspace. This value will be stored in the Workspace Key Vault.",
- "sensitive": true
+ "sensitive": true,
+ "updateable": true
}
},
"required": [
@@ -225,12 +229,14 @@
"type": "boolean",
"title": "Create AAD Groups for each workspace role",
"description": "Create AAD Groups for the workspace roles. If this is set to true, the workspace will create new AAD Groups.",
- "default": false
+ "default": false,
+ "updateable": true
},
"aad_redirect_uris": {
"type": "array",
"title": "AAD Redirect URIs",
"description": "Redirect URIs for the AAD app in Automatic Auth mode",
+ "updateable": true,
"items": {
"title": "items",
"type": "object",
diff --git a/templates/workspaces/unrestricted/porter.yaml b/templates/workspaces/unrestricted/porter.yaml
index fefa9df140..fd3a07583c 100644
--- a/templates/workspaces/unrestricted/porter.yaml
+++ b/templates/workspaces/unrestricted/porter.yaml
@@ -1,7 +1,7 @@
---
schemaVersion: 1.0.0
name: tre-workspace-unrestricted
-version: 0.11.1
+version: 0.11.4
description: "A base Azure TRE workspace"
dockerfile: Dockerfile.tmpl
registry: azuretre
diff --git a/templates/workspaces/unrestricted/template_schema.json b/templates/workspaces/unrestricted/template_schema.json
index 40e051d568..3fbaa16a3a 100644
--- a/templates/workspaces/unrestricted/template_schema.json
+++ b/templates/workspaces/unrestricted/template_schema.json
@@ -206,13 +206,15 @@
"client_id": {
"type": "string",
"title": "Application (Client) ID",
- "description": "The AAD Application Registration ID for the workspace."
+ "description": "The AAD Application Registration ID for the workspace.",
+ "updateable": true
},
"client_secret": {
"type": "string",
"title": "Application (Client) Secret",
"description": "The AAD Application Registration secret for the workspace. This value will be stored in the Workspace Key Vault.",
- "sensitive": true
+ "sensitive": true,
+ "updateable": true
}
},
"required": [
@@ -225,12 +227,14 @@
"type": "boolean",
"title": "Create AAD Groups for each workspace role",
"description": "Create AAD Groups for the workspace roles. If this is set to true, the workspace will create new AAD Groups.",
- "default": false
+ "default": false,
+ "updateable": true
},
"aad_redirect_uris": {
"type": "array",
"title": "AAD Redirect URIs",
"description": "Redirect URIs for the AAD app in Automatic Auth mode",
+ "updateable": true,
"items": {
"title": "items",
"type": "object",