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/_version.py b/api_app/_version.py index 53d3b0d45b..9027351fd5 100644 --- a/api_app/_version.py +++ b/api_app/_version.py @@ -1 +1 @@ -__version__ = "0.16.7" +__version__ = "0.16.8" 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",