diff --git a/.github/actions/devcontainer_run_command/action.yml b/.github/actions/devcontainer_run_command/action.yml index c9b8ec7f3e..6a2d11486e 100644 --- a/.github/actions/devcontainer_run_command/action.yml +++ b/.github/actions/devcontainer_run_command/action.yml @@ -89,6 +89,12 @@ inputs: TF_VAR_api_client_secret: description: "The API Client Secret." required: false + TF_VAR_application_admin_client_id: + description: "The Client ID of an identity that can manage the AAD Applications." + required: false + TF_VAR_application_admin_client_secret: + description: "The Client secret of an identity that can manage the AAD Applications." + required: false ACR_NAME: description: "The Container Registry that holds our Research images." required: false @@ -98,6 +104,9 @@ inputs: BUNDLE_TYPE: description: "The Bundle type (workspace / Workspace-service / User Resource)." required: false + WORKSPACE_SERVICE_NAME: + description: "The workspace service name for the bundle you are registering." + required: false IS_API_SECURED: description: "Indicates if the API endpoint has valid TLS certificate and if we validate it during E2E." required: false @@ -156,6 +165,8 @@ runs: TF_VAR_aad_tenant_id: "${{ inputs.AAD_TENANT_ID }}" TF_VAR_api_client_id: "${{ inputs.TF_VAR_api_client_id }}" TF_VAR_api_client_secret: "${{ inputs.TF_VAR_api_client_secret }}" + TF_VAR_application_admin_client_id: "${{ inputs.TF_VAR_application_admin_client_id }}" + TF_VAR_application_admin_client_secret: "${{ inputs.TF_VAR_application_admin_client_secret }}" TF_VAR_acr_name: ${{ inputs.ACR_NAME }} IS_API_SECURED: ${{ inputs.IS_API_SECURED }} run: | @@ -168,6 +179,7 @@ runs: -e TF_IN_AUTOMATION="${{ inputs.TF_IN_AUTOMATION }}" \ -e USE_ENV_VARS_NOT_FILES="${{ inputs.USE_ENV_VARS_NOT_FILES }}" \ -e BUNDLE_TYPE="${{ inputs.BUNDLE_TYPE }}" \ + -e WORKSPACE_SERVICE_NAME="${{ inputs.WORKSPACE_SERVICE_NAME }}" \ -e LOCATION="${{ inputs.LOCATION }}" \ -e TF_VAR_location="${{ inputs.LOCATION }}" \ -e RESOURCE_LOCATION="${{ inputs.LOCATION }}" \ @@ -183,6 +195,8 @@ runs: -e TF_VAR_aad_tenant_id \ -e TF_VAR_api_client_id \ -e TF_VAR_api_client_secret \ + -e TF_VAR_application_admin_client_id \ + -e TF_VAR_application_admin_client_secret \ -e TF_VAR_arm_subscription_id="${{ inputs.ARM_SUBSCRIPTION_ID }}" \ -e TF_VAR_swagger_ui_client_id \ -e TF_VAR_core_address_space \ diff --git a/.github/linters/.yaml-lint.yml b/.github/linters/.yaml-lint.yml index 49db36d299..a7448e6873 100644 --- a/.github/linters/.yaml-lint.yml +++ b/.github/linters/.yaml-lint.yml @@ -5,3 +5,5 @@ rules: line-length: max: 120 # Keep this updated with the editorconfig file level: warning + comments: + min-spaces-from-content: 1 # Used to follow prettier standard: https://github.com/prettier/prettier/pull/10926 diff --git a/.github/workflows/build_validation_develop.yml b/.github/workflows/build_validation_develop.yml index a811cace59..7a70ea5c29 100644 --- a/.github/workflows/build_validation_develop.yml +++ b/.github/workflows/build_validation_develop.yml @@ -47,8 +47,9 @@ jobs: - name: Lint code base # the slim image is 2GB smaller and we don't use the extra stuff - # Moved this after the Terraform checks above due something similar to this issue: https://github.com/github/super-linter/issues/2433 - uses: github/super-linter/slim@v4.9.3 + # Moved this after the Terraform checks above due something similar to this issue: + # https://github.com/github/super-linter/issues/2433 + uses: github/super-linter/slim@v4.9.4 env: # Until https://github.com/github/super-linter/commit/ec0662756da93f1e3aad4df049712df7d764d143 is released # we need to set the correct plugin directory (which is incorrectly set to github/home/.tflint.d/plugins by default) @@ -64,6 +65,5 @@ jobs: JAVA_FILE_NAME: checkstyle.xml VALIDATE_BASH: true VALIDATE_BASH_EXEC: true - # https://github.com/microsoft/AzureTRE/issues/1723 tracks re-instating VALIDATE_GITHUB_ACTIONS - # Note: in the meantime, the `.github/scripts/run-test.sh` script includes the `actionlint` checks) - # VALIDATE_GITHUB_ACTIONS: true + VALIDATE_GITHUB_ACTIONS: true + VALIDATE_DOCKERFILE_HADOLINT: true diff --git a/.github/workflows/deploy_tre.yml b/.github/workflows/deploy_tre.yml index ca1ddb2c90..e694d0e6ec 100644 --- a/.github/workflows/deploy_tre.yml +++ b/.github/workflows/deploy_tre.yml @@ -22,8 +22,7 @@ jobs: uses: ./.github/workflows/deploy_tre_reusable.yml with: ciGitRef: ${{ github.ref }} - runExtendedTests: true - runSharedServicesTests: true + e2eTestsCustomSelector: "extended or shared_services" secrets: AAD_TENANT_ID: ${{ secrets.AAD_TENANT_ID }} ACR_NAME: ${{ secrets.ACR_NAME }} diff --git a/.github/workflows/deploy_tre_branch.yml b/.github/workflows/deploy_tre_branch.yml index cd18f19b6c..ca448003be 100644 --- a/.github/workflows/deploy_tre_branch.yml +++ b/.github/workflows/deploy_tre_branch.yml @@ -9,10 +9,10 @@ name: Deploy Azure TRE (branch) on: # yamllint disable-line rule:truthy workflow_dispatch: inputs: - runExtendedTests: - description: Run the extended tests as part of the deployment? - type: boolean - default: false + e2eTestsCustomSelector: + description: A pytest marker selector for the e2e tests to be run + type: string + default: "" required: false runSharedServicesTests: description: Run the shared services tests as part of the deployment? @@ -20,6 +20,7 @@ on: # yamllint disable-line rule:truthy default: false required: false + # This will prevent multiple runs of this entire workflow. # We should NOT cancel in progress runs as that can destabilize the environment. concurrency: "${{ github.workflow }}-${{ github.ref }}" @@ -54,9 +55,7 @@ jobs: uses: ./.github/workflows/deploy_tre_reusable.yml with: ciGitRef: ${{ github.ref }} - # testing input against string 'true' - see https://github.com/actions/runner/issues/1483 - runExtendedTests: ${{ github.event.inputs.runExtendedTests == 'true' }} - runSharedSevicesTests: ${{ github.event.inputs.runSharedServicesTests == 'true' }} + e2eTestsCustomSelector: ${{ github.event.inputs.e2eTestsCustomSelector }} secrets: AAD_TENANT_ID: ${{ secrets.AAD_TENANT_ID }} ACR_NAME: ${{ format('tre{0}', needs.prepare-not-main.outputs.refid) }} diff --git a/.github/workflows/deploy_tre_reusable.yml b/.github/workflows/deploy_tre_reusable.yml index 27a99233ab..207a79399e 100644 --- a/.github/workflows/deploy_tre_reusable.yml +++ b/.github/workflows/deploy_tre_reusable.yml @@ -9,17 +9,19 @@ on: # yamllint disable-line rule:truthy type: string required: false prHeadSha: - description: For PR builds where GITHUB_REF isn't set to the PR (e.g. comment trigger), pass the PR's head SHA commit here + description: >- + For PR builds where GITHUB_REF isn't set to the PR (e.g. comment trigger), + pass the PR's head SHA commit here type: string required: false ciGitRef: description: The git ref to use in annotations to associate a deployment with the code that triggered it type: string required: true - runExtendedTests: - description: Controls whether to run the extended tests as part of the deployment - type: boolean - default: false + e2eTestsCustomSelector: + description: The pytest marker selector for the e2e tests to be run + type: string + default: "" required: false runSharedServicesTests: description: Controls whether to run the shared services tests as part of the deployment @@ -212,10 +214,7 @@ jobs: strategy: fail-fast: true matrix: - target: [ - build-and-push-api, - build-and-push-resource-processor, - build-and-push-gitea] + target: [build-and-push-api, build-and-push-resource-processor] steps: - name: Checkout @@ -277,18 +276,18 @@ jobs: TRE_ID: "${{ secrets.TRE_ID }}" LOCATION: ${{ secrets.LOCATION }} ACR_NAME: ${{ secrets.ACR_NAME }} - TF_VAR_terraform_state_container_name: - ${{ secrets.TF_STATE_CONTAINER }} + TF_VAR_terraform_state_container_name: ${{ secrets.TF_STATE_CONTAINER }} TF_VAR_mgmt_resource_group_name: ${{ secrets.MGMT_RESOURCE_GROUP }} - TF_VAR_mgmt_storage_account_name: - ${{ secrets.STATE_STORAGE_ACCOUNT_NAME }} + TF_VAR_mgmt_storage_account_name: ${{ secrets.STATE_STORAGE_ACCOUNT_NAME }} TF_VAR_core_address_space: ${{ secrets.CORE_ADDRESS_SPACE }} TF_VAR_tre_address_space: ${{ secrets.TRE_ADDRESS_SPACE }} TF_VAR_swagger_ui_client_id: "${{ secrets.SWAGGER_UI_CLIENT_ID }}" TF_VAR_api_client_id: "${{ secrets.API_CLIENT_ID }}" TF_VAR_api_client_secret: "${{ secrets.API_CLIENT_SECRET }}" - TF_VAR_keyvault_purge_protection_enabled: "${{ github.ref == 'refs/heads/main' && inputs.prRef == '' && true || false }}" - TF_VAR_stateful_resources_locked: "${{ github.ref == 'refs/heads/main' && inputs.prRef == '' && true || false }}" + TF_VAR_keyvault_purge_protection_enabled: + "${{ github.ref == 'refs/heads/main' && inputs.prRef == '' && true || false }}" + TF_VAR_stateful_resources_locked: + "${{ github.ref == 'refs/heads/main' && inputs.prRef == '' && true || false }}" deploy_tre: name: Deploy TRE @@ -326,18 +325,20 @@ jobs: TRE_ID: "${{ secrets.TRE_ID }}" LOCATION: ${{ secrets.LOCATION }} ACR_NAME: ${{ secrets.ACR_NAME }} - TF_VAR_terraform_state_container_name: - ${{ secrets.TF_STATE_CONTAINER }} + TF_VAR_terraform_state_container_name: ${{ secrets.TF_STATE_CONTAINER }} TF_VAR_mgmt_resource_group_name: ${{ secrets.MGMT_RESOURCE_GROUP }} - TF_VAR_mgmt_storage_account_name: - ${{ secrets.STATE_STORAGE_ACCOUNT_NAME }} + TF_VAR_mgmt_storage_account_name: ${{ secrets.STATE_STORAGE_ACCOUNT_NAME }} TF_VAR_core_address_space: ${{ secrets.CORE_ADDRESS_SPACE }} TF_VAR_tre_address_space: ${{ secrets.TRE_ADDRESS_SPACE }} TF_VAR_swagger_ui_client_id: "${{ secrets.SWAGGER_UI_CLIENT_ID }}" TF_VAR_api_client_id: "${{ secrets.API_CLIENT_ID }}" TF_VAR_api_client_secret: "${{ secrets.API_CLIENT_SECRET }}" - TF_VAR_keyvault_purge_protection_enabled: "${{ github.ref == 'refs/heads/main' && inputs.prRef == '' && true || false }}" - TF_VAR_stateful_resources_locked: "${{ github.ref == 'refs/heads/main' && inputs.prRef == '' && true || false }}" + TF_VAR_application_admin_client_id: "${{ secrets.API_CLIENT_ID }}" + TF_VAR_application_admin_client_secret: "${{ secrets.API_CLIENT_SECRET }}" + TF_VAR_keyvault_purge_protection_enabled: + "${{ github.ref == 'refs/heads/main' && inputs.prRef == '' && true || false }}" + TF_VAR_stateful_resources_locked: + "${{ github.ref == 'refs/heads/main' && inputs.prRef == '' && true || false }}" - name: API Healthcheck uses: ./.github/actions/devcontainer_run_command @@ -361,18 +362,18 @@ jobs: TRE_ID: "${{ secrets.TRE_ID }}" LOCATION: ${{ secrets.LOCATION }} ACR_NAME: ${{ secrets.ACR_NAME }} - TF_VAR_terraform_state_container_name: - ${{ secrets.TF_STATE_CONTAINER }} + TF_VAR_terraform_state_container_name: ${{ secrets.TF_STATE_CONTAINER }} TF_VAR_mgmt_resource_group_name: ${{ secrets.MGMT_RESOURCE_GROUP }} - TF_VAR_mgmt_storage_account_name: - ${{ secrets.STATE_STORAGE_ACCOUNT_NAME }} + TF_VAR_mgmt_storage_account_name: ${{ secrets.STATE_STORAGE_ACCOUNT_NAME }} TF_VAR_core_address_space: ${{ secrets.CORE_ADDRESS_SPACE }} TF_VAR_tre_address_space: ${{ secrets.TRE_ADDRESS_SPACE }} TF_VAR_swagger_ui_client_id: "${{ secrets.SWAGGER_UI_CLIENT_ID }}" TF_VAR_api_client_id: "${{ secrets.API_CLIENT_ID }}" TF_VAR_api_client_secret: "${{ secrets.API_CLIENT_SECRET }}" - TF_VAR_keyvault_purge_protection_enabled: "${{ github.ref == 'refs/heads/main' && inputs.prRef == '' && true || false }}" - TF_VAR_stateful_resources_locked: "${{ github.ref == 'refs/heads/main' && inputs.prRef == '' && true || false }}" + TF_VAR_keyvault_purge_protection_enabled: + "${{ github.ref == 'refs/heads/main' && inputs.prRef == '' && true || false }}" + TF_VAR_stateful_resources_locked: + "${{ github.ref == 'refs/heads/main' && inputs.prRef == '' && true || false }}" publish_bundles: name: Publish Bundles @@ -404,6 +405,8 @@ jobs: BUNDLE_DIR: "./templates/shared_services/sonatype-nexus/"} - {BUNDLE_TYPE: "shared_service", BUNDLE_DIR: "./templates/shared_services/gitea/"} + - {BUNDLE_TYPE: "user_resource", + BUNDLE_DIR: "./templates/workspace_services/guacamole/user_resources/guacamole-azure-windowsvm"} environment: CICD steps: - name: Checkout @@ -437,7 +440,7 @@ jobs: strategy: fail-fast: true matrix: - target: [build-and-push-guacamole] + target: [build-and-push-gitea, build-and-push-guacamole] steps: - name: Checkout @@ -493,6 +496,9 @@ jobs: BUNDLE_DIR: "./templates/shared_services/sonatype-nexus"} - {BUNDLE_TYPE: "shared_service", BUNDLE_DIR: "./templates/shared_services/gitea"} + - {BUNDLE_TYPE: "user_resource", + WORKSPACE_SERVICE_NAME: "tre-service-guacamole", + BUNDLE_DIR: "./templates/workspace_services/guacamole/user_resources/guacamole-azure-windowsvm"} environment: CICD steps: - name: Checkout @@ -523,6 +529,7 @@ jobs: TRE_ID: "${{ secrets.TRE_ID }}" LOCATION: "${{ secrets.LOCATION }}" BUNDLE_TYPE: ${{ matrix.BUNDLE_TYPE }} + WORKSPACE_SERVICE_NAME: ${{ matrix.WORKSPACE_SERVICE_NAME }} deploy_shared_services: name: Deploy shared services @@ -538,7 +545,7 @@ jobs: # then the default checkout will apply ref: ${{ inputs.prRef }} - - name: Register/deploy firewall + - name: Deploy firewall uses: ./.github/actions/devcontainer_run_command with: COMMAND: "make deploy-shared-service DIR=./templates/shared_services/firewall/ BUNDLE_TYPE=shared_service" @@ -581,18 +588,18 @@ jobs: TRE_ID: "${{ secrets.TRE_ID }}" LOCATION: ${{ secrets.LOCATION }} ACR_NAME: ${{ secrets.ACR_NAME }} - TF_VAR_terraform_state_container_name: - ${{ secrets.TF_STATE_CONTAINER }} + TF_VAR_terraform_state_container_name: ${{ secrets.TF_STATE_CONTAINER }} TF_VAR_mgmt_resource_group_name: ${{ secrets.MGMT_RESOURCE_GROUP }} - TF_VAR_mgmt_storage_account_name: - ${{ secrets.STATE_STORAGE_ACCOUNT_NAME }} + TF_VAR_mgmt_storage_account_name: ${{ secrets.STATE_STORAGE_ACCOUNT_NAME }} TF_VAR_core_address_space: ${{ secrets.CORE_ADDRESS_SPACE }} TF_VAR_tre_address_space: ${{ secrets.TRE_ADDRESS_SPACE }} TF_VAR_swagger_ui_client_id: "${{ secrets.SWAGGER_UI_CLIENT_ID }}" TF_VAR_api_client_id: "${{ secrets.API_CLIENT_ID }}" TF_VAR_api_client_secret: "${{ secrets.API_CLIENT_SECRET }}" - TF_VAR_keyvault_purge_protection_enabled: "${{ github.ref == 'refs/heads/main' && inputs.prRef == '' && true || false }}" - TF_VAR_stateful_resources_locked: "${{ github.ref == 'refs/heads/main' && inputs.prRef == '' && true || false }}" + TF_VAR_keyvault_purge_protection_enabled: + "${{ github.ref == 'refs/heads/main' && inputs.prRef == '' && true || false }}" + TF_VAR_stateful_resources_locked: + "${{ github.ref == 'refs/heads/main' && inputs.prRef == '' && true || false }}" e2e_tests_smoke: name: "Run E2E Tests (Smoke)" @@ -659,13 +666,14 @@ jobs: with: files: "./e2e_tests/pytest_e2e_smoke.xml" - e2e_tests_extended: - name: "Run E2E Tests (Extended)" - if: ${{ inputs.runExtendedTests }} + + e2e_tests_custom: + name: "Run E2E Tests" + if: ${{ inputs.e2eTestsCustomSelector != '' }} runs-on: ubuntu-latest environment: CICD needs: [deploy_shared_services, build_additional_images] - timeout-minutes: 50 + timeout-minutes: 120 steps: - name: Checkout uses: actions/checkout@v2 @@ -675,10 +683,10 @@ jobs: # then the default checkout will apply ref: ${{ inputs.prRef }} - - name: Run E2E Tests (Extended) + - name: Run E2E Tests uses: ./.github/actions/devcontainer_run_command with: - COMMAND: "make test-e2e-extended" + COMMAND: "make test-e2e-custom SELECTOR='${{ inputs.e2eTestsCustomSelector }}'" ACTIONS_ACR_NAME: ${{ secrets.ACTIONS_ACR_NAME }} ACTIONS_ACR_URI: ${{ secrets.ACTIONS_ACR_URI }} ACTIONS_ACR_PASSWORD: ${{ secrets.ACTIONS_ACR_PASSWORD }} @@ -702,14 +710,14 @@ jobs: if: always() uses: actions/upload-artifact@v2 with: - name: E2E Test (Extended) Results - path: "./e2e_tests/pytest_e2e_extended.xml" + name: E2E Test Results + path: "./e2e_tests/pytest_e2e_custom.xml" - name: Publish Test Results if: always() uses: EnricoMi/publish-unit-test-result-action@v1 with: - files: "./e2e_tests/pytest_e2e_extended.xml" + files: "./e2e_tests/pytest_e2e_custom.xml" e2e_tests_shared_services: name: "Run E2E Tests (Shared Services)" @@ -765,7 +773,7 @@ jobs: summary: name: Summary Notification - needs: [e2e_tests_smoke, e2e_tests_extended, e2e_tests_shared_services] + needs: [e2e_tests_smoke, e2e_tests_custom] runs-on: ubuntu-latest if: ${{ always() && (github.ref == 'refs/heads/main' && inputs.prRef == '') }} environment: CICD diff --git a/.github/workflows/pr_comment_bot.yml b/.github/workflows/pr_comment_bot.yml index 2faa79da24..e42457f535 100644 --- a/.github/workflows/pr_comment_bot.yml +++ b/.github/workflows/pr_comment_bot.yml @@ -134,15 +134,19 @@ jobs: run_test: # Run the tests with the re-usable workflow needs: [pr_comment] - if: ${{ needs.pr_comment.outputs.command == 'run-tests' || needs.pr_comment.outputs.command == 'run-tests-extended' || needs.pr_comment.outputs.command == 'run-tests-shared-services' }} + if: | + ${{ needs.pr_comment.outputs.command == 'run-tests' || + needs.pr_comment.outputs.command == 'run-tests-extended' || + needs.pr_comment.outputs.command == 'run-tests-shared-services' }} name: Deploy PR uses: ./.github/workflows/deploy_tre_reusable.yml with: prRef: ${{ needs.pr_comment.outputs.prRef }} prHeadSha: ${{ needs.pr_comment.outputs.prHeadSha }} ciGitRef: ${{ needs.pr_comment.outputs.ciGitRef }} - runExtendedTests: ${{ needs.pr_comment.outputs.command == 'run-tests-extended' }} - runSharedServicesTests: ${{ needs.pr_comment.outputs.command == 'run-tests-shared-services' }} + e2eTestsCustomSelector: >- + ${{ (needs.pr_comment.outputs.command == 'run-tests-extended' && 'extended') || + (needs.pr_comment.outputs.command == 'run-tests-shared-services' && 'shared_sevices') }} secrets: AAD_TENANT_ID: ${{ secrets.AAD_TENANT_ID }} ACR_NAME: ${{ format('tre{0}', needs.pr_comment.outputs.prRefId) }} diff --git a/.gitignore b/.gitignore index e40719411e..a31822e18b 100644 --- a/.gitignore +++ b/.gitignore @@ -201,8 +201,7 @@ templates/core/terraform/scripts/validation.txt templates/core/terraform/plan # Test results -e2e_tests/pytest_e2e_smoke.xml -e2e_tests/pytest_e2e_extended.xml +e2e_tests/pytest_e2e_*.xml e2e_tests/workspace_id.txt pytest_api_unit.xml pytest_api_unit_failed diff --git a/Makefile b/Makefile index 8a098e0f20..28f76bad0d 100644 --- a/Makefile +++ b/Makefile @@ -10,7 +10,7 @@ FULL_IMAGE_NAME_PREFIX:=`echo "${FULL_CONTAINER_REGISTRY_NAME}/${IMAGE_NAME_PREF target_title = @echo -e "\n\e[34m»»» 🧩 \e[96m$(1)\e[0m..." all: bootstrap mgmt-deploy images tre-deploy -images: build-and-push-api build-and-push-resource-processor build-and-push-gitea build-and-push-guacamole build-and-push-mlflow +images: build-and-push-api build-and-push-resource-processor build-and-push-gitea build-and-push-guacamole build-and-push-mlflow build-and-push-airlock-processor build-and-push-api: build-api-image push-api-image build-and-push-resource-processor: build-resource-processor-vm-porter-image push-resource-processor-vm-porter-image @@ -18,6 +18,7 @@ build-and-push-gitea: build-gitea-image push-gitea-image build-and-push-guacamole: build-guacamole-image push-guacamole-image build-and-push-mlflow: build-mlflow-image push-mlflow-image tre-deploy: deploy-core build-and-deploy-ui deploy-shared-services db-migrate show-core-output +build-and-push-airlock-processor: build-airlock-processor push-airlock-processor deploy-shared-services: $(MAKE) firewall-install \ && . ./devops/scripts/load_env.sh ./templates/core/.env \ @@ -88,6 +89,9 @@ build-guacamole-image: build-mlflow-image: $(call build_image,"mlflow-server","${MAKEFILE_DIR}/templates/workspace_services/mlflow/mlflow-server/version.txt","${MAKEFILE_DIR}/templates/workspace_services/mlflow/mlflow-server/docker/Dockerfile","${MAKEFILE_DIR}/templates/workspace_services/mlflow/mlflow-server") +build-airlock-processor: + $(call build_image,"airlock-processor","${MAKEFILE_DIR}/airlock_processor/_version.py","${MAKEFILE_DIR}/airlock_processor/Dockerfile","${MAKEFILE_DIR}/airlock_processor/") + firewall-install: $(MAKE) bundle-build DIR=${MAKEFILE_DIR}/templates/shared_services/firewall/ \ && $(MAKE) bundle-publish DIR=${MAKEFILE_DIR}/templates/shared_services/firewall/ \ @@ -138,6 +142,9 @@ push-guacamole-image: push-mlflow-image: $(call push_image,"mlflow-server","${MAKEFILE_DIR}/templates/workspace_services/mlflow/mlflow-server/version.txt") +push-airlock-processor: + $(call push_image,"airlock-processor","${MAKEFILE_DIR}/airlock_processor/_version.py") + # # These targets are for a graceful migration of Firewall # # from terraform state in Core to a Shared Service. # # See https://github.com/microsoft/AzureTRE/issues/1177 @@ -241,8 +248,9 @@ lint: -e VALIDATE_BASH=true \ -e VALIDATE_BASH_EXEC=true \ -e VALIDATE_GITHUB_ACTIONS=true \ + -e VALIDATE_DOCKERFILE_HADOLINT=true \ -v $${LOCAL_WORKSPACE_FOLDER}:/tmp/lint \ - github/super-linter:slim-v4 + github/super-linter:slim-v4.9.4 bundle-build: $(call target_title, "Building ${DIR} bundle with Porter") \ @@ -370,6 +378,7 @@ prepare-for-e2e: && $(call shared_service_bundle,sonatype-nexus) \ && $(call shared_service_bundle,gitea) \ && $(call user_resource_bundle,guacamole,guacamole-dev-vm) + && $(call user_resource_bundle,guacamole,guacamole-azure-windowsvm) test-e2e-smoke: $(call target_title, "Running E2E smoke tests") && \ @@ -386,6 +395,11 @@ test-e2e-shared-services: cd e2e_tests && \ python -m pytest -m shared_services --verify $${IS_API_SECURED:-true} --junit-xml pytest_e2e_shared_services.xml +test-e2e-custom: + $(call target_title, "Running E2E shared service tests") && \ + cd e2e_tests && \ + python -m pytest -m "${SELECTOR}" --verify $${IS_API_SECURED:-true} --junit-xml pytest_e2e_custom.xml + setup-local-debugging: $(call target_title,"Setting up the ability to debug the API and Resource Processor") \ && . ${MAKEFILE_DIR}/devops/scripts/check_dependencies.sh nodocker \ diff --git a/airlock_processor/.dockerignore b/airlock_processor/.dockerignore new file mode 100644 index 0000000000..46cc430915 --- /dev/null +++ b/airlock_processor/.dockerignore @@ -0,0 +1 @@ +local.settings.json diff --git a/airlock_processor/.gitignore b/airlock_processor/.gitignore new file mode 100644 index 0000000000..e04adb7cae --- /dev/null +++ b/airlock_processor/.gitignore @@ -0,0 +1,48 @@ +bin +obj +csx +.vs +edge +Publish + +*.user +*.suo +*.cscfg +*.Cache +project.lock.json + +/packages +/TestResults + +/tools/NuGet.exe +/App_Data +/secrets +/data +.secrets +appsettings.json +local.settings.json + +node_modules +dist + +# Local python packages +.python_packages/ + +# Python Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# Azurite artifacts +__blobstorage__ +__queuestorage__ +__azurite_db*__.json diff --git a/airlock_processor/Dockerfile b/airlock_processor/Dockerfile new file mode 100644 index 0000000000..44ced2a5fb --- /dev/null +++ b/airlock_processor/Dockerfile @@ -0,0 +1,11 @@ +# To enable ssh & remote debugging on app service change the base image to the one below +# FROM mcr.microsoft.com/azure-functions/python:3.0-python3.8-appservice +FROM mcr.microsoft.com/azure-functions/python:3.0-python3.8 + +ENV AzureWebJobsScriptRoot=/home/site/wwwroot \ + AzureFunctionsJobHost__Logging__Console__IsEnabled=true + +COPY requirements.txt / +RUN pip install --no-cache-dir -r /requirements.txt + +COPY . /home/site/wwwroot diff --git a/airlock_processor/StatusChangedQueueTrigger/__init__.py b/airlock_processor/StatusChangedQueueTrigger/__init__.py new file mode 100644 index 0000000000..861562f1d6 --- /dev/null +++ b/airlock_processor/StatusChangedQueueTrigger/__init__.py @@ -0,0 +1,18 @@ +import logging + +import azure.functions as func +import datetime + + +def main(msg: func.ServiceBusMessage, + outputEvent: func.Out[func.EventGridOutputEvent]): + + logging.info('Python ServiceBus queue trigger processed message: %s', msg.get_body().decode('utf-8')) + outputEvent.set( + func.EventGridOutputEvent( + id="step-result-id", + data={"tag1": "value1", "tag2": "value2"}, + subject="test-subject", + event_type="test-event-1", + event_time=datetime.datetime.utcnow(), + data_version="1.0")) diff --git a/airlock_processor/StatusChangedQueueTrigger/function.json b/airlock_processor/StatusChangedQueueTrigger/function.json new file mode 100644 index 0000000000..62cceee485 --- /dev/null +++ b/airlock_processor/StatusChangedQueueTrigger/function.json @@ -0,0 +1,19 @@ +{ + "scriptFile": "__init__.py", + "bindings": [ + { + "name": "msg", + "type": "serviceBusTrigger", + "direction": "in", + "queueName": "%AIRLOCK_STATUS_CHANGED_QUEUE_NAME%", + "connection": "SB_CONNECTION_STRING" + }, + { + "type": "eventGrid", + "name": "outputEvent", + "topicEndpointUri": "EVENT_GRID_TOPIC_URI_SETTING", + "topicKeySetting": "EVENT_GRID_TOPIC_KEY_SETTING", + "direction": "out" + } + ] +} diff --git a/airlock_processor/_version.py b/airlock_processor/_version.py new file mode 100644 index 0000000000..3b93d0be0c --- /dev/null +++ b/airlock_processor/_version.py @@ -0,0 +1 @@ +__version__ = "0.0.2" diff --git a/airlock_processor/host.json b/airlock_processor/host.json new file mode 100644 index 0000000000..2a6b8f1371 --- /dev/null +++ b/airlock_processor/host.json @@ -0,0 +1,15 @@ +{ + "version": "2.0", + "logging": { + "applicationInsights": { + "samplingSettings": { + "isEnabled": true, + "excludedTypes": "Request" + } + } + }, + "extensionBundle": { + "id": "Microsoft.Azure.Functions.ExtensionBundle", + "version": "[3.3.0, 4.0.0)" + } +} diff --git a/airlock_processor/requirements.txt b/airlock_processor/requirements.txt new file mode 100644 index 0000000000..6bb1e59d0a --- /dev/null +++ b/airlock_processor/requirements.txt @@ -0,0 +1,3 @@ +# Do not include azure-functions-worker as it may conflict with the Azure Functions platform + +azure-functions \ No newline at end of file diff --git a/api_app/api/routes/workspaces.py b/api_app/api/routes/workspaces.py index 5db2b05a02..627f76fe5d 100644 --- a/api_app/api/routes/workspaces.py +++ b/api_app/api/routes/workspaces.py @@ -73,7 +73,7 @@ async def create_workspace(workspace_create: WorkspaceInCreate, response: Respon try: # TODO: This requires Directory.ReadAll ( Application.Read.All ) to be enabled in the Azure AD application to enable a users workspaces to be listed. This should be made optional. auth_info = extract_auth_information(workspace_create.properties) - workspace, resource_template = workspace_repo.create_workspace_item(workspace_create, auth_info) + workspace, resource_template = workspace_repo.create_workspace_item(workspace_create, auth_info, user.id) except (ValidationError, ValueError) as e: logging.error(f"Failed to create workspace model instance: {e}") raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(e)) diff --git a/api_app/db/repositories/workspaces.py b/api_app/db/repositories/workspaces.py index 2cc4987502..0b62056a05 100644 --- a/api_app/db/repositories/workspaces.py +++ b/api_app/db/repositories/workspaces.py @@ -62,19 +62,21 @@ def get_workspace_by_id(self, workspace_id: str) -> Workspace: raise EntityDoesNotExist return parse_obj_as(Workspace, workspaces[0]) - def create_workspace_item(self, workspace_input: WorkspaceInCreate, auth_info: dict) -> Tuple[Workspace, ResourceTemplate]: + def create_workspace_item(self, workspace_input: WorkspaceInCreate, auth_info: dict, workspace_owner_object_id: str) -> Tuple[Workspace, ResourceTemplate]: full_workspace_id = str(uuid.uuid4()) template = self.validate_input_against_template(workspace_input.templateName, workspace_input, ResourceType.Workspace) address_space_param = {"address_space": self.get_address_space_based_on_size(workspace_input.properties)} auto_app_registration_param = {"register_aad_application": self.automatically_create_application_registration(workspace_input.properties)} + workspace_owner_param = {"workspace_owner_object_id": self.get_workspace_owner(workspace_input.properties, workspace_owner_object_id)} # we don't want something in the input to overwrite the system parameters, # so dict.update can't work. Priorities from right to left. resource_spec_parameters = {**workspace_input.properties, **address_space_param, **auto_app_registration_param, + **workspace_owner_param, **auth_info, **self.get_workspace_spec_params(full_workspace_id)} @@ -89,8 +91,14 @@ def create_workspace_item(self, workspace_input: WorkspaceInCreate, auth_info: d return workspace, template - def automatically_create_application_registration(self, properties: dict) -> bool: - return True if properties["client_id"] == "auto_create" else False + def get_workspace_owner(self, workspace_properties: dict, workspace_owner_object_id: str) -> str: + # Add the objectId of the user that will become the workspace owner. If it is not present in + # the request, we can assume the logged in user will be WorkspaceOwner + user_defined_workspace_owner_object_id = workspace_properties.get("workspace_owner_object_id") + return workspace_owner_object_id if user_defined_workspace_owner_object_id is None else user_defined_workspace_owner_object_id + + def automatically_create_application_registration(self, workspace_properties: dict) -> bool: + return True if workspace_properties["client_id"] == "auto_create" else False def get_address_space_based_on_size(self, workspace_properties: dict): # Default the address space to 'small' if not supplied. 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 7531ff670e..0e7de5d733 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 @@ -89,18 +89,19 @@ def test_get_workspace_by_id_queries_db(workspace_repo, workspace): @patch('core.config.TRE_ID', "9876") def test_create_workspace_item_creates_a_workspace_with_the_right_values(validate_input_mock, new_cidr_mock, workspace_repo, basic_workspace_request, basic_resource_template): workspace_to_create = basic_workspace_request - # make sure the input doesn't include an address_space so that one will be generated + # make sure the input has 'None' for values that we expect to be set workspace_to_create.properties.pop("address_space", None) + workspace_to_create.properties.pop("workspace_owner_object_id", None) validate_input_mock.return_value = basic_resource_template new_cidr_mock.return_value = "1.2.3.4/24" - workspace, _ = workspace_repo.create_workspace_item(workspace_to_create, {}) + workspace, _ = workspace_repo.create_workspace_item(workspace_to_create, {}, "test_object_id") assert workspace.templateName == workspace_to_create.templateName assert workspace.resourceType == ResourceType.Workspace - for key in ["display_name", "description", "azure_location", "workspace_id", "tre_id", "address_space"]: + for key in ["display_name", "description", "azure_location", "workspace_id", "tre_id", "address_space", "workspace_owner_object_id"]: assert key in workspace.properties assert len(workspace.properties[key]) > 0 @@ -108,6 +109,7 @@ def test_create_workspace_item_creates_a_workspace_with_the_right_values(validat assert workspace.properties["tre_id"] != workspace_to_create.properties["tre_id"] # a new CIDR was allocated assert workspace.properties["address_space"] == "1.2.3.4/24" + assert workspace.properties["workspace_owner_object_id"] == "test_object_id" @patch('core.config.RESOURCE_LOCATION', "useast2") @@ -153,7 +155,7 @@ def test_create_workspace_item_creates_a_workspace_with_custom_address_space(val workspace_to_create.properties["address_space"] = "10.2.4.0/24" validate_input_mock.return_value = basic_resource_template - workspace, _ = workspace_repo.create_workspace_item(workspace_to_create, {}) + workspace, _ = workspace_repo.create_workspace_item(workspace_to_create, {}, "test_object_id") assert workspace.properties["address_space"] == workspace_to_create.properties["address_space"] @@ -170,7 +172,7 @@ def test_create_workspace_item_throws_exception_with_bad_custom_address_space(va validate_input_mock.return_value = basic_resource_template with pytest.raises(InvalidInput): - workspace_repo.create_workspace_item(workspace_to_create, {}) + workspace_repo.create_workspace_item(workspace_to_create, {}, "test_object_id") def test_get_address_space_based_on_size_with_custom_address_space_and_missing_address(workspace_repo, basic_workspace_request): @@ -188,7 +190,7 @@ def test_create_workspace_item_raises_value_error_if_template_is_invalid(validat validate_input_mock.side_effect = ValueError with pytest.raises(ValueError): - workspace_repo.create_workspace_item(workspace_input, {}) + workspace_repo.create_workspace_item(workspace_input, {}, "test_object_id") def test_automatically_create_application_registration_returns_true(workspace_repo): @@ -201,3 +203,17 @@ def test_automatically_create_application_registration_returns_false(workspace_r dictToTest = {"client_id": "12345"} assert workspace_repo.automatically_create_application_registration(dictToTest) is False + + +def test_workspace_owner_is_set_if_not_present_in_workspace_properties(workspace_repo): + dictToTest = {} + expected_object_id = "Expected" + + assert workspace_repo.get_workspace_owner(dictToTest, expected_object_id) is expected_object_id + + +def test_workspace_owner_is_not_overwritten_if_present_in_workspace_properties(workspace_repo): + dictToTest = {"workspace_owner_object_id": "Expected"} + not_expected_object_id = "Not Expected" + + assert workspace_repo.get_workspace_owner(dictToTest, not_expected_object_id) == "Expected" diff --git a/devops/.env.sample b/devops/.env.sample index 4acb7723bc..21a4c29649 100644 --- a/devops/.env.sample +++ b/devops/.env.sample @@ -9,6 +9,7 @@ ACR_NAME=__CHANGE_ME__ ARM_SUBSCRIPTION_ID=__CHANGE_ME__ # If you want to override the currently signed in credentials +# You would do this if running commands like `make terraform-install DIR=./templates/workspaces/base` # ARM_TENANT_ID=__CHANGE_ME__ # ARM_CLIENT_ID=__CHANGE_ME__ # ARM_CLIENT_SECRET=__CHANGE_ME__ diff --git a/devops/terraform/.terraform.lock.hcl b/devops/terraform/.terraform.lock.hcl index 003eefa9f7..d566aa988e 100644 --- a/devops/terraform/.terraform.lock.hcl +++ b/devops/terraform/.terraform.lock.hcl @@ -2,20 +2,21 @@ # Manual edits may be lost in future updates. provider "registry.terraform.io/hashicorp/azurerm" { - version = "2.97.0" - constraints = "2.97.0" + version = "3.5.0" + constraints = "3.5.0" hashes = [ - "h1:XxT+XM/leTXa21aTnJjPBfNBQ8cLE4gYDg01WEZsV1U=", - "zh:0aac80e6d2b8ddf33d558ac893d52688e8abf8a0b995cfc3c35eb84afbf432a3", - "zh:11191068cb732208ebc8662651782f63db329a25f7ea1cd50cd91622a2c247b7", - "zh:36c8334194e7d605682053c7c70fbb2a650d9b0a7bcc44d5cdda4f205818438a", - "zh:3a5e01276added995e875b42ecc6b36ff73d267f0c096c87195bd2b1fff4f5b2", - "zh:557e38371657e6ed8aae9192d01480c4cca7c0f7ade6022f1aec247a6384922b", - "zh:67b913c280c5858549477a4b05e77078b1a5234de77c7bddd4ee1e8e237d5665", - "zh:7aeca864ce45b295db734cd968f7596ff12cd7c522ee89d53f432dae7c2b5d18", - "zh:b6127d7a796eaf9756dd212667eb48f79c0e78729589ec8ccf68e0b36ebb4e54", - "zh:bed448238740f897d1b399e5123b3a9eba256b981846f9ee92b71493446ca684", - "zh:c351a1bba34c3bd06fff75e4c15e4db0456268479463c2471598068ea1c5c884", - "zh:d073c24d0a4756e79b39f41f552d526800f9fb0ad0a74f742ac8de61b6416a3a", + "h1:T4XsCHDT839VehWKdxbVsLn0ECjcQaUTzbSGW055pgM=", + "zh:0d8ae6d6e87f44ed4a178be03d6466339b0bb578ab54c2677e365a8281b0bb7d", + "zh:29d250d1a18d49652b28f234ecd17687b36c875dc47877a678e587d5d136b054", + "zh:2e69ba373cf009e8a60b36d04f3dbc4638708d1bf88be9f96b3e52cbf8f47f31", + "zh:53d525dd84ac63b5f749bfbc6b70a202dacf29597664d2ab1165efea6f24f630", + "zh:a25024d574ccd5ae6c2962f3bb71d510f62899f493b1ed096f2f7f0e2b18f975", + "zh:aabc64fe64319b95aaba1d1866f87abc7b10adae37d2eafa2f85f37317fdd49f", + "zh:acc6a977814897cb23d3b3753213281334238f8bce6d2b21e9f04fc4087ee980", + "zh:b24987e9416c39cd59c0fa41c139a97406b9955f0607fcafbf3315014456338a", + "zh:c550eae45fd32acdbe32b4e5c450ae95df6cb18903ac7216b1b07b23a16ce045", + "zh:c8f83b763b643893dcb6933a6bcee824cb514e06e7e5c5f5ac4ba187e66d7e22", + "zh:dcdac07e7ea18464dea729717870c275de9453775243c231e1fb305cad0ee597", + "zh:f569b65999264a9416862bca5cd2a6177d94ccb0424f3a4ef424428912b9cb3c", ] } diff --git a/devops/terraform/main.tf b/devops/terraform/main.tf index c1f22ad7d9..9a0145c027 100644 --- a/devops/terraform/main.tf +++ b/devops/terraform/main.tf @@ -14,13 +14,13 @@ resource "azurerm_resource_group" "mgmt" { # Holds Terraform shared state (already exists, created by bootstrap.sh) resource "azurerm_storage_account" "state_storage" { - name = var.mgmt_storage_account_name - resource_group_name = azurerm_resource_group.mgmt.name - location = azurerm_resource_group.mgmt.location - account_tier = "Standard" - account_kind = "StorageV2" - account_replication_type = "LRS" - allow_blob_public_access = false + name = var.mgmt_storage_account_name + resource_group_name = azurerm_resource_group.mgmt.name + location = azurerm_resource_group.mgmt.location + account_tier = "Standard" + account_kind = "StorageV2" + account_replication_type = "LRS" + allow_nested_items_to_be_public = false lifecycle { ignore_changes = [tags] } } diff --git a/devops/terraform/terraform.tf b/devops/terraform/terraform.tf index d7b45396e5..18da1c89d9 100644 --- a/devops/terraform/terraform.tf +++ b/devops/terraform/terraform.tf @@ -4,7 +4,7 @@ terraform { required_providers { azurerm = { source = "hashicorp/azurerm" - version = "2.97.0" + version = "3.5.0" } } } diff --git a/docs/tre-admins/setup-instructions/installing-workspace-service-and-user-resource.md b/docs/tre-admins/setup-instructions/installing-workspace-service-and-user-resource.md index 1534262a76..cb54cfd9ab 100644 --- a/docs/tre-admins/setup-instructions/installing-workspace-service-and-user-resource.md +++ b/docs/tre-admins/setup-instructions/installing-workspace-service-and-user-resource.md @@ -66,17 +66,18 @@ Now that we have published and registered both workspace service and user resour 4. Enter the workspace_id in the `workspace_id` field. -5. Paste the following payload json into the `Request body` field, update `` with the client ID of the app registration for the base workspace you created previously, then click `Execute`. Review the server response. +5. Paste the following payload json into the `Request body` field. Update `` with the Workspace AAD Application URI for the base workspace you created previously, this will be in the format `api://` or `api://_ws_`. Then click `Execute`. Review the server response. ```json { - "templateName":"tre-service-guacamole", + "templateName": "tre-service-guacamole", "properties": { - "display_name":"Virtual Desktop", - "description":"Create virtual desktops for running research workloads", - "is_exposed_externally":true, - "guac_disable_copy":true, - "guac_disable_paste":true + "display_name": "Virtual Desktop", + "description": "Create virtual desktops for running research workloads", + "workspace_identifier_uri": "", + "is_exposed_externally": true, + "guac_disable_copy": true, + "guac_disable_paste": true } } ``` @@ -88,7 +89,7 @@ You can also follow the progress in Azure portal as various resources come up. !!! info There is currently a bug where the redirect URI isn't automatically set up correctly in the Workspace API app registration. Until this is fixed, you need to head to the app registration in the Azure portal, click on **Add a redirect URI** > **Add a platform** > **Web** > then paste in the Guacamole URI in the redirect URI box. - You can find this in the Guacamole app service properties and append `/guacamole/` to the end - it should look like this: `https://guacamole-{TRE_ID}-ws-XXXX-svc-XXXX.azurewebsites.net/guacamole/`). Finally, make sure you check the **ID tokens** checkbox and click **Configure**. + You can find this in the Guacamole app service properties and append `/oauth2/callback` to the end - it should look like this: `https://guacamole-{TRE_ID}-ws-XXXX-svc-XXXX.azurewebsites.net/oauth2/callback/`). Finally, make sure you check the **ID tokens** checkbox and click **Configure**. ## Creating a user resource diff --git a/docs/tre-admins/setup-instructions/pre-deployment-steps.md b/docs/tre-admins/setup-instructions/pre-deployment-steps.md index 413aed83f9..36d4f09d62 100644 --- a/docs/tre-admins/setup-instructions/pre-deployment-steps.md +++ b/docs/tre-admins/setup-instructions/pre-deployment-steps.md @@ -56,6 +56,7 @@ Next, you will set the configuration variables for the specific Azure TRE instan 1. Open the `/templates/core/.env.sample` file and then save it without the .sample extension. You should now have a file called `.env` located in the `/templates/core` folder. 1. Set the first one of the variables, `TRE_ID`, which is the alphanumeric, with underscores and hyphens allowed, ID for the Azure TRE instance. The value will be used in various Azure resources, and **needs to be globally unique and less than 12 characters in length**. Use only lowercase letters. Choose wisely! +1. Choose whether or not to deploy the built-in web UI (`./ui`). By default this will _not_ be deployed. To deploy the UI, ensure you set `DEPLOY_UI=true` in the .env file. 1. Run `make auth` script to create 4 different AAD Applications that are used for TRE. The details of the script are covered in the [auth document](../auth.md). !!! note diff --git a/e2e_tests/helpers.py b/e2e_tests/helpers.py index d042a0b2b5..bb0a6045ad 100644 --- a/e2e_tests/helpers.py +++ b/e2e_tests/helpers.py @@ -1,5 +1,5 @@ import asyncio -from typing import Optional +from typing import Optional, Tuple from contextlib import asynccontextmanager from httpx import AsyncClient, Timeout import logging @@ -220,7 +220,7 @@ async def get_identifier_uri(client, workspace_id: str, auth_headers) -> str: return f"api://{workspace['properties']['scope_id'].lstrip('api://')}" -async def get_workspace_owner_token(admin_token, workspace_id, verify) -> Optional[str]: +async def get_workspace_auth_details(admin_token, workspace_id, verify) -> Tuple[str, str]: async with AsyncClient(verify=verify) as client: auth_headers = get_auth_header(admin_token) scope_uri = await get_identifier_uri(client, workspace_id, auth_headers) @@ -241,9 +241,7 @@ async def get_workspace_owner_token(admin_token, workspace_id, verify) -> Option except JSONDecodeError: raise Exception("Failed to parse response as JSON: {}".format(response.content)) - if "access_token" not in responseJson: + if "access_token" not in responseJson or response.status_code != status.HTTP_200_OK: raise Exception("Failed to get access_token: {}".format(response.content)) - token = responseJson["access_token"] - - return token if (response.status_code == status.HTTP_200_OK) else None + return responseJson["access_token"], scope_uri diff --git a/e2e_tests/pytest.ini b/e2e_tests/pytest.ini index a742b46772..4eeec37064 100644 --- a/e2e_tests/pytest.ini +++ b/e2e_tests/pytest.ini @@ -2,8 +2,11 @@ markers = smoke: marks tests as smoke (run sometimes, relatively fast) extended: marks tests as extended (run less frequently, relatively slow) + extended_aad + shared_services performance: marks tests for performance evaluation timeout: used to set test timeout with pytest-timeout + asyncio_mode = auto log_cli = 1 diff --git a/e2e_tests/test_performance.py b/e2e_tests/test_performance.py index 0aba73a82f..ed43e66d33 100644 --- a/e2e_tests/test_performance.py +++ b/e2e_tests/test_performance.py @@ -1,7 +1,7 @@ import asyncio import pytest import config -from helpers import disable_and_delete_resource, get_workspace_owner_token, post_resource +from helpers import disable_and_delete_resource, get_workspace_auth_details, post_resource from resources import strings pytestmark = pytest.mark.asyncio @@ -72,7 +72,7 @@ async def test_bulk_updates_to_ensure_each_resource_updated_in_series(admin_toke else: workspace_path = f"/workspaces/{config.PERF_TEST_WORKSPACE_ID}" - workspace_owner_token = await get_workspace_owner_token(admin_token=admin_token, workspace_id=workspace_id, verify=verify) + workspace_owner_token, scope_uri = await get_workspace_auth_details(admin_token=admin_token, workspace_id=workspace_id, verify=verify) if config.PERF_TEST_WORKSPACE_SERVICE_ID == "": # create a guac service @@ -80,7 +80,8 @@ async def test_bulk_updates_to_ensure_each_resource_updated_in_series(admin_toke "templateName": "tre-service-guacamole", "properties": { "display_name": "Workspace service test", - "description": "" + "description": "", + "workspace_identifier_uri": scope_uri } } diff --git a/e2e_tests/test_workspace_services.py b/e2e_tests/test_workspace_services.py index be17852b82..3b4ba17fe4 100644 --- a/e2e_tests/test_workspace_services.py +++ b/e2e_tests/test_workspace_services.py @@ -1,7 +1,7 @@ import pytest import config -from helpers import disable_and_delete_resource, get_workspace_owner_token, post_resource +from helpers import disable_and_delete_resource, get_workspace_auth_details, post_resource from resources import strings @@ -24,13 +24,14 @@ async def test_create_guacamole_service_into_base_workspace(admin_token, verify) } workspace_path, workspace_id = await post_resource(payload, strings.API_WORKSPACES, access_token=admin_token, verify=verify) - workspace_owner_token = await get_workspace_owner_token(admin_token=admin_token, workspace_id=workspace_id, verify=verify) + workspace_owner_token, scope_uri = await get_workspace_auth_details(admin_token=admin_token, workspace_id=workspace_id, verify=verify) service_payload = { "templateName": "tre-service-guacamole", "properties": { "display_name": "Workspace service test", - "description": "Workspace service for E2E test" + "description": "Workspace service for E2E test", + "workspace_identifier_uri": scope_uri } } @@ -49,6 +50,19 @@ async def test_create_guacamole_service_into_base_workspace(admin_token, verify) await post_resource(patch_payload, f'/api{workspace_service_path}', workspace_owner_token, verify, method="PATCH") + user_resource_payload = { + "templateName": "tre-service-guacamole-windowsvm", + "properties": { + "display_name": "My VM", + "description": "Will be using this VM for my research", + "os_image": "Windows 10" + } + } + + user_resource_path, user_resource_id = await post_resource(user_resource_payload, f'/api{workspace_service_path}/{strings.API_USER_RESOURCES}', workspace_owner_token, verify, method="POST") + + await disable_and_delete_resource(f'/api{user_resource_path}', workspace_owner_token, verify) + await disable_and_delete_resource(f'/api{workspace_service_path}', workspace_owner_token, verify) await disable_and_delete_resource(f'/api{workspace_path}', admin_token, verify) @@ -56,7 +70,7 @@ async def test_create_guacamole_service_into_base_workspace(admin_token, verify) @pytest.mark.extended_aad @pytest.mark.timeout(3000) -async def test_create_guacamole_service_into_aad_workspace(admin_token, workspace_owner_token, verify) -> None: +async def test_create_guacamole_service_into_aad_workspace(admin_token, verify) -> None: """This test will create a Guacamole service but will create a workspace and automatically register the AAD Application""" payload = { @@ -70,13 +84,14 @@ async def test_create_guacamole_service_into_aad_workspace(admin_token, workspac } workspace_path, workspace_id = await post_resource(payload, strings.API_WORKSPACES, access_token=admin_token, verify=verify) - workspace_owner_token = await get_workspace_owner_token(admin_token=admin_token, workspace_id=workspace_id, verify=verify) + workspace_owner_token, scope_uri = await get_workspace_auth_details(admin_token=admin_token, workspace_id=workspace_id, verify=verify) service_payload = { "templateName": "tre-service-guacamole", "properties": { "display_name": "Workspace service test", - "description": "Workspace service for E2E test" + "description": "Workspace service for E2E test", + "workspace_identifier_uri": scope_uri } } @@ -95,6 +110,19 @@ async def test_create_guacamole_service_into_aad_workspace(admin_token, workspac await post_resource(patch_payload, f'/api{workspace_service_path}', workspace_owner_token, verify, method="PATCH") + user_resource_payload = { + "templateName": "tre-service-guacamole-windowsvm", + "properties": { + "display_name": "My VM", + "description": "Will be using this VM for my research", + "os_image": "Windows 10" + } + } + + user_resource_path, user_resource_id = await post_resource(user_resource_payload, f'/api{workspace_service_path}/{strings.API_USER_RESOURCES}', workspace_owner_token, verify, method="POST") + + await disable_and_delete_resource(f'/api{user_resource_path}', workspace_owner_token, verify) + await disable_and_delete_resource(f'/api{workspace_service_path}', workspace_owner_token, verify) await disable_and_delete_resource(f'/api{workspace_path}', admin_token, verify) diff --git a/resource_processor/version.txt b/resource_processor/version.txt index 493f7415d7..260c070a89 100644 --- a/resource_processor/version.txt +++ b/resource_processor/version.txt @@ -1 +1 @@ -__version__ = "0.3.0" +__version__ = "0.3.1" diff --git a/resource_processor/vmss_porter/aad_auth.json b/resource_processor/vmss_porter/aad_auth.json index 7ebdd74142..0d694c1627 100644 --- a/resource_processor/vmss_porter/aad_auth.json +++ b/resource_processor/vmss_porter/aad_auth.json @@ -13,13 +13,13 @@ { "name": "auth_client_id", "source": { - "secret": "api-client-id" + "secret": "application-admin-client-id" } }, { "name": "auth_client_secret", "source": { - "secret": "api-client-secret" + "secret": "application-admin-client-secret" } } ] diff --git a/resource_processor/vmss_porter/aad_auth_local_debugging.json b/resource_processor/vmss_porter/aad_auth_local_debugging.json index a91d680315..48bec7a4f3 100644 --- a/resource_processor/vmss_porter/aad_auth_local_debugging.json +++ b/resource_processor/vmss_porter/aad_auth_local_debugging.json @@ -13,13 +13,13 @@ { "name": "auth_client_id", "source": { - "env": "API_CLIENT_ID" + "env": "APPLICATION_ADMIN_CLIENT_ID" } }, { "name": "auth_client_secret", "source": { - "env": "API_CLIENT_SECRET" + "env": "APPLICATION_ADMIN_CLIENT_SECRET" } } ] diff --git a/scripts/aad/aad-app-reg.sh b/scripts/aad/aad-app-reg.sh index 0a06474f28..f6c4e4f173 100755 --- a/scripts/aad/aad-app-reg.sh +++ b/scripts/aad/aad-app-reg.sh @@ -25,8 +25,6 @@ Options: --automation-account Create an app registration for automation (e.g. CI/CD) to use for registering bundles etc Can be used with -a to apply admin consent --automation-clientid Optional, when --workspace is specified the client ID of the automation account can be added to the TRE workspace. - --read-write-all-permission Optional, Whether to grant the application "Application.ReadWrite.All" permission. - This is used when you wish TRE to be able to automatically create workspace app registrations. Examples: 1. $0 -n TRE -r https://mytre.region.cloudapp.azure.com -a @@ -51,7 +49,6 @@ fi # Get the directory that this script is in DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" - declare grantAdminConsent=0 declare swaggerAppId="" declare workspace=0 @@ -61,7 +58,6 @@ declare currentUserId="" declare spId="" declare createAutomationAccount=0 declare automationAppId="" -declare applicationReadWriteAll=0 declare msGraphUri="https://graph.microsoft.com/v1.0" # Initialize parameters specified from command line @@ -95,10 +91,6 @@ while [[ $# -gt 0 ]]; do automationAppId=$2 shift 2 ;; - --read-write-all-permission) - applicationReadWriteAll=1 - shift 1 - ;; *) echo "Invalid option: $1." show_usage @@ -130,12 +122,6 @@ currentUserId=$(az ad signed-in-user show --query 'objectId' --output tsv) tenant=$(az rest -m get -u "${msGraphUri}/domains" -o json | jq -r '.value[] | select(.isDefault == true) | .id') echo "You are about to create app registrations in the Azure AD tenant \"${tenant}\"." -read -p "Do you want to continue? (y/N) " -n 1 -r -echo -if [[ ! $REPLY =~ ^[Yy]$ ]] -then - exit 0 -fi # Load in helper functions # shellcheck disable=SC1091 @@ -146,6 +132,8 @@ source "${DIR}/grant_admin_consent.sh" source "${DIR}/wait_for_new_app_registration.sh" # shellcheck disable=SC1091 source "${DIR}/wait_for_new_service_principal.sh" +# shellcheck disable=SC1091 +source "${DIR}/get_msgraph_access.sh" # Generate GUIDS userRoleId=$(cat /proc/sys/kernel/random/uuid) @@ -264,46 +252,17 @@ msGraphProfileScopeId="14dad69e-099b-42c9-810b-d002981feec1" msGraphObjectId=$(az ad sp show --id ${msGraphAppId} --query "objectId" --output tsv) directoryReadAllId=$(az ad sp show --id ${msGraphAppId} --query "appRoles[?value=='Directory.Read.All'].id" --output tsv) userReadAllId=$(az ad sp show --id ${msGraphAppId} --query "appRoles[?value=='User.Read.All'].id" --output tsv) -applicationReadWriteAllId=$(az ad sp show --id ${msGraphAppId} --query "appRoles[?value=='Application.ReadWrite.All'].id" --output tsv) applicationReadWriteOwnedById=$(az ad sp show --id ${msGraphAppId} --query "appRoles[?value=='Application.ReadWrite.OwnedBy'].id" --output tsv) -function get_msgraph_scope() { - oauthScope=$(az ad sp show --id ${msGraphAppId} --query "oauth2Permissions[?value=='$1'].id | [0]" --output tsv) - jq -c . <<- JSON - { - "id": "${oauthScope}", - "type": "Scope" - } -JSON -} - -function get_msgraph_role() { - appRoleScope=$(az ad sp show --id ${msGraphAppId} --query "appRoles[?value=='$1'].id | [0]" --output tsv) - jq -c . <<- JSON - { - "id": "${appRoleScope}", - "type": "Role" - } -JSON -} - roleUserReadAll=$(get_msgraph_role "User.Read.All" ) roleDirectoryReadAll=$(get_msgraph_role "Directory.Read.All" ) roleApplicationReadWriteOwnedBy=$(get_msgraph_role "Application.ReadWrite.OwnedBy" ) -roleApplicationReadWriteAll="" - -# Conditionally set whether this app can create other applications. Note the comma -# at the end of roleApplicationReadWriteAll so that the array is maintained if present. -if [ "$applicationReadWriteAll" -eq 1 ]; then - roleApplicationReadWriteAll="$(get_msgraph_role 'Application.ReadWrite.All' )," -fi apiRequiredResourceAccess=$(jq -c . << JSON [ { "resourceAppId": "${msGraphAppId}", "resourceAccess": [ - ${roleApplicationReadWriteAll} ${roleUserReadAll}, ${roleDirectoryReadAll} ] @@ -450,7 +409,7 @@ az ad sp update --id "$spId" --set tags="['WindowsAzureActiveDirectoryIntegrated echo "running 'az ad app permission grant' to make changes effective" az ad app permission grant --id "${apiAppId}" --api "${msGraphAppId}" -# If a TRE core app reg +# If a workspace if [[ "$workspace" -ne 0 ]]; then # Grant admin consent for the delegated workspace scopes if [[ "$grantAdminConsent" -eq 1 ]]; then @@ -515,12 +474,6 @@ else grant_admin_consent "${spId}" "$msGraphObjectId" "${directoryReadAllId}" wait_for_new_service_principal "${spId}" grant_admin_consent "${spId}" "${msGraphObjectId}" "${userReadAllId}" - - # Global Admin permission is not given by default. - if [ "$applicationReadWriteAll" -eq 1 ]; then - wait_for_new_service_principal "$spId" - grant_admin_consent "$spId" "$msGraphObjectId" "$applicationReadWriteAllId" - fi fi # Now create the app for the Swagger UI @@ -757,6 +710,8 @@ if [[ $createAutomationAccount -ne 0 ]]; then echo "Granting admin consent for ${appName} Automation Admin App (ClientID ${automationAppId})" wait_for_new_app_registration "${automationAppId}" adminConsentResponse=$(az ad app permission admin-consent --id "${automationAppId}") + echo "Response:" + echo "${adminConsentResponse}" if [ -z "${adminConsentResponse}" ]; then echo "Admin consent failed, trying once more: ${adminConsentResponse}" az ad app permission admin-consent --id "${automationAppId}" @@ -788,7 +743,6 @@ AAD_TENANT_ID="$(az account show --output json | jq -r '.tenantId')" ** Please copy the following variables to /templates/core/.env ** -WORKSPACE_API_OBJECT_ID=$(az ad app show --id "${apiAppId}" --query objectId) WORKSPACE_API_CLIENT_ID="${apiAppId}" WORKSPACE_API_CLIENT_SECRET="${spPassword}" diff --git a/scripts/aad/create_application_administrator.sh b/scripts/aad/create_application_administrator.sh new file mode 100755 index 0000000000..a897962de2 --- /dev/null +++ b/scripts/aad/create_application_administrator.sh @@ -0,0 +1,196 @@ +#!/bin/bash + +# Setup Script +set -euo pipefail +# AZURE_CORE_OUTPUT=jsonc # force CLI output to JSON for the script (user can still change default for interactive usage in the dev container) + +function show_usage() +{ + cat << USAGE + +Utility script for creating an application administrator for TRE. This is optional and is normal +if you want to delegate Application creation to TRE. +This script is trigger by the environment variable AUTO_WORKSPACE_APP_REGISTRATION. +You must be logged in using Azure CLI with sufficient privileges to modify Azure Active Directory to run this script. + +Usage: $0 [--admin-consent] + +Options: + -n,--name Required. The prefix for the app (registration) names e.g., "TRE". + -a,--admin-consent Optional, but recommended. Grants admin consent for the app registrations, when this flag is set. + Requires directory admin privileges to the Azure AD in question. + +USAGE + exit 1 +} + +if ! command -v az &> /dev/null; then + echo "This script requires Azure CLI" 1>&2 + exit 1 +fi + +# Get the directory that this script is in +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" + +declare grantAdminConsent=0 +declare currentUserId="" +declare spId="" +declare msGraphUri="https://graph.microsoft.com/v1.0" +declare appName="" + +# Initialize parameters specified from command line +while [[ $# -gt 0 ]]; do + case "$1" in + -n|--name) + appName=$2 + shift 2 + ;; + -a|--admin-consent) + grantAdminConsent=1 + shift 1 + ;; + *) + echo "Invalid option: $1." + show_usage + exit 2 + ;; + esac +done + +################################### +# CHECK INCOMMING PARAMETERS # +################################### +if [[ $(az account list --only-show-errors -o json | jq 'length') -eq 0 ]]; then + echo "Please run az login -t --allow-no-subscriptions" + exit 1 +fi + +if [[ -z "$appName" ]]; then + echo "Please specify the application name" 1>&2 + show_usage +fi +appName="$appName Application Admin" +currentUserId=$(az ad signed-in-user show --query 'objectId' --output tsv) +tenant=$(az rest -m get -u "${msGraphUri}/domains" -o json | jq -r '.value[] | select(.isDefault == true) | .id') + +echo "You are about to create app registrations in the Azure AD tenant \"${tenant}\"." + +# Load in helper functions +# shellcheck disable=SC1091 +source "${DIR}/get_existing_app.sh" +# shellcheck disable=SC1091 +source "${DIR}/grant_admin_consent.sh" +# shellcheck disable=SC1091 +source "${DIR}/wait_for_new_app_registration.sh" +# shellcheck disable=SC1091 +source "${DIR}/wait_for_new_service_principal.sh" +# shellcheck disable=SC1091 +source "${DIR}/get_msgraph_access.sh" + +# Get an existing object if it's been created before. +appObjectId="" +existingApp=$(get_existing_app --name "${appName}") || null +if [ -n "${existingApp}" ]; then + appObjectId=$(echo "${existingApp}" | jq -r '.objectId') +fi + +# Get the Required Resource Scope/Role +msGraphAppId="00000003-0000-0000-c000-000000000000" +msGraphObjectId=$(az ad sp show --id ${msGraphAppId} --query "objectId" --output tsv) +applicationReadWriteAllId=$(az ad sp show --id ${msGraphAppId} --query "appRoles[?value=='Application.ReadWrite.All'].id" --output tsv) + +roleApplicationReadWriteAll="$(get_msgraph_role 'Application.ReadWrite.All' )" + +appDefinition=$(jq -c . << JSON +{ + "displayName": "${appName}", + "signInAudience": "AzureADMyOrg", + "requiredResourceAccess": [ + { + "resourceAppId": "${msGraphAppId}", + "resourceAccess": [ + ${roleApplicationReadWriteAll} + ] + }] +} +JSON +) + +# Is the app already registered? +if [[ -n ${appObjectId} ]]; then + echo "Updating app registration with ID ${appObjectId}" + az rest --method PATCH --uri "${msGraphUri}/applications/${appObjectId}" --headers Content-Type=application/json --body "${appDefinition}" + appId=$(az ad app show --id "${appObjectId}" --query "appId" --output tsv) + echo "App registration with ID ${appId} updated" +else + echo "Creating a new app registration, ${appName}" + appId=$(az rest --method POST --uri "${msGraphUri}/applications" --headers Content-Type=application/json --body "${appDefinition}" --output tsv --query "appId") + + # Poll until the app registration is found in the listing. + wait_for_new_app_registration "${appId}" +fi + +# Make the current user an owner of the application. +az ad app owner add --id "${appId}" --owner-object-id "$currentUserId" + +# See if a service principal already exists +spId=$(az ad sp list --filter "appId eq '${appId}'" --query '[0].objectId' --output tsv) + +resetPassword=0 + +# If not, create a new service principal +if [[ -z "$spId" ]]; then + spId=$(az ad sp create --id "${appId}" --query 'objectId' --output tsv) + echo "Creating a new service principal, for '${appName}' app, with ID ${spId}" + wait_for_new_service_principal "${spId}" + az ad app owner add --id "${appId}" --owner-object-id "${spId}" + resetPassword=1 +else + echo "Service principal for the app already exists." + echo "Existing passwords (client secrets) cannot be queried. To view the password it needs to be reset." + read -p "Do you wish to reset the ${appName} app password (y/N)? " -n 1 -r + echo + + if [[ $REPLY =~ ^[Yy]$ ]]; then + resetPassword=1 + fi +fi + +spPassword="" + +if [[ "$resetPassword" == 1 ]]; then + # Reset the app password (client secret) and display it + spPassword=$(az ad sp credential reset --name "${appId}" --query 'password' --output tsv) + echo "'${appName}' app password (client secret): ${spPassword}" +fi + +# This tag ensures the app is listed in "Enterprise applications" +az ad sp update --id "$spId" --set tags="['WindowsAzureActiveDirectoryIntegratedApp']" + +# needed to make the API permissions change effective, this must be done after SP creation... +echo "running 'az ad app permission grant' to make changes effective" +az ad app permission grant --id "${appId}" --api "${msGraphAppId}" + +# Grant admin consent on the required resource accesses (Graph API) +if [[ $grantAdminConsent -eq 1 ]]; then + echo "Granting admin consent for '${appName} app (service principal ID ${spId}) - NOTE: Directory admin privileges required for this step" + wait_for_new_service_principal "${spId}" + grant_admin_consent "${spId}" "$msGraphObjectId" "${applicationReadWriteAllId}" +fi + +cat << ENV_VARS + +AAD_TENANT_ID="$(az account show --output json | jq -r '.tenantId')" + +** Please copy the following variables to /templates/core/.env ** + +APPLICATION_ADMIN_CLIENT_ID="${appId}" +APPLICATION_ADMIN_CLIENT_SECRET="${spPassword}" + +ENV_VARS + +if [[ $grantAdminConsent -eq 0 ]]; then + echo "NOTE: Make sure the API permissions of the app registrations have admin consent granted." + echo "Run this script with flag -a to grant admin consent or configure the registrations in Azure Portal." + echo "See APP REGISTRATIONS in documentation for more information." +fi diff --git a/scripts/aad/get_msgraph_access.sh b/scripts/aad/get_msgraph_access.sh new file mode 100755 index 0000000000..b3a3e84500 --- /dev/null +++ b/scripts/aad/get_msgraph_access.sh @@ -0,0 +1,27 @@ +#!/bin/bash + +# Setup Script +set -euo pipefail + +# Magic string for MSGraph +msGraphAppId="00000003-0000-0000-c000-000000000000" + +function get_msgraph_scope() { + oauthScope=$(az ad sp show --id ${msGraphAppId} --query "oauth2Permissions[?value=='$1'].id | [0]" --output tsv) + jq -c . <<- JSON + { + "id": "${oauthScope}", + "type": "Scope" + } +JSON +} + +function get_msgraph_role() { + appRoleScope=$(az ad sp show --id ${msGraphAppId} --query "appRoles[?value=='$1'].id | [0]" --output tsv) + jq -c . <<- JSON + { + "id": "${appRoleScope}", + "type": "Role" + } +JSON +} diff --git a/scripts/create_aad_assets.sh b/scripts/create_aad_assets.sh index 1b4f27aa68..b83e2c4180 100755 --- a/scripts/create_aad_assets.sh +++ b/scripts/create_aad_assets.sh @@ -1,13 +1,11 @@ #!/bin/bash -set -e +set -o errexit +set -o pipefail +set -o nounset +# set -o xtrace : "${AAD_TENANT_ID?'You have not set your AAD_TENANT_ID in ./templates/core/.env'}" -api_app_can_create_other_applications="" -if [ "${AUTO_WORKSPACE_APP_REGISTRATION}" == true ]; then - api_app_can_create_other_applications="--read-write-all-permission" -fi - LOGGED_IN_TENANT_ID=$(az account show --query tenantId -o tsv) CHANGED_TENANT=0 @@ -19,12 +17,24 @@ if [ "${LOGGED_IN_TENANT_ID}" != "${AAD_TENANT_ID}" ]; then CHANGED_TENANT=1 fi -# Then register an App. DO NOT put quotes around ${api_app_can_create_other_applications} as this -# will break the aad-app-reg.dh script. +# Create the identity that is able to create other applications +if [ "${AUTO_WORKSPACE_APP_REGISTRATION}" == true ]; then + ./scripts/aad/create_application_administrator.sh \ + --name "${TRE_ID}" --admin-consent + + echo "Please copy the values above into your /templates/core/.env." + read -p "Please confirm you have done this? (y/N) " -n 1 -r + echo + if [[ ! $REPLY =~ ^[Yy]$ ]]; then + exit 0 + fi +fi + +# Then register an App for the TRE Core. ./scripts/aad/aad-app-reg.sh \ --name "${TRE_ID}" \ - --tre-url "https://${TRE_ID}.${LOCATION}.cloudapp.azure.com" \ - --admin-consent --automation-account ${api_app_can_create_other_applications} + --swaggerui-redirecturl "https://${TRE_ID}.${LOCATION}.cloudapp.azure.com/api/docs/oauth2-redirect" \ + --admin-consent --automation-account echo "Please copy the values above into your /templates/core/.env." read -p "Please confirm you have done this? (y/N) " -n 1 -r @@ -39,7 +49,7 @@ set -a # shellcheck disable=SC1091 . ./templates/core/.env -echo "Please check that the following value is the same as above to check you have copied yoru keys." +echo "Please check that the following value is the same as above to check you have copied your keys." echo "API client id is : ${API_CLIENT_ID}" ./scripts/aad/aad-app-reg.sh \ diff --git a/templates/core/.env.sample b/templates/core/.env.sample index 6b4722bd2a..965fd079f0 100644 --- a/templates/core/.env.sample +++ b/templates/core/.env.sample @@ -5,12 +5,17 @@ TRE_ADDRESS_SPACE="10.0.0.0/12" DEPLOY_GITEA=true DEPLOY_NEXUS=true RESOURCE_PROCESSOR_TYPE="vmss_porter" +API_APP_SERVICE_PLAN_SKU_SIZE="P1v2" +APP_SERVICE_PLAN_SKU="P1v2" # Auth configuration # If you would like the workspace bundle to also create the AAD Workspace application -# then set this to true. This requires the API AAD Application to have the following +# then set this to true. This requires an identity that has the following # role permission `Application.ReadWrite.All` # AUTO_WORKSPACE_APP_REGISTRATION=false +# APPLICATION_ADMIN_CLIENT_ID="Generated if the value above is true and you run `make auth`" +# APPLICATION_ADMIN_CLIENT_SECRET="Generated if the value above is true and you run `make auth`" + AAD_TENANT_ID=__CHANGE_ME__ API_CLIENT_ID=__CHANGE_ME__ diff --git a/templates/core/terraform/.terraform.lock.hcl b/templates/core/terraform/.terraform.lock.hcl index a2e0e3bf07..84749a34d9 100644 --- a/templates/core/terraform/.terraform.lock.hcl +++ b/templates/core/terraform/.terraform.lock.hcl @@ -2,21 +2,22 @@ # Manual edits may be lost in future updates. provider "registry.terraform.io/hashicorp/azurerm" { - version = "2.97.0" - constraints = "2.97.0" + version = "3.5.0" + constraints = "3.5.0" hashes = [ - "h1:XxT+XM/leTXa21aTnJjPBfNBQ8cLE4gYDg01WEZsV1U=", - "zh:0aac80e6d2b8ddf33d558ac893d52688e8abf8a0b995cfc3c35eb84afbf432a3", - "zh:11191068cb732208ebc8662651782f63db329a25f7ea1cd50cd91622a2c247b7", - "zh:36c8334194e7d605682053c7c70fbb2a650d9b0a7bcc44d5cdda4f205818438a", - "zh:3a5e01276added995e875b42ecc6b36ff73d267f0c096c87195bd2b1fff4f5b2", - "zh:557e38371657e6ed8aae9192d01480c4cca7c0f7ade6022f1aec247a6384922b", - "zh:67b913c280c5858549477a4b05e77078b1a5234de77c7bddd4ee1e8e237d5665", - "zh:7aeca864ce45b295db734cd968f7596ff12cd7c522ee89d53f432dae7c2b5d18", - "zh:b6127d7a796eaf9756dd212667eb48f79c0e78729589ec8ccf68e0b36ebb4e54", - "zh:bed448238740f897d1b399e5123b3a9eba256b981846f9ee92b71493446ca684", - "zh:c351a1bba34c3bd06fff75e4c15e4db0456268479463c2471598068ea1c5c884", - "zh:d073c24d0a4756e79b39f41f552d526800f9fb0ad0a74f742ac8de61b6416a3a", + "h1:T4XsCHDT839VehWKdxbVsLn0ECjcQaUTzbSGW055pgM=", + "zh:0d8ae6d6e87f44ed4a178be03d6466339b0bb578ab54c2677e365a8281b0bb7d", + "zh:29d250d1a18d49652b28f234ecd17687b36c875dc47877a678e587d5d136b054", + "zh:2e69ba373cf009e8a60b36d04f3dbc4638708d1bf88be9f96b3e52cbf8f47f31", + "zh:53d525dd84ac63b5f749bfbc6b70a202dacf29597664d2ab1165efea6f24f630", + "zh:a25024d574ccd5ae6c2962f3bb71d510f62899f493b1ed096f2f7f0e2b18f975", + "zh:aabc64fe64319b95aaba1d1866f87abc7b10adae37d2eafa2f85f37317fdd49f", + "zh:acc6a977814897cb23d3b3753213281334238f8bce6d2b21e9f04fc4087ee980", + "zh:b24987e9416c39cd59c0fa41c139a97406b9955f0607fcafbf3315014456338a", + "zh:c550eae45fd32acdbe32b4e5c450ae95df6cb18903ac7216b1b07b23a16ce045", + "zh:c8f83b763b643893dcb6933a6bcee824cb514e06e7e5c5f5ac4ba187e66d7e22", + "zh:dcdac07e7ea18464dea729717870c275de9453775243c231e1fb305cad0ee597", + "zh:f569b65999264a9416862bca5cd2a6177d94ccb0424f3a4ef424428912b9cb3c", ] } diff --git a/templates/core/terraform/airlock/airlock_processor.tf b/templates/core/terraform/airlock/airlock_processor.tf new file mode 100644 index 0000000000..bfa050a644 --- /dev/null +++ b/templates/core/terraform/airlock/airlock_processor.tf @@ -0,0 +1,72 @@ +data "local_file" "airlock_processor_version" { + filename = "${path.root}/../../../airlock_processor/_version.py" +} + +locals { + version = replace(replace(replace(data.local_file.airlock_processor_version.content, "__version__ = \"", ""), "\"", ""), "\n", "") +} + +# re-using the web api app plan +data "azurerm_app_service_plan" "core" { + name = "plan-${var.tre_id}" + resource_group_name = var.resource_group_name +} + +data "azurerm_application_insights" "core" { + name = "appi-${var.tre_id}" + resource_group_name = var.resource_group_name +} + + +resource "azurerm_storage_account" "sa_airlock_processor_func_app" { + name = local.airlock_function_sa_name + resource_group_name = var.resource_group_name + location = var.location + account_tier = "Standard" + account_replication_type = "LRS" + tags = local.tre_core_tags + + lifecycle { ignore_changes = [tags] } +} + +resource "azurerm_linux_function_app" "airlock_function_app" { + name = local.airlock_function_app_name + resource_group_name = var.resource_group_name + location = var.location + + storage_account_name = azurerm_storage_account.sa_airlock_processor_func_app.name + service_plan_id = data.azurerm_app_service_plan.core.id + + storage_account_access_key = azurerm_storage_account.sa_airlock_processor_func_app.primary_access_key + tags = local.tre_core_tags + + identity { + type = "UserAssigned" + identity_ids = [azurerm_user_assigned_identity.airlock_id.id] + } + + app_settings = { + "SB_CONNECTION_STRING" = data.azurerm_servicebus_namespace.airlock_sb.default_primary_connection_string + "EVENT_GRID_TOPIC_URI_SETTING" = azurerm_eventgrid_topic.step_result.endpoint + "EVENT_GRID_TOPIC_KEY_SETTING" = azurerm_eventgrid_topic.step_result.primary_access_key + "WEBSITES_ENABLE_APP_SERVICE_STORAGE" = false + "AIRLOCK_STATUS_CHANGED_QUEUE_NAME" = "airlock-status-changed" + "APPINSIGHTS_INSTRUMENTATIONKEY" = data.azurerm_application_insights.core.instrumentation_key + } + + site_config { + always_on = var.enable_local_debugging ? true : false + container_registry_managed_identity_client_id = azurerm_user_assigned_identity.airlock_id.client_id + container_registry_use_managed_identity = true + application_stack { + docker { + registry_url = var.docker_registry_server + image_name = var.airlock_processor_image_repository + image_tag = local.version + } + } + } + + lifecycle { ignore_changes = [tags] } +} + diff --git a/templates/core/terraform/airlock/identity.tf b/templates/core/terraform/airlock/identity.tf new file mode 100644 index 0000000000..89091d6dec --- /dev/null +++ b/templates/core/terraform/airlock/identity.tf @@ -0,0 +1,43 @@ +data "azurerm_cosmosdb_account" "tre-db-account" { + name = "cosmos-${var.tre_id}" + resource_group_name = var.resource_group_name +} + +data "azurerm_container_registry" "mgmt_acr" { + name = var.mgmt_acr_name + resource_group_name = var.mgmt_resource_group_name +} + +resource "azurerm_user_assigned_identity" "airlock_id" { + resource_group_name = var.resource_group_name + location = var.location + tags = local.tre_core_tags + + name = "id-airlock-${var.tre_id}" + + lifecycle { ignore_changes = [tags] } +} + +resource "azurerm_role_assignment" "acrpull_role" { + scope = data.azurerm_container_registry.mgmt_acr.id + role_definition_name = "AcrPull" + principal_id = azurerm_user_assigned_identity.airlock_id.principal_id +} + +resource "azurerm_role_assignment" "servicebus_sender" { + scope = data.azurerm_servicebus_namespace.airlock_sb.id + role_definition_name = "Azure Service Bus Data Sender" + principal_id = azurerm_user_assigned_identity.airlock_id.principal_id +} + +resource "azurerm_role_assignment" "servicebus_receiver" { + scope = data.azurerm_servicebus_namespace.airlock_sb.id + role_definition_name = "Azure Service Bus Data Receiver" + principal_id = azurerm_user_assigned_identity.airlock_id.principal_id +} + +resource "azurerm_role_assignment" "cosmos_contributor" { + scope = data.azurerm_cosmosdb_account.tre-db-account.id + role_definition_name = "Contributor" + principal_id = azurerm_user_assigned_identity.airlock_id.principal_id +} diff --git a/templates/core/terraform/airlock/locals.tf b/templates/core/terraform/airlock/locals.tf index 080b0e05d5..447294e0a6 100644 --- a/templates/core/terraform/airlock/locals.tf +++ b/templates/core/terraform/airlock/locals.tf @@ -33,4 +33,11 @@ locals { import_rejected_eventgrid_subscription_name = "evgs-airlock-import-rejected-blob-created" export_approved_eventgrid_subscription_name = "evgs-airlock-export-approved-blob-created" + airlock_function_app_name = "func-airlock-processor-${var.tre_id}" + airlock_function_sa_name = "saairlockp${var.tre_id}" + + tre_core_tags = { + tre_id = var.tre_id + tre_core_service_id = var.tre_id + } } diff --git a/templates/core/terraform/airlock/service_bus.tf b/templates/core/terraform/airlock/service_bus.tf index 580ccb4bba..81af154e91 100644 --- a/templates/core/terraform/airlock/service_bus.tf +++ b/templates/core/terraform/airlock/service_bus.tf @@ -2,7 +2,6 @@ data "azurerm_servicebus_namespace" "airlock_sb" { name = "sb-${var.tre_id}" resource_group_name = var.resource_group_name - } resource "azurerm_servicebus_queue" "step_result" { diff --git a/templates/core/terraform/airlock/storage_accounts.tf b/templates/core/terraform/airlock/storage_accounts.tf index 4ddd07d9ea..edf8f0b249 100644 --- a/templates/core/terraform/airlock/storage_accounts.tf +++ b/templates/core/terraform/airlock/storage_accounts.tf @@ -7,7 +7,7 @@ resource "azurerm_storage_account" "sa_external_import" { account_replication_type = "GRS" # Don't allow anonymous access (unrelated to the 'public' networking rules) - allow_blob_public_access = false + 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 @@ -29,7 +29,7 @@ resource "azurerm_storage_account" "sa_export_approved" { account_replication_type = "GRS" # Don't allow anonymous access (unrelated to the 'public' networking rules) - allow_blob_public_access = false + 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 @@ -44,12 +44,12 @@ resource "azurerm_storage_account" "sa_export_approved" { # '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 + 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_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 @@ -96,12 +96,12 @@ resource "azurerm_private_endpoint" "stg_ip_import_pe" { # '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 + name = local.import_rejected_storage_name + location = var.location + resource_group_name = var.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 @@ -125,8 +125,6 @@ resource "azurerm_private_endpoint" "stgipimportpe" { 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] @@ -138,4 +136,8 @@ resource "azurerm_private_endpoint" "stgipimportpe" { is_manual_connection = false subresource_names = ["Blob"] } + + tags = local.tre_core_tags + + lifecycle { ignore_changes = [tags] } } diff --git a/templates/core/terraform/airlock/variables.tf b/templates/core/terraform/airlock/variables.tf index 850cb96e1f..bf36d0246b 100644 --- a/templates/core/terraform/airlock/variables.tf +++ b/templates/core/terraform/airlock/variables.tf @@ -3,3 +3,24 @@ variable "location" {} variable "resource_group_name" {} variable "shared_subnet_id" {} variable "enable_local_debugging" {} + +variable "docker_registry_server" { + type = string + description = "Docker registry server" +} + +variable "airlock_processor_image_repository" { + type = string + description = "Repository for Airlock processor image" + default = "microsoft/azuretre/airlock-processor" +} + +variable "mgmt_resource_group_name" { + type = string + description = "Shared management resource group" +} + +variable "mgmt_acr_name" { + type = string + description = "Management ACR name" +} diff --git a/templates/core/terraform/api-webapp.tf b/templates/core/terraform/api-webapp.tf index 6c2b7ecf02..17ed5b3be7 100644 --- a/templates/core/terraform/api-webapp.tf +++ b/templates/core/terraform/api-webapp.tf @@ -6,27 +6,22 @@ locals { version = replace(replace(replace(data.local_file.api_app_version.content, "__version__ = \"", ""), "\"", ""), "\n", "") } -resource "azurerm_app_service_plan" "core" { +resource "azurerm_service_plan" "core" { name = "plan-${var.tre_id}" resource_group_name = azurerm_resource_group.core.name location = azurerm_resource_group.core.location - reserved = true - kind = "linux" + os_type = "Linux" + sku_name = var.api_app_service_plan_sku_size tags = local.tre_core_tags + worker_count = 1 lifecycle { ignore_changes = [tags] } - - sku { - tier = var.api_app_service_plan_sku_tier - capacity = 1 - size = var.api_app_service_plan_sku_size - } } resource "azurerm_app_service" "api" { name = "api-${var.tre_id}" resource_group_name = azurerm_resource_group.core.name location = azurerm_resource_group.core.location - app_service_plan_id = azurerm_app_service_plan.core.id + app_service_plan_id = azurerm_service_plan.core.id https_only = true key_vault_reference_identity_id = azurerm_user_assigned_identity.id.id tags = local.tre_core_tags diff --git a/templates/core/terraform/appgateway/appgateway.tf b/templates/core/terraform/appgateway/appgateway.tf index 0f8294be63..21abc62889 100644 --- a/templates/core/terraform/appgateway/appgateway.tf +++ b/templates/core/terraform/appgateway/appgateway.tf @@ -7,7 +7,7 @@ resource "azurerm_public_ip" "appgwpip" { domain_name_label = var.tre_id tags = local.tre_core_tags - lifecycle { ignore_changes = [tags] } + lifecycle { ignore_changes = [tags, zones] } } resource "azurerm_user_assigned_identity" "agw_id" { diff --git a/templates/core/terraform/appgateway/staticweb.tf b/templates/core/terraform/appgateway/staticweb.tf index 3b0730cd8e..adf50b9b35 100644 --- a/templates/core/terraform/appgateway/staticweb.tf +++ b/templates/core/terraform/appgateway/staticweb.tf @@ -2,15 +2,15 @@ data "azurerm_client_config" "deployer" {} # See https://microsoft.github.io/AzureTRE/tre-developers/letsencrypt/ resource "azurerm_storage_account" "staticweb" { - name = local.staticweb_storage_name - resource_group_name = var.resource_group_name - location = var.location - account_kind = "StorageV2" - account_tier = "Standard" - account_replication_type = "LRS" - enable_https_traffic_only = true - allow_blob_public_access = false - tags = local.tre_core_tags + name = local.staticweb_storage_name + resource_group_name = var.resource_group_name + location = var.location + account_kind = "StorageV2" + account_tier = "Standard" + account_replication_type = "LRS" + enable_https_traffic_only = true + allow_nested_items_to_be_public = false + tags = local.tre_core_tags static_website { index_document = "index.html" diff --git a/templates/core/terraform/azure-monitor/azure-monitor.tf b/templates/core/terraform/azure-monitor/azure-monitor.tf index a5ed473958..8e1962744b 100644 --- a/templates/core/terraform/azure-monitor/azure-monitor.tf +++ b/templates/core/terraform/azure-monitor/azure-monitor.tf @@ -3,7 +3,7 @@ resource "azurerm_log_analytics_workspace" "core" { resource_group_name = var.resource_group_name location = var.location retention_in_days = 30 - sku = "pergb2018" + sku = "PerGB2018" tags = local.tre_core_tags lifecycle { ignore_changes = [tags] } @@ -12,14 +12,14 @@ resource "azurerm_log_analytics_workspace" "core" { # Storage account for Application Insights # Because Private Link is enabled on Application Performance Management (APM), Bring Your Own Storage (BYOS) approach is required resource "azurerm_storage_account" "app_insights" { - name = lower(replace("stappinsights${var.tre_id}", "-", "")) - resource_group_name = var.resource_group_name - location = var.location - account_kind = "StorageV2" - account_tier = "Standard" - account_replication_type = "LRS" - allow_blob_public_access = false - tags = local.tre_core_tags + name = lower(replace("stappinsights${var.tre_id}", "-", "")) + resource_group_name = var.resource_group_name + location = var.location + account_kind = "StorageV2" + account_tier = "Standard" + account_replication_type = "LRS" + allow_nested_items_to_be_public = false + tags = local.tre_core_tags lifecycle { ignore_changes = [tags] } } diff --git a/templates/core/terraform/bastion.tf b/templates/core/terraform/bastion.tf index 656dd3b605..1eec8f3d6d 100644 --- a/templates/core/terraform/bastion.tf +++ b/templates/core/terraform/bastion.tf @@ -6,7 +6,7 @@ resource "azurerm_public_ip" "bastion" { sku = "Standard" tags = local.tre_core_tags - lifecycle { ignore_changes = [tags] } + lifecycle { ignore_changes = [tags, zones] } } resource "azurerm_bastion_host" "bastion" { diff --git a/templates/core/terraform/deploy.sh b/templates/core/terraform/deploy.sh index b296d335c7..02baa35125 100755 --- a/templates/core/terraform/deploy.sh +++ b/templates/core/terraform/deploy.sh @@ -5,20 +5,29 @@ set -o pipefail set -o nounset # set -o xtrace +# This variables are loaded in for us +# shellcheck disable=SC2154 export TF_VAR_docker_registry_server="$TF_VAR_acr_name.azurecr.io" -export TF_VAR_docker_registry_username=$TF_VAR_acr_name -export TF_VAR_docker_registry_password=$(az acr credential show --name ${TF_VAR_acr_name} --query passwords[0].value -o tsv | sed 's/"//g') +export TF_VAR_docker_registry_username="${TF_VAR_acr_name}" +TF_VAR_docker_registry_password=$(az acr credential show --name "${TF_VAR_acr_name}" --query passwords[0].value -o tsv | sed 's/"//g') +export TF_VAR_docker_registry_password + +# This is where we can migrate any Terraform before we plan and apply +# For instance deprecated Terraform resources +#./migrate.sh PLAN_FILE="tfplan$$" TS=$(date +"%s") LOG_FILE="${TS}-tre-core.log" +# This variables are loaded in for us +# shellcheck disable=SC2154 ../../../devops/scripts/terraform_wrapper.sh \ - -g $TF_VAR_mgmt_resource_group_name \ - -s $TF_VAR_mgmt_storage_account_name \ - -n $TF_VAR_terraform_state_container_name \ - -k ${TRE_ID} \ - -l ${LOG_FILE} \ + -g "${TF_VAR_mgmt_resource_group_name}" \ + -s "${TF_VAR_mgmt_storage_account_name}" \ + -n "${TF_VAR_terraform_state_container_name}" \ + -k "${TRE_ID}" \ + -l "${LOG_FILE}" \ -c "terraform plan -out ${PLAN_FILE} && \ terraform apply -input=false -auto-approve ${PLAN_FILE} && \ terraform output -json > ../tre_output.json" diff --git a/templates/core/terraform/keyvault.tf b/templates/core/terraform/keyvault.tf index 0cadb78d77..6962363d9a 100644 --- a/templates/core/terraform/keyvault.tf +++ b/templates/core/terraform/keyvault.tf @@ -89,6 +89,24 @@ resource "azurerm_key_vault_secret" "auth_tenant_id" { ] } +resource "azurerm_key_vault_secret" "application_admin_client_id" { + name = "application-admin-client-id" + value = var.application_admin_client_id + key_vault_id = azurerm_key_vault.kv.id + depends_on = [ + azurerm_key_vault_access_policy.deployer + ] +} + +resource "azurerm_key_vault_secret" "application_admin_client_secret" { + name = "application-admin-client-secret" + value = var.application_admin_client_secret + key_vault_id = azurerm_key_vault.kv.id + depends_on = [ + azurerm_key_vault_access_policy.deployer + ] +} + resource "azurerm_monitor_diagnostic_setting" "kv" { name = "diagnostics-kv-${var.tre_id}" target_resource_id = azurerm_key_vault.kv.id diff --git a/templates/core/terraform/main.tf b/templates/core/terraform/main.tf index 0eebb15722..3e3d0669f1 100644 --- a/templates/core/terraform/main.tf +++ b/templates/core/terraform/main.tf @@ -3,7 +3,7 @@ terraform { required_providers { azurerm = { source = "hashicorp/azurerm" - version = "=2.97.0" + version = "=3.5.0" } } @@ -73,13 +73,15 @@ 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 - + 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 + docker_registry_server = var.docker_registry_server + mgmt_resource_group_name = var.mgmt_resource_group_name + mgmt_acr_name = var.acr_name depends_on = [ azurerm_servicebus_namespace.sb, module.network @@ -104,6 +106,7 @@ module "resource_processor_vmss_porter" { mgmt_resource_group_name = var.mgmt_resource_group_name terraform_state_container_name = var.terraform_state_container_name key_vault_name = azurerm_key_vault.kv.name + key_vault_id = azurerm_key_vault.kv.id subscription_id = var.arm_subscription_id resource_processor_number_processes_per_instance = var.resource_processor_number_processes_per_instance diff --git a/templates/core/terraform/migrate.sh b/templates/core/terraform/migrate.sh new file mode 100755 index 0000000000..4a94815c64 --- /dev/null +++ b/templates/core/terraform/migrate.sh @@ -0,0 +1,40 @@ +#!/bin/bash + +set -o errexit +set -o pipefail +set -o nounset +# set -o xtrace + +# This variables are loaded in for us +# shellcheck disable=SC2154 +terraform init -input=false -backend=true -reconfigure -upgrade \ + -backend-config="resource_group_name=${TF_VAR_mgmt_resource_group_name}" \ + -backend-config="storage_account_name=${TF_VAR_mgmt_storage_account_name}" \ + -backend-config="container_name=${TF_VAR_terraform_state_container_name}" \ + -backend-config="key=${TRE_ID}" + +echo "*** Migrating TF Resources ***" +# 1. Check we have a root_module in state +# 2. Grab the Resource ID +# 3. Delete the old resource from state +# 4. Import the new resource type in using the existing Azure Resource ID + +# azurerm_app_service_plan -> azurerm_service_plan +core_app_service_plan_id=$(terraform show -json \ + | jq -r 'select(.values.root_module) | .values.root_module.resources[] | select(.address=="azurerm_app_service_plan.core") | .values.id' \ + || null) +if [ -n "${core_app_service_plan_id}" ]; then + echo "Migrating ${core_app_service_plan_id}" + terraform state rm azurerm_app_service_plan.core + terraform import azurerm_service_plan.core "${core_app_service_plan_id}" +fi + +# azurerm_app_service -> azurerm_linux_web_app +api_app_service_id=$(terraform show -json \ + | jq -r 'select(.values.root_module) | .values.root_module.resources[] | select(.address=="azurerm_app_service.api") | .values.id' \ + || null) +if [ -n "${api_app_service_id}" ]; then + echo "Migrating ${api_app_service_id}. (Phase 2)" + #terraform state rm azurerm_app_service.api + #terraform import azurerm_linux_web_app.api "${api_app_service_id}" +fi diff --git a/templates/core/terraform/network/dns_zones.tf b/templates/core/terraform/network/dns_zones.tf index 37c18819c8..8a2a6b1f33 100644 --- a/templates/core/terraform/network/dns_zones.tf +++ b/templates/core/terraform/network/dns_zones.tf @@ -233,6 +233,7 @@ resource "azurerm_private_dns_zone" "postgres" { resource "azurerm_private_dns_zone" "nexus" { name = "nexus-${var.tre_id}.${var.location}.cloudapp.azure.com" resource_group_name = var.resource_group_name + tags = local.tre_core_tags lifecycle { ignore_changes = [tags] } } diff --git a/templates/core/terraform/resource_processor/vmss_porter/main.tf b/templates/core/terraform/resource_processor/vmss_porter/main.tf index addf008943..8b67c8110c 100644 --- a/templates/core/terraform/resource_processor/vmss_porter/main.tf +++ b/templates/core/terraform/resource_processor/vmss_porter/main.tf @@ -49,7 +49,7 @@ resource "random_password" "password" { resource "azurerm_key_vault_secret" "resource_processor_vmss_password" { name = "resource-processor-vmss-password" value = random_password.password.result - key_vault_id = data.azurerm_key_vault.kv.id + key_vault_id = var.key_vault_id } resource "azurerm_user_assigned_identity" "vmss_msi" { @@ -187,7 +187,7 @@ resource "azurerm_role_assignment" "subscription_contributor" { } resource "azurerm_key_vault_access_policy" "resource_processor" { - key_vault_id = data.azurerm_key_vault.kv.id + key_vault_id = var.key_vault_id tenant_id = azurerm_user_assigned_identity.vmss_msi.tenant_id object_id = azurerm_user_assigned_identity.vmss_msi.principal_id diff --git a/templates/core/terraform/resource_processor/vmss_porter/variables.tf b/templates/core/terraform/resource_processor/vmss_porter/variables.tf index 50f874affd..7e292f5d8a 100644 --- a/templates/core/terraform/resource_processor/vmss_porter/variables.tf +++ b/templates/core/terraform/resource_processor/vmss_porter/variables.tf @@ -13,6 +13,7 @@ variable "mgmt_resource_group_name" {} variable "terraform_state_container_name" {} variable "app_insights_connection_string" {} variable "key_vault_name" {} +variable "key_vault_id" {} variable "resource_processor_number_processes_per_instance" {} variable "subscription_id" { description = "The subscription id to create the resource processor permission/role. If not supplied will use the TF context." diff --git a/templates/core/terraform/scripts/build-deploy-ui.sh b/templates/core/terraform/scripts/build-deploy-ui.sh index 633a143904..aa581e1f7e 100755 --- a/templates/core/terraform/scripts/build-deploy-ui.sh +++ b/templates/core/terraform/scripts/build-deploy-ui.sh @@ -14,7 +14,7 @@ jq --arg rootClientId "${SWAGGER_UI_CLIENT_ID}" \ --arg rootTenantId "${AAD_TENANT_ID}" \ --arg treApiClientId "${API_CLIENT_ID}" \ --arg treUrl "https://${FQDN}/api" \ - '.rootClientId = $rootClientId | .rootTenantId = $rootTenantId | .treApiClientId = $treApiClientId | .treUrl = $treUrl' ./src/config.sample.json > ./src/config.json + '.rootClientId = $rootClientId | .rootTenantId = $rootTenantId | .treApiClientId = $treApiClientId | .treUrl = $treUrl' ./src/config.source.json > ./src/config.json # build and deploy the app yarn install diff --git a/templates/core/terraform/storage.tf b/templates/core/terraform/storage.tf index 0a28533cf9..3bbb47ea20 100644 --- a/templates/core/terraform/storage.tf +++ b/templates/core/terraform/storage.tf @@ -58,6 +58,7 @@ resource "azurerm_private_endpoint" "filepe" { location = azurerm_resource_group.core.location resource_group_name = azurerm_resource_group.core.name subnet_id = module.network.shared_subnet_id + tags = local.tre_core_tags lifecycle { ignore_changes = [tags] } diff --git a/templates/core/terraform/variables.tf b/templates/core/terraform/variables.tf index 42a2b1142b..cc76febf8c 100644 --- a/templates/core/terraform/variables.tf +++ b/templates/core/terraform/variables.tf @@ -39,11 +39,6 @@ variable "api_image_repository" { default = "microsoft/azuretre/api" } -variable "api_app_service_plan_sku_tier" { - type = string - default = "PremiumV3" -} - variable "api_app_service_plan_sku_size" { type = string default = "P1v3" @@ -113,7 +108,19 @@ variable "api_client_id" { variable "api_client_secret" { type = string - description = "A client secret use by the API to authenticate with Azure AD for access to Microsoft Graph." + description = "A client secret used by the API to authenticate with Azure AD for access to Microsoft Graph." + sensitive = true +} + +variable "application_admin_client_id" { + type = string + description = "The client id (app id) of the registration in Azure AD for creating AAD Applications." + sensitive = true +} + +variable "application_admin_client_secret" { + type = string + description = "A client secret used by the Resource Processor to authenticate with Azure AD to create AAD Applications." sensitive = true } diff --git a/templates/shared_services/certs/Dockerfile.tmpl b/templates/shared_services/certs/Dockerfile.tmpl index d7e1a1f563..47098764eb 100644 --- a/templates/shared_services/certs/Dockerfile.tmpl +++ b/templates/shared_services/certs/Dockerfile.tmpl @@ -1,22 +1,25 @@ -FROM python:3.8 +FROM python:3.8-slim-buster ARG BUNDLE_DIR -RUN apt-get update \ - && apt-get install -y ca-certificates \ - && apt-get clean -y && rm -rf /var/lib/apt/lists/* +SHELL ["/bin/bash", "-o", "pipefail", "-c"] # Install Azure CLI +# It's useless to specify azcli version since the mixin installs the latest anyway +# hadolint ignore=DL3008 RUN apt-get update \ - && apt-get install -y ca-certificates jq curl apt-transport-https lsb-release gnupg \ + && apt-get install -y --no-install-recommends ca-certificates="20200601~deb10u2" jq="1.5+dfsg-2+b1" curl="7.64.0-4+deb10u2" apt-transport-https="1.8.2.3" lsb-release="10.2019051400" gnupg="2.2.12-1+deb10u1" \ && curl -sL https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor | tee /etc/apt/trusted.gpg.d/microsoft.gpg > /dev/null \ && AZ_REPO=$(lsb_release -cs) \ && echo "deb [arch=amd64] https://packages.microsoft.com/repos/azure-cli/ $AZ_REPO main" | tee /etc/apt/sources.list.d/azure-cli.list \ - && apt-get update && apt-get -y install azure-cli \ + && apt-get update && apt-get -y --no-install-recommends install azure-cli \ && apt-get clean -y && rm -rf /var/lib/apt/lists/* # Install Certbot -RUN apt-get update && apt-get install -y python3 python3-venv libaugeas0 \ +# Some of the tools' versions seem to depend on the base image so proboably best not to specify them. +# hadolint ignore=DL3008 +RUN apt-get update \ + && apt-get install -y --no-install-recommends python3 python3-venv libaugeas0="1.11.0-3" \ && python3 -m venv /opt/certbot/ \ && /opt/certbot/bin/pip install --no-cache-dir --upgrade pip \ && /opt/certbot/bin/pip install --no-cache-dir certbot \ diff --git a/templates/shared_services/certs/porter.yaml b/templates/shared_services/certs/porter.yaml index 8e5664472f..7e10df3cd4 100755 --- a/templates/shared_services/certs/porter.yaml +++ b/templates/shared_services/certs/porter.yaml @@ -1,6 +1,6 @@ --- name: tre-shared-service-certs -version: 0.0.11 +version: 0.0.12 description: "An Azure TRE shared service to generate certificates for a specified internal domain using Letsencrypt" registry: azuretre dockerfile: Dockerfile.tmpl @@ -59,14 +59,10 @@ install: domain_prefix: "{{ bundle.parameters.domain_prefix }}" cert_name: "{{ bundle.parameters.cert_name }}" backendConfig: - resource_group_name: - "{{ bundle.parameters.tfstate_resource_group_name }}" - storage_account_name: - "{{ bundle.parameters.tfstate_storage_account_name }}" - container_name: - "{{ bundle.parameters.tfstate_container_name }}" - key: - "{{ bundle.parameters.tre_id }}-shared-service-certs" + resource_group_name: "{{ bundle.parameters.tfstate_resource_group_name }}" + storage_account_name: "{{ bundle.parameters.tfstate_storage_account_name }}" + container_name: "{{ bundle.parameters.tfstate_container_name }}" + key: "{{ bundle.parameters.tre_id }}-shared-service-certs" upgrade: - exec: @@ -88,14 +84,10 @@ uninstall: domain_prefix: "{{ bundle.parameters.domain_prefix }}" cert_name: "{{ bundle.parameters.cert_name }}" backendConfig: - resource_group_name: - "{{ bundle.parameters.tfstate_resource_group_name }}" - storage_account_name: - "{{ bundle.parameters.tfstate_storage_account_name }}" - container_name: - "{{ bundle.parameters.tfstate_container_name }}" - key: - "{{ bundle.parameters.tre_id }}-shared-service-certs" + resource_group_name: "{{ bundle.parameters.tfstate_resource_group_name }}" + storage_account_name: "{{ bundle.parameters.tfstate_storage_account_name }}" + container_name: "{{ bundle.parameters.tfstate_container_name }}" + key: "{{ bundle.parameters.tre_id }}-shared-service-certs" generate: - terraform: @@ -103,10 +95,8 @@ generate: - "output" description: "Get Terraform output variables" backendConfig: - resource_group_name: - "{{ bundle.parameters.tfstate_resource_group_name }}" - storage_account_name: - "{{ bundle.parameters.tfstate_storage_account_name }}" + resource_group_name: "{{ bundle.parameters.tfstate_resource_group_name }}" + storage_account_name: "{{ bundle.parameters.tfstate_storage_account_name }}" container_name: "{{ bundle.parameters.tfstate_container_name }}" key: "{{ bundle.parameters.tre_id }}-shared-service-certs" outputs: @@ -116,8 +106,7 @@ generate: - name: resource_group_name - name: keyvault_name - az: - description: - "Login to Azure" + description: "Login to Azure" arguments: - login flags: diff --git a/templates/shared_services/certs/terraform/appgateway.tf b/templates/shared_services/certs/terraform/appgateway.tf index d3f2ad5291..d8cb701a5d 100644 --- a/templates/shared_services/certs/terraform/appgateway.tf +++ b/templates/shared_services/certs/terraform/appgateway.tf @@ -28,7 +28,7 @@ resource "azurerm_public_ip" "appgwpip" { sku = "Standard" domain_name_label = "${var.domain_prefix}-${var.tre_id}" - lifecycle { ignore_changes = [tags] } + lifecycle { ignore_changes = [tags, zones] } } resource "azurerm_user_assigned_identity" "agw_id" { diff --git a/templates/shared_services/firewall/Dockerfile.tmpl b/templates/shared_services/firewall/Dockerfile.tmpl index 3f8524ce64..73a646ee72 100644 --- a/templates/shared_services/firewall/Dockerfile.tmpl +++ b/templates/shared_services/firewall/Dockerfile.tmpl @@ -2,15 +2,16 @@ FROM debian:stretch-slim ARG BUNDLE_DIR -RUN apt-get update && apt-get install -y ca-certificates +SHELL ["/bin/bash", "-o", "pipefail", "-c"] # Install Azure CLI RUN apt-get update \ - && apt-get install -y ca-certificates jq curl apt-transport-https lsb-release gnupg \ + && apt-get install -y ca-certificates="20200601~deb9u2" curl="7.52.1-5+deb9u16" apt-transport-https="1.4.11" lsb-release="9.20161125" gnupg="2.1.18-8~deb9u4" \ && curl -sL https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor | tee /etc/apt/trusted.gpg.d/microsoft.gpg > /dev/null \ && AZ_REPO=$(lsb_release -cs) \ && echo "deb [arch=amd64] https://packages.microsoft.com/repos/azure-cli/ $AZ_REPO main" | tee /etc/apt/sources.list.d/azure-cli.list \ - && apt-get update && apt-get -y install azure-cli + && apt-get update && apt-get -y install azure-cli="2.36.0-1~stretch" \ + && apt-get clean -y && rm -rf /var/lib/apt/lists/* # This is a template Dockerfile for the bundle's invocation image # You can customize it to use different base images, install tools and copy configuration files. diff --git a/templates/shared_services/firewall/porter.yaml b/templates/shared_services/firewall/porter.yaml index 8a45aa14eb..64caea8838 100644 --- a/templates/shared_services/firewall/porter.yaml +++ b/templates/shared_services/firewall/porter.yaml @@ -1,6 +1,6 @@ --- name: tre-shared-service-firewall -version: 0.3.0 +version: 0.3.1 description: "An Azure TRE Firewall shared service" registry: azuretre dockerfile: Dockerfile.tmpl @@ -38,7 +38,7 @@ parameters: default: false - name: rule_collections type: string - default: "W10=" #b64 for [] + default: "W10=" # b64 for [] mixins: - exec diff --git a/templates/shared_services/firewall/terraform/firewall.tf b/templates/shared_services/firewall/terraform/firewall.tf index 5fcf431713..07cf121bff 100644 --- a/templates/shared_services/firewall/terraform/firewall.tf +++ b/templates/shared_services/firewall/terraform/firewall.tf @@ -4,8 +4,9 @@ resource "azurerm_public_ip" "fwpip" { location = data.azurerm_resource_group.rg.location allocation_method = "Static" sku = "Standard" + tags = local.tre_shared_service_tags - lifecycle { ignore_changes = [tags] } + lifecycle { ignore_changes = [tags, zones] } } resource "azurerm_firewall" "fw" { @@ -13,6 +14,9 @@ resource "azurerm_firewall" "fw" { name = "fw-${var.tre_id}" resource_group_name = local.core_resource_group_name location = data.azurerm_resource_group.rg.location + sku_tier = "Standard" + sku_name = "AZFW_VNet" + tags = local.tre_shared_service_tags ip_configuration { name = "fw-ip-configuration" subnet_id = data.azurerm_subnet.firewall.id diff --git a/templates/shared_services/firewall/terraform/locals.tf b/templates/shared_services/firewall/terraform/locals.tf index 06f276d0a1..316b2f79a6 100644 --- a/templates/shared_services/firewall/terraform/locals.tf +++ b/templates/shared_services/firewall/terraform/locals.tf @@ -1,4 +1,8 @@ locals { core_resource_group_name = "rg-${var.tre_id}" firewall_name = "fw-${var.tre_id}" + tre_shared_service_tags = { + tre_id = var.tre_id + tre_shared_service_id = var.tre_resource_id + } } diff --git a/templates/shared_services/firewall/terraform/main.tf b/templates/shared_services/firewall/terraform/main.tf index 715a8db036..fa8b6fa244 100644 --- a/templates/shared_services/firewall/terraform/main.tf +++ b/templates/shared_services/firewall/terraform/main.tf @@ -3,7 +3,7 @@ terraform { required_providers { azurerm = { source = "hashicorp/azurerm" - version = "=2.97.0" + version = "=3.5.0" } } diff --git a/templates/shared_services/firewall/terraform/routetable.tf b/templates/shared_services/firewall/terraform/routetable.tf index 36f03c4cf2..756a054c9e 100644 --- a/templates/shared_services/firewall/terraform/routetable.tf +++ b/templates/shared_services/firewall/terraform/routetable.tf @@ -3,6 +3,7 @@ resource "azurerm_route_table" "rt" { resource_group_name = local.core_resource_group_name location = data.azurerm_resource_group.rg.location disable_bgp_route_propagation = false + tags = local.tre_shared_service_tags lifecycle { ignore_changes = [tags] } diff --git a/templates/shared_services/gitea/Dockerfile.tmpl b/templates/shared_services/gitea/Dockerfile.tmpl deleted file mode 100644 index 3f8524ce64..0000000000 --- a/templates/shared_services/gitea/Dockerfile.tmpl +++ /dev/null @@ -1,29 +0,0 @@ -FROM debian:stretch-slim - -ARG BUNDLE_DIR - -RUN apt-get update && apt-get install -y ca-certificates - -# Install Azure CLI -RUN apt-get update \ - && apt-get install -y ca-certificates jq curl apt-transport-https lsb-release gnupg \ - && curl -sL https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor | tee /etc/apt/trusted.gpg.d/microsoft.gpg > /dev/null \ - && AZ_REPO=$(lsb_release -cs) \ - && echo "deb [arch=amd64] https://packages.microsoft.com/repos/azure-cli/ $AZ_REPO main" | tee /etc/apt/sources.list.d/azure-cli.list \ - && apt-get update && apt-get -y install azure-cli - -# This is a template Dockerfile for the bundle's invocation image -# You can customize it to use different base images, install tools and copy configuration files. -# -# Porter will use it as a template and append lines to it for the mixins -# and to set the CMD appropriately for the CNAB specification. -# -# Add the following line to porter.yaml to instruct Porter to use this template -# dockerfile: Dockerfile.tmpl - -# You can control where the mixin's Dockerfile lines are inserted into this file by moving "# PORTER_MIXINS" line -# another location in this file. If you remove that line, the mixins generated content is appended to this file. -# PORTER_MIXINS - -# Use the BUNDLE_DIR build argument to copy files into the bundle -COPY . $BUNDLE_DIR diff --git a/templates/shared_services/gitea/porter.yaml b/templates/shared_services/gitea/porter.yaml index 5ba055a495..dcd6b90f03 100644 --- a/templates/shared_services/gitea/porter.yaml +++ b/templates/shared_services/gitea/porter.yaml @@ -1,9 +1,8 @@ --- name: tre-shared-service-gitea -version: 0.3.1 +version: 0.3.5 description: "A Gitea shared service" registry: azuretre -dockerfile: Dockerfile.tmpl credentials: - name: azure_tenant_id @@ -36,6 +35,7 @@ parameters: description: "The name of the Terraform state storage container" - name: arm_use_msi env: ARM_USE_MSI + type: boolean default: false mixins: - exec @@ -49,14 +49,11 @@ install: vars: tre_id: "{{ bundle.parameters.tre_id }}" tre_resource_id: "{{ bundle.parameters.id }}" - mgmt_resource_group_name: - "{{ bundle.parameters.tfstate_resource_group_name }}" + mgmt_resource_group_name: "{{ bundle.parameters.tfstate_resource_group_name }}" acr_name: "{{ bundle.parameters.mgmt_acr_name }}" backendConfig: - resource_group_name: - "{{ bundle.parameters.tfstate_resource_group_name }}" - storage_account_name: - "{{ bundle.parameters.tfstate_storage_account_name }}" + resource_group_name: "{{ bundle.parameters.tfstate_resource_group_name }}" + storage_account_name: "{{ bundle.parameters.tfstate_storage_account_name }}" container_name: "{{ bundle.parameters.tfstate_container_name }}" key: "{{ bundle.parameters.tre_id }}-shared-service-gitea" upgrade: @@ -72,13 +69,10 @@ uninstall: vars: tre_id: "{{ bundle.parameters.tre_id }}" tre_resource_id: "{{ bundle.parameters.id }}" - mgmt_resource_group_name: - "{{ bundle.parameters.tfstate_resource_group_name }}" + mgmt_resource_group_name: "{{ bundle.parameters.tfstate_resource_group_name }}" acr_name: "{{ bundle.parameters.mgmt_acr_name }}" backendConfig: - resource_group_name: - "{{ bundle.parameters.tfstate_resource_group_name }}" - storage_account_name: - "{{ bundle.parameters.tfstate_storage_account_name }}" + resource_group_name: "{{ bundle.parameters.tfstate_resource_group_name }}" + storage_account_name: "{{ bundle.parameters.tfstate_storage_account_name }}" container_name: "{{ bundle.parameters.tfstate_container_name }}" key: "{{ bundle.parameters.tre_id }}-shared-service-gitea" diff --git a/templates/shared_services/gitea/terraform/.terraform.lock.hcl b/templates/shared_services/gitea/terraform/.terraform.lock.hcl index f12bff178e..e7d57a8fe4 100644 --- a/templates/shared_services/gitea/terraform/.terraform.lock.hcl +++ b/templates/shared_services/gitea/terraform/.terraform.lock.hcl @@ -2,59 +2,59 @@ # Manual edits may be lost in future updates. provider "registry.terraform.io/hashicorp/azurerm" { - version = "3.4.0" - constraints = "3.4.0" + version = "3.5.0" + constraints = "3.5.0" hashes = [ - "h1:h78yKGgOFrU/N5ntockxN7XF/ufv47j77+oauO2GKqk=", - "zh:4e9913fc3378436d19150c334e5906eafb83a4af3a270423cb7cdda94b27371f", - "zh:5b3d0cec2a600dc1f6633baa8fc36368c5c330fd7654861edcfa76f760a8f6a9", - "zh:5e0e1f899027bc182f31d996c9611e5ba27a034c848d7b0519b39e559fc4f38d", - "zh:66e3a1383ed6a0370989f6fd6abcfa63ccf6918ae535108595af57b9c20a9257", - "zh:688493baf6a116a399b737d74c11080051aca1ab087e5cddd14cc683b7e45c76", - "zh:9e471d85d52343e3ba778f3a94626d820fbec97bb589a3ac7a6a0939b9387770", - "zh:be1e85635daca1768f26962a4cbbadbf7fd13d9da8f9f188e938beca542c2ad5", - "zh:c00e14b6aa566eb9995cb0e1611a18fb8650d9f35c7636a7643a1b6e22660226", - "zh:c40711e5021838fd879da4c9e6b8f7e72104ada2adf0f3ba22e1cc32c3c54086", - "zh:cc62f8541de8d79577e57664e4f03c1fca893d455e5fb238d20668389c0f09ee", - "zh:cd9cbb5c6e5ceb5fcc7c4d0cab516ff209667d1b539b8c7436bd5e452c6aba8f", + "h1:T4XsCHDT839VehWKdxbVsLn0ECjcQaUTzbSGW055pgM=", + "zh:0d8ae6d6e87f44ed4a178be03d6466339b0bb578ab54c2677e365a8281b0bb7d", + "zh:29d250d1a18d49652b28f234ecd17687b36c875dc47877a678e587d5d136b054", + "zh:2e69ba373cf009e8a60b36d04f3dbc4638708d1bf88be9f96b3e52cbf8f47f31", + "zh:53d525dd84ac63b5f749bfbc6b70a202dacf29597664d2ab1165efea6f24f630", + "zh:a25024d574ccd5ae6c2962f3bb71d510f62899f493b1ed096f2f7f0e2b18f975", + "zh:aabc64fe64319b95aaba1d1866f87abc7b10adae37d2eafa2f85f37317fdd49f", + "zh:acc6a977814897cb23d3b3753213281334238f8bce6d2b21e9f04fc4087ee980", + "zh:b24987e9416c39cd59c0fa41c139a97406b9955f0607fcafbf3315014456338a", + "zh:c550eae45fd32acdbe32b4e5c450ae95df6cb18903ac7216b1b07b23a16ce045", + "zh:c8f83b763b643893dcb6933a6bcee824cb514e06e7e5c5f5ac4ba187e66d7e22", + "zh:dcdac07e7ea18464dea729717870c275de9453775243c231e1fb305cad0ee597", "zh:f569b65999264a9416862bca5cd2a6177d94ccb0424f3a4ef424428912b9cb3c", ] } provider "registry.terraform.io/hashicorp/local" { - version = "2.2.2" + version = "2.2.3" hashes = [ - "h1:5UYW2wJ320IggrzLt8tLD6MowePqycWtH1b2RInHZkE=", - "zh:027e4873c69da214e2fed131666d5de92089732a11d096b68257da54d30b6f9d", - "zh:0ba2216e16cfb72538d76a4c4945b4567a76f7edbfef926b1c5a08d7bba2a043", - "zh:1fee8f6aae1833c27caa96e156cf99a681b6f085e476d7e1b77d285e21d182c1", - "zh:2e8a3e72e877003df1c390a231e0d8e827eba9f788606e643f8e061218750360", - "zh:719008f9e262aa1523a6f9132adbe9eee93c648c2981f8359ce41a40e6425433", + "h1:aWp5iSUxBGgPv1UnV5yag9Pb0N+U1I0sZb38AXBFO8A=", + "zh:04f0978bb3e052707b8e82e46780c371ac1c66b689b4a23bbc2f58865ab7d5c0", + "zh:6484f1b3e9e3771eb7cc8e8bab8b35f939a55d550b3f4fb2ab141a24269ee6aa", + "zh:78a56d59a013cb0f7eb1c92815d6eb5cf07f8b5f0ae20b96d049e73db915b238", "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", - "zh:9a70fdbe6ef955c4919a4519caca116f34c19c7ddedd77990fbe4f80fe66dc84", - "zh:abc412423d670cbb6264827fa80e1ffdc4a74aff3f19ba6a239dd87b85b15bec", - "zh:ae953a62c94d2a2a0822e5717fafc54e454af57bd6ed02cd301b9786765c1dd3", - "zh:be0910bdf46698560f9e86f51a4ff795c62c02f8dc82b2b1dab77a0b3a93f61e", - "zh:e58f9083b7971919b95f553227adaa7abe864fce976f0166cf4d65fc17257ff2", - "zh:ff4f77cbdbb22cc98182821c7ef84dce16298ab0e997d5c7fae97247f7a4bcb0", + "zh:8aa9950f4c4db37239bcb62e19910c49e47043f6c8587e5b0396619923657797", + "zh:996beea85f9084a725ff0e6473a4594deb5266727c5f56e9c1c7c62ded6addbb", + "zh:9a7ef7a21f48fabfd145b2e2a4240ca57517ad155017e86a30860d7c0c109de3", + "zh:a63e70ac052aa25120113bcddd50c1f3cfe61f681a93a50cea5595a4b2cc3e1c", + "zh:a6e8d46f94108e049ad85dbed60354236dc0b9b5ec8eabe01c4580280a43d3b8", + "zh:bb112ce7efbfcfa0e65ed97fa245ef348e0fd5bfa5a7e4ab2091a9bd469f0a9e", + "zh:d7bec0da5c094c6955efed100f3fe22fca8866859f87c025be1760feb174d6d9", + "zh:fb9f271b72094d07cef8154cd3d50e9aa818a0ea39130bc193132ad7b23076fd", ] } provider "registry.terraform.io/hashicorp/random" { - version = "3.1.3" + version = "3.2.0" hashes = [ - "h1:nLWniS8xhb32qRQy+n4bDPjQ7YWZPVMR3v1vSrx7QyY=", - "zh:26e07aa32e403303fc212a4367b4d67188ac965c37a9812e07acee1470687a73", - "zh:27386f48e9c9d849fbb5a8828d461fde35e71f6b6c9fc235bc4ae8403eb9c92d", - "zh:5f4edda4c94240297bbd9b83618fd362348cadf6bf24ea65ea0e1844d7ccedc0", - "zh:646313a907126cd5e69f6a9fafe816e9154fccdc04541e06fed02bb3a8fa2d2e", - "zh:7349692932a5d462f8dee1500ab60401594dddb94e9aa6bf6c4c0bd53e91bbb8", + "h1:eeUh6cJ6wKLLuo4q9uQ0CA1Zvfqya4Wn1LecLCN8KKs=", + "zh:2960977ce9a7d6a7d3e934e75ec5814735626f95c186ad95a9102344a1a38ac1", + "zh:2fd012abfabe7076f3f2f402eeef4970e20574d20ffec57c162b02b6e848c32f", + "zh:4cd3234671cf01c913023418b227eb78b0659f2cd2e0b387be1f0bb607d29889", + "zh:52e695b4fa3fae735ffc901edff8183745f980923510a744db7616e8f10dc499", "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", - "zh:9034daba8d9b32b35930d168f363af04cecb153d5849a7e4a5966c97c5dc956e", - "zh:bb81dfca59ef5f949ef39f19ea4f4de25479907abc28cdaa36d12ecd7c0a9699", - "zh:bcf7806b99b4c248439ae02c8e21f77aff9fadbc019ce619b929eef09d1221bb", - "zh:d708e14d169e61f326535dd08eecd3811cd4942555a6f8efabc37dbff9c6fc61", - "zh:dc294e19a46e1cefb9e557a7b789c8dd8f319beca99b8c265181bc633dc434cc", - "zh:f9d758ee53c55dc016dd736427b6b0c3c8eb4d0dbbc785b6a3579b0ffedd9e42", + "zh:848b4a294e5ba15192ee4bfd199c07f60a437d7572efcd2d89db036e1ebc0e6e", + "zh:9d49aa432a05748a9527e95448cebee1238c87c97c7e8dec694bfd709683f9c7", + "zh:b4ad4cf289d3f7408649b74b8639918833613f2a1f3cf51b51f4b2fdaa412dd2", + "zh:c1544c4b416096fb8d8dbf84c4488584a2844a30dd533b957e9e9e60a165f24e", + "zh:dc737d6b4591cad8c9a1d0b347e587e846d8d901789b29b4dd401b6cdf82c017", + "zh:f5645fd39f749dbbf847cbdc87ba0dbd141143f12917a6a8904faf8a9b64111e", + "zh:fdedf610e0d020878a8f1fedda8105e0c33a7e23c4792fca54460685552de308", ] } diff --git a/templates/shared_services/gitea/terraform/gitea-webapp.tf b/templates/shared_services/gitea/terraform/gitea-webapp.tf index 18527c8675..52c28ff8c9 100644 --- a/templates/shared_services/gitea/terraform/gitea-webapp.tf +++ b/templates/shared_services/gitea/terraform/gitea-webapp.tf @@ -10,6 +10,7 @@ resource "random_password" "gitea_passwd" { resource "azurerm_user_assigned_identity" "gitea_id" { resource_group_name = local.core_resource_group_name location = data.azurerm_resource_group.rg.location + tags = local.tre_shared_service_tags name = "id-gitea-${var.tre_id}" @@ -23,6 +24,7 @@ resource "azurerm_app_service" "gitea" { app_service_plan_id = data.azurerm_app_service_plan.core.id https_only = true key_vault_reference_identity_id = azurerm_user_assigned_identity.gitea_id.id + tags = local.tre_shared_service_tags app_settings = { APPINSIGHTS_INSTRUMENTATIONKEY = data.azurerm_application_insights.core.instrumentation_key @@ -116,6 +118,7 @@ resource "azurerm_private_endpoint" "gitea_private_endpoint" { resource_group_name = local.core_resource_group_name location = data.azurerm_resource_group.rg.location subnet_id = data.azurerm_subnet.shared.id + tags = local.tre_shared_service_tags private_service_connection { private_connection_resource_id = azurerm_app_service.gitea.id diff --git a/templates/shared_services/gitea/terraform/locals.tf b/templates/shared_services/gitea/terraform/locals.tf index 55d1312511..b20736b615 100644 --- a/templates/shared_services/gitea/terraform/locals.tf +++ b/templates/shared_services/gitea/terraform/locals.tf @@ -7,4 +7,8 @@ locals { keyvault_name = "kv-${var.tre_id}" version = replace(replace(replace(data.local_file.version.content, "__version__ = \"", ""), "\"", ""), "\n", "") gitea_allowed_fqdns_list = distinct(compact(split(",", replace(var.gitea_allowed_fqdns, " ", "")))) + tre_shared_service_tags = { + tre_id = var.tre_id + tre_shared_service_id = var.tre_resource_id + } } diff --git a/templates/shared_services/gitea/terraform/main.tf b/templates/shared_services/gitea/terraform/main.tf index 2ead62214d..42aabdf7d7 100644 --- a/templates/shared_services/gitea/terraform/main.tf +++ b/templates/shared_services/gitea/terraform/main.tf @@ -3,7 +3,7 @@ terraform { required_providers { azurerm = { source = "hashicorp/azurerm" - version = "=3.4.0" + version = "=3.5.0" } } diff --git a/templates/shared_services/gitea/terraform/mysql.tf b/templates/shared_services/gitea/terraform/mysql.tf index a7a04b4ce7..6acc147040 100644 --- a/templates/shared_services/gitea/terraform/mysql.tf +++ b/templates/shared_services/gitea/terraform/mysql.tf @@ -7,13 +7,16 @@ resource "random_password" "password" { } resource "azurerm_mysql_server" "gitea" { - name = "mysql-${var.tre_id}" - resource_group_name = local.core_resource_group_name - location = data.azurerm_resource_group.rg.location - administrator_login = "mysqladmin" - administrator_login_password = random_password.password.result - sku_name = "GP_Gen5_2" - storage_mb = 5120 + name = "mysql-${var.tre_id}" + resource_group_name = local.core_resource_group_name + location = data.azurerm_resource_group.rg.location + administrator_login = "mysqladmin" + administrator_login_password = random_password.password.result + sku_name = "GP_Gen5_2" + storage_mb = 5120 + # Ignoring tflint due to a bug in it. + # TODO: https://github.com/microsoft/AzureTRE/issues/1944 + # tflint-ignore: azurerm_mysql_server_invalid_version version = "8.0" auto_grow_enabled = true backup_retention_days = 7 @@ -22,6 +25,7 @@ resource "azurerm_mysql_server" "gitea" { public_network_access_enabled = false ssl_enforcement_enabled = true ssl_minimal_tls_version_enforced = "TLS1_2" + tags = local.tre_shared_service_tags lifecycle { ignore_changes = [tags] } } @@ -39,6 +43,7 @@ resource "azurerm_private_endpoint" "private-endpoint" { location = data.azurerm_resource_group.rg.location resource_group_name = local.core_resource_group_name subnet_id = data.azurerm_subnet.shared.id + tags = local.tre_shared_service_tags private_service_connection { private_connection_resource_id = azurerm_mysql_server.gitea.id @@ -59,6 +64,7 @@ resource "azurerm_key_vault_secret" "db_password" { name = "${azurerm_mysql_server.gitea.name}-administrator-password" value = random_password.password.result key_vault_id = data.azurerm_key_vault.keyvault.id + tags = local.tre_shared_service_tags depends_on = [ azurerm_key_vault_access_policy.gitea_policy diff --git a/templates/shared_services/gitea/version.txt b/templates/shared_services/gitea/version.txt index f9aa3e1109..d7b30e1210 100644 --- a/templates/shared_services/gitea/version.txt +++ b/templates/shared_services/gitea/version.txt @@ -1 +1 @@ -__version__ = "0.3.2" +__version__ = "0.3.6" diff --git a/templates/shared_services/sonatype-nexus-vm/Dockerfile.tmpl b/templates/shared_services/sonatype-nexus-vm/Dockerfile.tmpl index 3f8524ce64..cd6b922b18 100644 --- a/templates/shared_services/sonatype-nexus-vm/Dockerfile.tmpl +++ b/templates/shared_services/sonatype-nexus-vm/Dockerfile.tmpl @@ -2,15 +2,16 @@ FROM debian:stretch-slim ARG BUNDLE_DIR -RUN apt-get update && apt-get install -y ca-certificates +SHELL ["/bin/bash", "-o", "pipefail", "-c"] # Install Azure CLI RUN apt-get update \ - && apt-get install -y ca-certificates jq curl apt-transport-https lsb-release gnupg \ + && apt-get install -y ca-certificates="20200601~deb9u2" jq="1.5+dfsg-1.3" curl="7.52.1-5+deb9u16" apt-transport-https="1.4.11" lsb-release="9.20161125" gnupg="2.1.18-8~deb9u4" \ && curl -sL https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor | tee /etc/apt/trusted.gpg.d/microsoft.gpg > /dev/null \ && AZ_REPO=$(lsb_release -cs) \ && echo "deb [arch=amd64] https://packages.microsoft.com/repos/azure-cli/ $AZ_REPO main" | tee /etc/apt/sources.list.d/azure-cli.list \ - && apt-get update && apt-get -y install azure-cli + && apt-get update && apt-get -y install azure-cli="2.36.0-1~stretch" \ + && apt-get clean -y && rm -rf /var/lib/apt/lists/* # This is a template Dockerfile for the bundle's invocation image # You can customize it to use different base images, install tools and copy configuration files. diff --git a/templates/shared_services/sonatype-nexus-vm/parameters.json b/templates/shared_services/sonatype-nexus-vm/parameters.json index c01ad0266b..38d90219d7 100755 --- a/templates/shared_services/sonatype-nexus-vm/parameters.json +++ b/templates/shared_services/sonatype-nexus-vm/parameters.json @@ -10,6 +10,12 @@ "env": "TRE_ID" } }, + { + "name": "id", + "source": { + "env": "ID" + } + }, { "name": "tfstate_container_name", "source": { diff --git a/templates/shared_services/sonatype-nexus-vm/porter.yaml b/templates/shared_services/sonatype-nexus-vm/porter.yaml index 5cfc16b8eb..e3e052e2cc 100644 --- a/templates/shared_services/sonatype-nexus-vm/porter.yaml +++ b/templates/shared_services/sonatype-nexus-vm/porter.yaml @@ -1,8 +1,10 @@ --- name: tre-shared-service-sonatype-nexus -version: 2.0.0 +version: 2.0.2 description: "A Sonatype Nexus shared service" registry: azuretre +dockerfile: Dockerfile.tmpl + credentials: - name: azure_tenant_id env: ARM_TENANT_ID @@ -16,6 +18,9 @@ parameters: - name: tre_id type: string description: "The ID of the parent TRE instance e.g., mytre-dev-3142" + - name: id + type: string + description: "Resource ID" - name: tfstate_resource_group_name type: string description: "Resource group containing the Terraform state storage account" @@ -28,6 +33,7 @@ parameters: description: "The name of the Terraform state storage container" - name: arm_use_msi env: ARM_USE_MSI + type: boolean default: false - name: ssl_cert_name type: string @@ -36,7 +42,6 @@ parameters: mixins: - exec - - az - terraform: clientVersion: 1.1.5 install: @@ -45,6 +50,7 @@ install: input: false vars: tre_id: "{{ bundle.parameters.tre_id }}" + tre_resource_id: "{{ bundle.parameters.id }}" ssl_cert_name: "{{ bundle.parameters.ssl_cert_name }}" backendConfig: resource_group_name: @@ -65,6 +71,7 @@ uninstall: input: false vars: tre_id: "{{ bundle.parameters.tre_id }}" + tre_resource_id: "{{ bundle.parameters.id }}" ssl_cert_name: "{{ bundle.parameters.ssl_cert_name }}" backendConfig: resource_group_name: diff --git a/templates/shared_services/sonatype-nexus-vm/terraform/locals.tf b/templates/shared_services/sonatype-nexus-vm/terraform/locals.tf index d9736d661d..2bdb2719c4 100644 --- a/templates/shared_services/sonatype-nexus-vm/terraform/locals.tf +++ b/templates/shared_services/sonatype-nexus-vm/terraform/locals.tf @@ -5,4 +5,8 @@ locals { nexus_allowed_fqdns = "*pypi.org,files.pythonhosted.org,security.ubuntu.com,archive.ubuntu.com,keyserver.ubuntu.com,repo.anaconda.com,*.docker.com,*.docker.io,conda.anaconda.org,azure.archive.ubuntu.com, packages.microsoft.com" nexus_allowed_fqdns_list = distinct(compact(split(",", replace(local.nexus_allowed_fqdns, " ", "")))) storage_account_name = lower(replace("stg-${var.tre_id}", "-", "")) + tre_shared_service_tags = { + tre_id = var.tre_id + tre_shared_service_id = var.tre_resource_id + } } diff --git a/templates/shared_services/sonatype-nexus-vm/terraform/variables.tf b/templates/shared_services/sonatype-nexus-vm/terraform/variables.tf index 604381e20d..23c2fa3826 100644 --- a/templates/shared_services/sonatype-nexus-vm/terraform/variables.tf +++ b/templates/shared_services/sonatype-nexus-vm/terraform/variables.tf @@ -2,6 +2,11 @@ variable "tre_id" { type = string } +variable "tre_resource_id" { + type = string + description = "Resource ID" +} + variable "ssl_cert_name" { type = string } diff --git a/templates/shared_services/sonatype-nexus-vm/terraform/vm.tf b/templates/shared_services/sonatype-nexus-vm/terraform/vm.tf index 301b70ac40..d521ec526f 100644 --- a/templates/shared_services/sonatype-nexus-vm/terraform/vm.tf +++ b/templates/shared_services/sonatype-nexus-vm/terraform/vm.tf @@ -2,6 +2,7 @@ resource "azurerm_network_interface" "nexus" { name = "nic-nexus-${var.tre_id}" location = data.azurerm_resource_group.rg.location resource_group_name = local.core_resource_group_name + tags = local.tre_shared_service_tags ip_configuration { name = "primary" @@ -15,6 +16,7 @@ resource "azurerm_private_dns_zone_virtual_network_link" "nexus_core_vnet" { resource_group_name = local.core_resource_group_name private_dns_zone_name = data.azurerm_private_dns_zone.nexus.name virtual_network_id = data.azurerm_virtual_network.core.id + tags = local.tre_shared_service_tags } resource "azurerm_private_dns_a_record" "nexus_vm" { @@ -23,6 +25,7 @@ resource "azurerm_private_dns_a_record" "nexus_vm" { resource_group_name = local.core_resource_group_name ttl = 300 records = [azurerm_linux_virtual_machine.nexus.private_ip_address] + tags = local.tre_shared_service_tags } resource "random_password" "nexus_vm_password" { @@ -55,18 +58,21 @@ resource "azurerm_key_vault_secret" "nexus_vm_password" { name = "nexus-vm-password" value = random_password.nexus_vm_password.result key_vault_id = data.azurerm_key_vault.kv.id + tags = local.tre_shared_service_tags } resource "azurerm_key_vault_secret" "nexus_admin_password" { name = "nexus-admin-password" value = random_password.nexus_admin_password.result key_vault_id = data.azurerm_key_vault.kv.id + tags = local.tre_shared_service_tags } resource "azurerm_user_assigned_identity" "nexus_msi" { name = "id-nexus-${var.tre_id}" location = data.azurerm_resource_group.rg.location resource_group_name = local.core_resource_group_name + tags = local.tre_shared_service_tags lifecycle { ignore_changes = [tags] } } @@ -87,6 +93,7 @@ resource "azurerm_linux_virtual_machine" "nexus" { disable_password_authentication = false admin_username = "adminuser" admin_password = random_password.nexus_vm_password.result + tags = local.tre_shared_service_tags custom_data = data.template_cloudinit_config.nexus_config.rendered diff --git a/templates/shared_services/sonatype-nexus/Dockerfile.tmpl b/templates/shared_services/sonatype-nexus/Dockerfile.tmpl index 3f8524ce64..cd6b922b18 100644 --- a/templates/shared_services/sonatype-nexus/Dockerfile.tmpl +++ b/templates/shared_services/sonatype-nexus/Dockerfile.tmpl @@ -2,15 +2,16 @@ FROM debian:stretch-slim ARG BUNDLE_DIR -RUN apt-get update && apt-get install -y ca-certificates +SHELL ["/bin/bash", "-o", "pipefail", "-c"] # Install Azure CLI RUN apt-get update \ - && apt-get install -y ca-certificates jq curl apt-transport-https lsb-release gnupg \ + && apt-get install -y ca-certificates="20200601~deb9u2" jq="1.5+dfsg-1.3" curl="7.52.1-5+deb9u16" apt-transport-https="1.4.11" lsb-release="9.20161125" gnupg="2.1.18-8~deb9u4" \ && curl -sL https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor | tee /etc/apt/trusted.gpg.d/microsoft.gpg > /dev/null \ && AZ_REPO=$(lsb_release -cs) \ && echo "deb [arch=amd64] https://packages.microsoft.com/repos/azure-cli/ $AZ_REPO main" | tee /etc/apt/sources.list.d/azure-cli.list \ - && apt-get update && apt-get -y install azure-cli + && apt-get update && apt-get -y install azure-cli="2.36.0-1~stretch" \ + && apt-get clean -y && rm -rf /var/lib/apt/lists/* # This is a template Dockerfile for the bundle's invocation image # You can customize it to use different base images, install tools and copy configuration files. diff --git a/templates/shared_services/sonatype-nexus/porter.yaml b/templates/shared_services/sonatype-nexus/porter.yaml index 0f5d9b8531..102004696d 100644 --- a/templates/shared_services/sonatype-nexus/porter.yaml +++ b/templates/shared_services/sonatype-nexus/porter.yaml @@ -1,8 +1,10 @@ --- name: tre-shared-service-nexus -version: 0.3.1 +version: 0.3.3 description: "A Sonatype Nexus shared service" registry: azuretre +dockerfile: Dockerfile.tmpl + credentials: - name: azure_tenant_id env: ARM_TENANT_ID @@ -31,10 +33,10 @@ parameters: description: "The name of the Terraform state storage container" - name: arm_use_msi env: ARM_USE_MSI + type: boolean default: false mixins: - exec - - az - terraform: clientVersion: 1.1.5 install: @@ -45,10 +47,8 @@ install: tre_id: "{{ bundle.parameters.tre_id }}" tre_resource_id: "{{ bundle.parameters.id }}" backendConfig: - resource_group_name: - "{{ bundle.parameters.tfstate_resource_group_name }}" - storage_account_name: - "{{ bundle.parameters.tfstate_storage_account_name }}" + resource_group_name: "{{ bundle.parameters.tfstate_resource_group_name }}" + storage_account_name: "{{ bundle.parameters.tfstate_storage_account_name }}" container_name: "{{ bundle.parameters.tfstate_container_name }}" key: "{{ bundle.parameters.tre_id }}-shared-service-sonatype-nexus" upgrade: @@ -65,9 +65,7 @@ uninstall: tre_id: "{{ bundle.parameters.tre_id }}" tre_resource_id: "{{ bundle.parameters.id }}" backendConfig: - resource_group_name: - "{{ bundle.parameters.tfstate_resource_group_name }}" - storage_account_name: - "{{ bundle.parameters.tfstate_storage_account_name }}" + resource_group_name: "{{ bundle.parameters.tfstate_resource_group_name }}" + storage_account_name: "{{ bundle.parameters.tfstate_storage_account_name }}" container_name: "{{ bundle.parameters.tfstate_container_name }}" key: "{{ bundle.parameters.tre_id }}-shared-service-sonatype-nexus" diff --git a/templates/shared_services/sonatype-nexus/terraform/.terraform.lock.hcl b/templates/shared_services/sonatype-nexus/terraform/.terraform.lock.hcl index 6ce0e29592..f980a633f3 100644 --- a/templates/shared_services/sonatype-nexus/terraform/.terraform.lock.hcl +++ b/templates/shared_services/sonatype-nexus/terraform/.terraform.lock.hcl @@ -2,38 +2,40 @@ # Manual edits may be lost in future updates. provider "registry.terraform.io/hashicorp/azurerm" { - version = "2.97.0" - constraints = "2.97.0" + version = "3.5.0" + constraints = "3.5.0" hashes = [ - "h1:XxT+XM/leTXa21aTnJjPBfNBQ8cLE4gYDg01WEZsV1U=", - "zh:0aac80e6d2b8ddf33d558ac893d52688e8abf8a0b995cfc3c35eb84afbf432a3", - "zh:11191068cb732208ebc8662651782f63db329a25f7ea1cd50cd91622a2c247b7", - "zh:36c8334194e7d605682053c7c70fbb2a650d9b0a7bcc44d5cdda4f205818438a", - "zh:3a5e01276added995e875b42ecc6b36ff73d267f0c096c87195bd2b1fff4f5b2", - "zh:557e38371657e6ed8aae9192d01480c4cca7c0f7ade6022f1aec247a6384922b", - "zh:67b913c280c5858549477a4b05e77078b1a5234de77c7bddd4ee1e8e237d5665", - "zh:7aeca864ce45b295db734cd968f7596ff12cd7c522ee89d53f432dae7c2b5d18", - "zh:b6127d7a796eaf9756dd212667eb48f79c0e78729589ec8ccf68e0b36ebb4e54", - "zh:bed448238740f897d1b399e5123b3a9eba256b981846f9ee92b71493446ca684", - "zh:c351a1bba34c3bd06fff75e4c15e4db0456268479463c2471598068ea1c5c884", - "zh:d073c24d0a4756e79b39f41f552d526800f9fb0ad0a74f742ac8de61b6416a3a", + "h1:T4XsCHDT839VehWKdxbVsLn0ECjcQaUTzbSGW055pgM=", + "zh:0d8ae6d6e87f44ed4a178be03d6466339b0bb578ab54c2677e365a8281b0bb7d", + "zh:29d250d1a18d49652b28f234ecd17687b36c875dc47877a678e587d5d136b054", + "zh:2e69ba373cf009e8a60b36d04f3dbc4638708d1bf88be9f96b3e52cbf8f47f31", + "zh:53d525dd84ac63b5f749bfbc6b70a202dacf29597664d2ab1165efea6f24f630", + "zh:a25024d574ccd5ae6c2962f3bb71d510f62899f493b1ed096f2f7f0e2b18f975", + "zh:aabc64fe64319b95aaba1d1866f87abc7b10adae37d2eafa2f85f37317fdd49f", + "zh:acc6a977814897cb23d3b3753213281334238f8bce6d2b21e9f04fc4087ee980", + "zh:b24987e9416c39cd59c0fa41c139a97406b9955f0607fcafbf3315014456338a", + "zh:c550eae45fd32acdbe32b4e5c450ae95df6cb18903ac7216b1b07b23a16ce045", + "zh:c8f83b763b643893dcb6933a6bcee824cb514e06e7e5c5f5ac4ba187e66d7e22", + "zh:dcdac07e7ea18464dea729717870c275de9453775243c231e1fb305cad0ee597", + "zh:f569b65999264a9416862bca5cd2a6177d94ccb0424f3a4ef424428912b9cb3c", ] } provider "registry.terraform.io/hashicorp/null" { - version = "3.1.0" + version = "3.1.1" hashes = [ - "h1:vpC6bgUQoJ0znqIKVFevOdq+YQw42bRq0u+H3nto8nA=", - "zh:02a1675fd8de126a00460942aaae242e65ca3380b5bb192e8773ef3da9073fd2", - "zh:53e30545ff8926a8e30ad30648991ca8b93b6fa496272cd23b26763c8ee84515", - "zh:5f9200bf708913621d0f6514179d89700e9aa3097c77dac730e8ba6e5901d521", - "zh:9ebf4d9704faba06b3ec7242c773c0fbfe12d62db7d00356d4f55385fc69bfb2", - "zh:a6576c81adc70326e4e1c999c04ad9ca37113a6e925aefab4765e5a5198efa7e", - "zh:a8a42d13346347aff6c63a37cda9b2c6aa5cc384a55b2fe6d6adfa390e609c53", - "zh:c797744d08a5307d50210e0454f91ca4d1c7621c68740441cf4579390452321d", - "zh:cecb6a304046df34c11229f20a80b24b1603960b794d68361a67c5efe58e62b8", - "zh:e1371aa1e502000d9974cfaff5be4cfa02f47b17400005a16f14d2ef30dc2a70", - "zh:fc39cc1fe71234a0b0369d5c5c7f876c71b956d23d7d6f518289737a001ba69b", - "zh:fea4227271ebf7d9e2b61b89ce2328c7262acd9fd190e1fd6d15a591abfa848e", + "h1:71sNUDvmiJcijsvfXpiLCz0lXIBSsEJjMxljt7hxMhw=", + "zh:063466f41f1d9fd0dd93722840c1314f046d8760b1812fa67c34de0afcba5597", + "zh:08c058e367de6debdad35fc24d97131c7cf75103baec8279aba3506a08b53faf", + "zh:73ce6dff935150d6ddc6ac4a10071e02647d10175c173cfe5dca81f3d13d8afe", + "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", + "zh:8fdd792a626413502e68c195f2097352bdc6a0df694f7df350ed784741eb587e", + "zh:976bbaf268cb497400fd5b3c774d218f3933271864345f18deebe4dcbfcd6afa", + "zh:b21b78ca581f98f4cdb7a366b03ae9db23a73dfa7df12c533d7c19b68e9e72e5", + "zh:b7fc0c1615dbdb1d6fd4abb9c7dc7da286631f7ca2299fb9cd4664258ccfbff4", + "zh:d1efc942b2c44345e0c29bc976594cb7278c38cfb8897b344669eafbc3cddf46", + "zh:e356c245b3cd9d4789bab010893566acace682d7db877e52d40fc4ca34a50924", + "zh:ea98802ba92fcfa8cf12cbce2e9e7ebe999afbf8ed47fa45fc847a098d89468b", + "zh:eff8872458806499889f6927b5d954560f3d74bf20b6043409edf94d26cd906f", ] } diff --git a/templates/shared_services/sonatype-nexus/terraform/data.tf b/templates/shared_services/sonatype-nexus/terraform/data.tf index 2c87cc3f82..7c031011bb 100644 --- a/templates/shared_services/sonatype-nexus/terraform/data.tf +++ b/templates/shared_services/sonatype-nexus/terraform/data.tf @@ -3,7 +3,7 @@ data "azurerm_log_analytics_workspace" "tre" { resource_group_name = local.core_resource_group_name } -data "azurerm_app_service_plan" "core" { +data "azurerm_service_plan" "core" { name = "plan-${var.tre_id}" resource_group_name = local.core_resource_group_name } diff --git a/templates/shared_services/sonatype-nexus/terraform/locals.tf b/templates/shared_services/sonatype-nexus/terraform/locals.tf index 015df1fe39..770deefe5e 100644 --- a/templates/shared_services/sonatype-nexus/terraform/locals.tf +++ b/templates/shared_services/sonatype-nexus/terraform/locals.tf @@ -4,4 +4,8 @@ locals { firewall_name = "fw-${var.tre_id}" storage_account_name = lower(replace("stg-${var.tre_id}", "-", "")) nexus_allowed_fqdns_list = distinct(compact(split(",", replace(var.nexus_allowed_fqdns, " ", "")))) + tre_shared_service_tags = { + tre_id = var.tre_id + tre_shared_service_id = var.tre_resource_id + } } diff --git a/templates/shared_services/sonatype-nexus/terraform/main.tf b/templates/shared_services/sonatype-nexus/terraform/main.tf index 715a8db036..fa8b6fa244 100644 --- a/templates/shared_services/sonatype-nexus/terraform/main.tf +++ b/templates/shared_services/sonatype-nexus/terraform/main.tf @@ -3,7 +3,7 @@ terraform { required_providers { azurerm = { source = "hashicorp/azurerm" - version = "=2.97.0" + version = "=3.5.0" } } diff --git a/templates/shared_services/sonatype-nexus/terraform/webapp.tf b/templates/shared_services/sonatype-nexus/terraform/webapp.tf index b7044e0709..2c0ffb708b 100644 --- a/templates/shared_services/sonatype-nexus/terraform/webapp.tf +++ b/templates/shared_services/sonatype-nexus/terraform/webapp.tf @@ -2,8 +2,9 @@ resource "azurerm_app_service" "nexus" { name = "nexus-${var.tre_id}" resource_group_name = local.core_resource_group_name location = data.azurerm_resource_group.rg.location - app_service_plan_id = data.azurerm_app_service_plan.core.id + app_service_plan_id = data.azurerm_service_plan.core.id https_only = true + tags = local.tre_shared_service_tags app_settings = { APPINSIGHTS_INSTRUMENTATIONKEY = data.azurerm_application_insights.core.instrumentation_key @@ -68,6 +69,7 @@ resource "azurerm_private_endpoint" "nexus_private_endpoint" { resource_group_name = local.core_resource_group_name location = data.azurerm_resource_group.rg.location subnet_id = data.azurerm_subnet.shared.id + tags = local.tre_shared_service_tags private_service_connection { private_connection_resource_id = azurerm_app_service.nexus.id diff --git a/templates/workspace_services/azureml/Dockerfile.tmpl b/templates/workspace_services/azureml/Dockerfile.tmpl index 63dc0b4ca5..79f66c2b75 100644 --- a/templates/workspace_services/azureml/Dockerfile.tmpl +++ b/templates/workspace_services/azureml/Dockerfile.tmpl @@ -1,12 +1,15 @@ -FROM debian:buster +FROM debian:stretch-slim + +SHELL ["/bin/bash", "-o", "pipefail", "-c"] # Install Azure CLI RUN apt-get update \ - && apt-get install -y ca-certificates jq curl apt-transport-https lsb-release gnupg \ + && apt-get install -y ca-certificates="20200601~deb9u2" jq="1.5+dfsg-1.3" curl="7.52.1-5+deb9u16" apt-transport-https="1.4.11" lsb-release="9.20161125" gnupg="2.1.18-8~deb9u4" \ && curl -sL https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor | tee /etc/apt/trusted.gpg.d/microsoft.gpg > /dev/null \ && AZ_REPO=$(lsb_release -cs) \ && echo "deb [arch=amd64] https://packages.microsoft.com/repos/azure-cli/ $AZ_REPO main" | tee /etc/apt/sources.list.d/azure-cli.list \ - && apt-get update && apt-get -y install azure-cli + && apt-get update && apt-get -y install azure-cli="2.36.0-1~stretch" \ + && apt-get clean -y && rm -rf /var/lib/apt/lists/* RUN az extension add --name azure-firewall diff --git a/templates/workspace_services/azureml/porter.yaml b/templates/workspace_services/azureml/porter.yaml index e5b4340c26..440055ae5e 100644 --- a/templates/workspace_services/azureml/porter.yaml +++ b/templates/workspace_services/azureml/porter.yaml @@ -1,6 +1,6 @@ --- name: tre-service-azureml -version: 0.3.0 +version: 0.3.1 description: "An Azure TRE service for Azure Machine Learning" registry: azuretre dockerfile: Dockerfile.tmpl @@ -64,10 +64,8 @@ install: arm_client_secret: "{{ bundle.credentials.azure_client_secret }}" arm_use_msi: "{{ bundle.parameters.arm_use_msi }}" backendConfig: - resource_group_name: - "{{ bundle.parameters.tfstate_resource_group_name }}" - storage_account_name: - "{{ bundle.parameters.tfstate_storage_account_name }}" + resource_group_name: "{{ bundle.parameters.tfstate_resource_group_name }}" + storage_account_name: "{{ bundle.parameters.tfstate_storage_account_name }}" container_name: "{{ bundle.parameters.tfstate_container_name }}" key: "tre-service-azureml-{{ bundle.parameters.id }}" outputs: @@ -94,9 +92,7 @@ uninstall: arm_client_id: "{{ bundle.credentials.azure_client_id }}" arm_client_secret: "{{ bundle.credentials.azure_client_secret }}" backendConfig: - resource_group_name: - "{{ bundle.parameters.tfstate_resource_group_name }}" - storage_account_name: - "{{ bundle.parameters.tfstate_storage_account_name }}" + resource_group_name: "{{ bundle.parameters.tfstate_resource_group_name }}" + storage_account_name: "{{ bundle.parameters.tfstate_storage_account_name }}" container_name: "{{ bundle.parameters.tfstate_container_name }}" key: "tre-service-azureml-{{ bundle.parameters.id }}" diff --git a/templates/workspace_services/azureml/user_resources/aml_compute/Dockerfile.tmpl b/templates/workspace_services/azureml/user_resources/aml_compute/Dockerfile.tmpl index e40f09d2ed..86fc334c03 100644 --- a/templates/workspace_services/azureml/user_resources/aml_compute/Dockerfile.tmpl +++ b/templates/workspace_services/azureml/user_resources/aml_compute/Dockerfile.tmpl @@ -1,4 +1,4 @@ -FROM debian:buster +FROM debian:stretch-slim ARG BUNDLE_DIR diff --git a/templates/workspace_services/azureml/user_resources/aml_compute/porter.yaml b/templates/workspace_services/azureml/user_resources/aml_compute/porter.yaml index 45d1c56b79..5c6c392537 100644 --- a/templates/workspace_services/azureml/user_resources/aml_compute/porter.yaml +++ b/templates/workspace_services/azureml/user_resources/aml_compute/porter.yaml @@ -1,6 +1,6 @@ --- name: tre-user-resource-aml-compute-instance -version: 0.3.0 +version: 0.3.1 description: "Azure Machine Learning Compute Instance" registry: azuretre dockerfile: Dockerfile.tmpl @@ -26,7 +26,7 @@ parameters: type: string - name: vm_size type: string - default: 'Standard_DS2_v3' + default: "Standard_DS2_v3" - name: auth_tenant_id type: string - name: user_object_id @@ -46,6 +46,7 @@ parameters: env: TERRAFORM_STATE_CONTAINER_NAME - name: arm_use_msi env: ARM_USE_MSI + type: boolean default: false mixins: @@ -54,7 +55,6 @@ mixins: - terraform: clientVersion: 1.0.5 - install: - terraform: description: "Deploy service" @@ -71,14 +71,11 @@ install: arm_client_secret: "{{ bundle.credentials.azure_client_secret }}" arm_use_msi: "{{ bundle.parameters.arm_use_msi }}" backendConfig: - resource_group_name: - "{{ bundle.parameters.tfstate_resource_group_name }}" - storage_account_name: - "{{ bundle.parameters.tfstate_storage_account_name }}" + resource_group_name: "{{ bundle.parameters.tfstate_resource_group_name }}" + storage_account_name: "{{ bundle.parameters.tfstate_storage_account_name }}" container_name: "{{ bundle.parameters.tfstate_container_name }}" key: "tre-user-resource-aml-compute-instance-{{ bundle.parameters.id }}" - uninstall: - exec: description: "Delete AML Compute Instance" diff --git a/templates/workspace_services/devtestlabs/porter.yaml b/templates/workspace_services/devtestlabs/porter.yaml index 9e9767a23e..ed534659e8 100644 --- a/templates/workspace_services/devtestlabs/porter.yaml +++ b/templates/workspace_services/devtestlabs/porter.yaml @@ -34,6 +34,7 @@ parameters: description: "The name of the Terraform state storage container" - name: arm_use_msi env: ARM_USE_MSI + type: boolean default: false mixins: @@ -49,10 +50,8 @@ install: tre_id: "{{ bundle.parameters.tre_id }}" tre_resource_id: "{{ bundle.parameters.id }}" backendConfig: - resource_group_name: - "{{ bundle.parameters.tfstate_resource_group_name }}" - storage_account_name: - "{{ bundle.parameters.tfstate_storage_account_name }}" + resource_group_name: "{{ bundle.parameters.tfstate_resource_group_name }}" + storage_account_name: "{{ bundle.parameters.tfstate_storage_account_name }}" container_name: "{{ bundle.parameters.tfstate_container_name }}" key: "tre-service-devtestlabs-{{ bundle.parameters.id }}" @@ -71,9 +70,7 @@ uninstall: tre_id: "{{ bundle.parameters.tre_id }}" tre_resource_id: "{{ bundle.parameters.id }}" backendConfig: - resource_group_name: - "{{ bundle.parameters.tfstate_resource_group_name }}" - storage_account_name: - "{{ bundle.parameters.tfstate_storage_account_name }}" + resource_group_name: "{{ bundle.parameters.tfstate_resource_group_name }}" + storage_account_name: "{{ bundle.parameters.tfstate_storage_account_name }}" container_name: "{{ bundle.parameters.tfstate_container_name }}" key: "tre-service-devtestlabs-{{ bundle.parameters.id }}" diff --git a/templates/workspace_services/gitea/Dockerfile.tmpl b/templates/workspace_services/gitea/Dockerfile.tmpl deleted file mode 100644 index 3f8524ce64..0000000000 --- a/templates/workspace_services/gitea/Dockerfile.tmpl +++ /dev/null @@ -1,29 +0,0 @@ -FROM debian:stretch-slim - -ARG BUNDLE_DIR - -RUN apt-get update && apt-get install -y ca-certificates - -# Install Azure CLI -RUN apt-get update \ - && apt-get install -y ca-certificates jq curl apt-transport-https lsb-release gnupg \ - && curl -sL https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor | tee /etc/apt/trusted.gpg.d/microsoft.gpg > /dev/null \ - && AZ_REPO=$(lsb_release -cs) \ - && echo "deb [arch=amd64] https://packages.microsoft.com/repos/azure-cli/ $AZ_REPO main" | tee /etc/apt/sources.list.d/azure-cli.list \ - && apt-get update && apt-get -y install azure-cli - -# This is a template Dockerfile for the bundle's invocation image -# You can customize it to use different base images, install tools and copy configuration files. -# -# Porter will use it as a template and append lines to it for the mixins -# and to set the CMD appropriately for the CNAB specification. -# -# Add the following line to porter.yaml to instruct Porter to use this template -# dockerfile: Dockerfile.tmpl - -# You can control where the mixin's Dockerfile lines are inserted into this file by moving "# PORTER_MIXINS" line -# another location in this file. If you remove that line, the mixins generated content is appended to this file. -# PORTER_MIXINS - -# Use the BUNDLE_DIR build argument to copy files into the bundle -COPY . $BUNDLE_DIR diff --git a/templates/workspace_services/gitea/porter.yaml b/templates/workspace_services/gitea/porter.yaml index 2cc1456076..02ab44127a 100644 --- a/templates/workspace_services/gitea/porter.yaml +++ b/templates/workspace_services/gitea/porter.yaml @@ -1,9 +1,8 @@ --- name: tre-workspace-service-gitea -version: 0.3.1 +version: 0.3.2 description: "A Gitea workspace service" registry: azuretre -dockerfile: Dockerfile.tmpl credentials: - name: azure_tenant_id @@ -57,6 +56,7 @@ parameters: description: "The name of the Terraform state storage container" - name: arm_use_msi env: ARM_USE_MSI + type: boolean default: false mixins: diff --git a/templates/workspace_services/gitea/terraform/.terraform.lock.hcl b/templates/workspace_services/gitea/terraform/.terraform.lock.hcl index 00b91198f9..e7d57a8fe4 100644 --- a/templates/workspace_services/gitea/terraform/.terraform.lock.hcl +++ b/templates/workspace_services/gitea/terraform/.terraform.lock.hcl @@ -2,56 +2,59 @@ # Manual edits may be lost in future updates. provider "registry.terraform.io/hashicorp/azurerm" { - version = "2.97.0" - constraints = "2.97.0" + version = "3.5.0" + constraints = "3.5.0" hashes = [ - "h1:XxT+XM/leTXa21aTnJjPBfNBQ8cLE4gYDg01WEZsV1U=", - "zh:0aac80e6d2b8ddf33d558ac893d52688e8abf8a0b995cfc3c35eb84afbf432a3", - "zh:11191068cb732208ebc8662651782f63db329a25f7ea1cd50cd91622a2c247b7", - "zh:36c8334194e7d605682053c7c70fbb2a650d9b0a7bcc44d5cdda4f205818438a", - "zh:3a5e01276added995e875b42ecc6b36ff73d267f0c096c87195bd2b1fff4f5b2", - "zh:557e38371657e6ed8aae9192d01480c4cca7c0f7ade6022f1aec247a6384922b", - "zh:67b913c280c5858549477a4b05e77078b1a5234de77c7bddd4ee1e8e237d5665", - "zh:7aeca864ce45b295db734cd968f7596ff12cd7c522ee89d53f432dae7c2b5d18", - "zh:b6127d7a796eaf9756dd212667eb48f79c0e78729589ec8ccf68e0b36ebb4e54", - "zh:bed448238740f897d1b399e5123b3a9eba256b981846f9ee92b71493446ca684", - "zh:c351a1bba34c3bd06fff75e4c15e4db0456268479463c2471598068ea1c5c884", - "zh:d073c24d0a4756e79b39f41f552d526800f9fb0ad0a74f742ac8de61b6416a3a", + "h1:T4XsCHDT839VehWKdxbVsLn0ECjcQaUTzbSGW055pgM=", + "zh:0d8ae6d6e87f44ed4a178be03d6466339b0bb578ab54c2677e365a8281b0bb7d", + "zh:29d250d1a18d49652b28f234ecd17687b36c875dc47877a678e587d5d136b054", + "zh:2e69ba373cf009e8a60b36d04f3dbc4638708d1bf88be9f96b3e52cbf8f47f31", + "zh:53d525dd84ac63b5f749bfbc6b70a202dacf29597664d2ab1165efea6f24f630", + "zh:a25024d574ccd5ae6c2962f3bb71d510f62899f493b1ed096f2f7f0e2b18f975", + "zh:aabc64fe64319b95aaba1d1866f87abc7b10adae37d2eafa2f85f37317fdd49f", + "zh:acc6a977814897cb23d3b3753213281334238f8bce6d2b21e9f04fc4087ee980", + "zh:b24987e9416c39cd59c0fa41c139a97406b9955f0607fcafbf3315014456338a", + "zh:c550eae45fd32acdbe32b4e5c450ae95df6cb18903ac7216b1b07b23a16ce045", + "zh:c8f83b763b643893dcb6933a6bcee824cb514e06e7e5c5f5ac4ba187e66d7e22", + "zh:dcdac07e7ea18464dea729717870c275de9453775243c231e1fb305cad0ee597", + "zh:f569b65999264a9416862bca5cd2a6177d94ccb0424f3a4ef424428912b9cb3c", ] } provider "registry.terraform.io/hashicorp/local" { - version = "2.1.0" + version = "2.2.3" hashes = [ - "h1:EYZdckuGU3n6APs97nS2LxZm3dDtGqyM4qaIvsmac8o=", - "zh:0f1ec65101fa35050978d483d6e8916664b7556800348456ff3d09454ac1eae2", - "zh:36e42ac19f5d68467aacf07e6adcf83c7486f2e5b5f4339e9671f68525fc87ab", - "zh:6db9db2a1819e77b1642ec3b5e95042b202aee8151a0256d289f2e141bf3ceb3", - "zh:719dfd97bb9ddce99f7d741260b8ece2682b363735c764cac83303f02386075a", - "zh:7598bb86e0378fd97eaa04638c1a4c75f960f62f69d3662e6d80ffa5a89847fe", - "zh:ad0a188b52517fec9eca393f1e2c9daea362b33ae2eb38a857b6b09949a727c1", - "zh:c46846c8df66a13fee6eff7dc5d528a7f868ae0dcf92d79deaac73cc297ed20c", - "zh:dc1a20a2eec12095d04bf6da5321f535351a594a636912361db20eb2a707ccc4", - "zh:e57ab4771a9d999401f6badd8b018558357d3cbdf3d33cc0c4f83e818ca8e94b", - "zh:ebdcde208072b4b0f8d305ebf2bfdc62c926e0717599dcf8ec2fd8c5845031c3", - "zh:ef34c52b68933bedd0868a13ccfd59ff1c820f299760b3c02e008dc95e2ece91", + "h1:aWp5iSUxBGgPv1UnV5yag9Pb0N+U1I0sZb38AXBFO8A=", + "zh:04f0978bb3e052707b8e82e46780c371ac1c66b689b4a23bbc2f58865ab7d5c0", + "zh:6484f1b3e9e3771eb7cc8e8bab8b35f939a55d550b3f4fb2ab141a24269ee6aa", + "zh:78a56d59a013cb0f7eb1c92815d6eb5cf07f8b5f0ae20b96d049e73db915b238", + "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", + "zh:8aa9950f4c4db37239bcb62e19910c49e47043f6c8587e5b0396619923657797", + "zh:996beea85f9084a725ff0e6473a4594deb5266727c5f56e9c1c7c62ded6addbb", + "zh:9a7ef7a21f48fabfd145b2e2a4240ca57517ad155017e86a30860d7c0c109de3", + "zh:a63e70ac052aa25120113bcddd50c1f3cfe61f681a93a50cea5595a4b2cc3e1c", + "zh:a6e8d46f94108e049ad85dbed60354236dc0b9b5ec8eabe01c4580280a43d3b8", + "zh:bb112ce7efbfcfa0e65ed97fa245ef348e0fd5bfa5a7e4ab2091a9bd469f0a9e", + "zh:d7bec0da5c094c6955efed100f3fe22fca8866859f87c025be1760feb174d6d9", + "zh:fb9f271b72094d07cef8154cd3d50e9aa818a0ea39130bc193132ad7b23076fd", ] } provider "registry.terraform.io/hashicorp/random" { - version = "3.1.0" + version = "3.2.0" hashes = [ - "h1:BZMEPucF+pbu9gsPk0G0BHx7YP04+tKdq2MrRDF1EDM=", - "zh:2bbb3339f0643b5daa07480ef4397bd23a79963cc364cdfbb4e86354cb7725bc", - "zh:3cd456047805bf639fbf2c761b1848880ea703a054f76db51852008b11008626", - "zh:4f251b0eda5bb5e3dc26ea4400dba200018213654b69b4a5f96abee815b4f5ff", - "zh:7011332745ea061e517fe1319bd6c75054a314155cb2c1199a5b01fe1889a7e2", - "zh:738ed82858317ccc246691c8b85995bc125ac3b4143043219bd0437adc56c992", - "zh:7dbe52fac7bb21227acd7529b487511c91f4107db9cc4414f50d04ffc3cab427", - "zh:a3a9251fb15f93e4cfc1789800fc2d7414bbc18944ad4c5c98f466e6477c42bc", - "zh:a543ec1a3a8c20635cf374110bd2f87c07374cf2c50617eee2c669b3ceeeaa9f", - "zh:d9ab41d556a48bd7059f0810cf020500635bfc696c9fc3adab5ea8915c1d886b", - "zh:d9e13427a7d011dbd654e591b0337e6074eef8c3b9bb11b2e39eaaf257044fd7", - "zh:f7605bd1437752114baf601bdf6931debe6dc6bfe3006eb7e9bb9080931dca8a", + "h1:eeUh6cJ6wKLLuo4q9uQ0CA1Zvfqya4Wn1LecLCN8KKs=", + "zh:2960977ce9a7d6a7d3e934e75ec5814735626f95c186ad95a9102344a1a38ac1", + "zh:2fd012abfabe7076f3f2f402eeef4970e20574d20ffec57c162b02b6e848c32f", + "zh:4cd3234671cf01c913023418b227eb78b0659f2cd2e0b387be1f0bb607d29889", + "zh:52e695b4fa3fae735ffc901edff8183745f980923510a744db7616e8f10dc499", + "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", + "zh:848b4a294e5ba15192ee4bfd199c07f60a437d7572efcd2d89db036e1ebc0e6e", + "zh:9d49aa432a05748a9527e95448cebee1238c87c97c7e8dec694bfd709683f9c7", + "zh:b4ad4cf289d3f7408649b74b8639918833613f2a1f3cf51b51f4b2fdaa412dd2", + "zh:c1544c4b416096fb8d8dbf84c4488584a2844a30dd533b957e9e9e60a165f24e", + "zh:dc737d6b4591cad8c9a1d0b347e587e846d8d901789b29b4dd401b6cdf82c017", + "zh:f5645fd39f749dbbf847cbdc87ba0dbd141143f12917a6a8904faf8a9b64111e", + "zh:fdedf610e0d020878a8f1fedda8105e0c33a7e23c4792fca54460685552de308", ] } diff --git a/templates/workspace_services/gitea/terraform/main.tf b/templates/workspace_services/gitea/terraform/main.tf index accc59ca4d..7287dba7d5 100644 --- a/templates/workspace_services/gitea/terraform/main.tf +++ b/templates/workspace_services/gitea/terraform/main.tf @@ -3,7 +3,7 @@ terraform { required_providers { azurerm = { source = "hashicorp/azurerm" - version = "=2.97.0" + version = "=3.5.0" } } diff --git a/templates/workspace_services/gitea/version.txt b/templates/workspace_services/gitea/version.txt index 493f7415d7..f9aa3e1109 100644 --- a/templates/workspace_services/gitea/version.txt +++ b/templates/workspace_services/gitea/version.txt @@ -1 +1 @@ -__version__ = "0.3.0" +__version__ = "0.3.2" diff --git a/templates/workspace_services/guacamole/.env.sample b/templates/workspace_services/guacamole/.env.sample index 7603c7052c..0f1ba1666b 100644 --- a/templates/workspace_services/guacamole/.env.sample +++ b/templates/workspace_services/guacamole/.env.sample @@ -7,6 +7,11 @@ WORKSPACE_ID="__CHANGE_ME__" # Guacamole image tag to use (version in templates\workspace\services\guacamole\version.txt) GUACAMOLE_IMAGE_TAG="__CHANGE_ME__" +MGMT_ACR_NAME="__CHANGE_ME__" + +# This is scope_id of the workspace (api://) and you can find this as a workspace +# property in cosmos +WORKSPACE_IDENTIFIER_URI="__CHANGE_ME__" ARM_USE_MSI=false GUAC_DISABLE_COPY=true diff --git a/templates/workspace_services/guacamole/Dockerfile.tmpl b/templates/workspace_services/guacamole/Dockerfile.tmpl index 7c481b3f5b..79f66c2b75 100644 --- a/templates/workspace_services/guacamole/Dockerfile.tmpl +++ b/templates/workspace_services/guacamole/Dockerfile.tmpl @@ -1,14 +1,15 @@ -FROM debian:buster +FROM debian:stretch-slim + +SHELL ["/bin/bash", "-o", "pipefail", "-c"] # Install Azure CLI RUN apt-get update \ - && apt-get install -y ca-certificates jq curl apt-transport-https lsb-release gnupg \ + && apt-get install -y ca-certificates="20200601~deb9u2" jq="1.5+dfsg-1.3" curl="7.52.1-5+deb9u16" apt-transport-https="1.4.11" lsb-release="9.20161125" gnupg="2.1.18-8~deb9u4" \ && curl -sL https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor | tee /etc/apt/trusted.gpg.d/microsoft.gpg > /dev/null \ && AZ_REPO=$(lsb_release -cs) \ && echo "deb [arch=amd64] https://packages.microsoft.com/repos/azure-cli/ $AZ_REPO main" | tee /etc/apt/sources.list.d/azure-cli.list \ - && apt-get update && apt-get -y install azure-cli - -RUN az config set extension.use_dynamic_install=yes_without_prompt + && apt-get update && apt-get -y install azure-cli="2.36.0-1~stretch" \ + && apt-get clean -y && rm -rf /var/lib/apt/lists/* RUN az extension add --name azure-firewall diff --git a/templates/workspace_services/guacamole/guacamole-server/docker/Dockerfile b/templates/workspace_services/guacamole/guacamole-server/docker/Dockerfile index c9ab6fa88b..d2d9165231 100644 --- a/templates/workspace_services/guacamole/guacamole-server/docker/Dockerfile +++ b/templates/workspace_services/guacamole/guacamole-server/docker/Dockerfile @@ -1,12 +1,12 @@ -FROM maven:3-jdk-11-openj9 AS client_build +FROM maven:3-jdk-11 AS client_build -COPY ./guacamole-auth-azure/pom.xml pom.xml -COPY ./guacamole-auth-azure/src src +COPY ./guacamole-auth-azure/pom.xml /pom.xml +COPY ./guacamole-auth-azure/src /src COPY ./docker/maven_package_and_exit_succesfully.sh /tmp/ RUN bash /tmp/maven_package_and_exit_succesfully.sh FROM scratch as test-results -COPY --from=client_build /target/surefire-reports/* ./ +COPY --from=client_build /target/surefire-reports/* / FROM guacamole/guacd:1.4.0 @@ -14,27 +14,31 @@ ARG GUACAMOLE_AZURE_VERSION=0.1.1 ENV DEBIAN_FRONTEND=noninteractive +# https://github.com/microsoft/AzureTRE/issues/1937 +# hadolint ignore=DL3002 USER root # dependencies - -RUN apt-get update && apt-get install wget curl openssh-server apt-transport-https gnupg -y && \ +# hadolint ignore=DL3008 +RUN apt-get update && apt-get install wget curl openssh-server apt-transport-https gnupg -y --no-install-recommends && \ apt-get autoclean && apt-get autoremove && rm -rf /var/lib/apt/lists/* -RUN wget https://github.com/AdoptOpenJDK/openjdk11-binaries/releases/download/jdk-11.0.11%2B9/OpenJDK11U-jre_x64_linux_hotspot_11.0.11_9.tar.gz && \ - mkdir -p /usr/lib/jvm/java-11-openjdk-amd64/ && \ - tar xzf OpenJDK11U-jre_x64_linux_hotspot_11.0.11_9.tar.gz -C /usr/lib/jvm/java-11-openjdk-amd64/ --strip-components=1 && \ - export PATH=/usr/lib/jvm/java-11-openjdk-amd64/bin:$PATH && java -version - -RUN \ - TOMCAT_VER=`curl --silent http://mirror.vorboss.net/apache/tomcat/tomcat-9/ | grep v9 -m 1 | awk '{split($5,c,">v") ; split(c[2],d,"/") ; print d[1]}'` && \ - wget -N http://mirror.vorboss.net/apache/tomcat/tomcat-9/v${TOMCAT_VER}/bin/apache-tomcat-${TOMCAT_VER}.tar.gz &&\ - tar xzf apache-tomcat-${TOMCAT_VER}.tar.gz && \ - rm -f apache-tomcat-${TOMCAT_VER}.tar.gz && \ - mv apache-tomcat-${TOMCAT_VER}/ /usr/share/tomcat9/ - ENV JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64 +RUN JAVA_ARCHIVE=java.tar.gz && \ + wget -O "$JAVA_ARCHIVE" "https://github.com/adoptium/temurin11-binaries/releases/download/jdk-11.0.15%2B10/OpenJDK11U-jre_x64_linux_hotspot_11.0.15_10.tar.gz" --progress=dot:giga && \ + mkdir -p "$JAVA_HOME" && \ + tar xzf "$JAVA_ARCHIVE" -C "$JAVA_HOME" --strip-components=1 && \ + rm -f "$JAVA_ARCHIVE" && \ + export PATH="$JAVA_HOME"/bin:"$PATH" && java -version + ENV CATALINA_BASE=/usr/share/tomcat9/ +RUN TOMCAT_ARCHIVE=tomcat.tar.gz && \ + TOMCAT_VER=9.0.62 && \ + wget -O "$TOMCAT_ARCHIVE" -N "http://mirror.vorboss.net/apache/tomcat/tomcat-9/v${TOMCAT_VER}/bin/apache-tomcat-${TOMCAT_VER}.tar.gz" --progress=dot:giga && \ + tar xzf "$TOMCAT_ARCHIVE" && \ + rm -f "$TOMCAT_ARCHIVE" && \ + mv apache-tomcat-${TOMCAT_VER}/ "$CATALINA_BASE" + ENV GUACAMOLE_HOME=/guacamole/ ENV GUACAMOLE_LIB="${GUACAMOLE_HOME}/lib/" ENV CLASSPATH=${GUACAMOLE_LIB}:${CLASSPATH} @@ -43,23 +47,29 @@ RUN mkdir /guac-transfer COPY ./docker/guacamole/ ${GUACAMOLE_HOME} -RUN wget -O s6-overlay.tar.gz https://github.com/just-containers/s6-overlay/releases/download/v2.2.0.3/s6-overlay-amd64.tar.gz && tar xzvf s6-overlay.tar.gz -C / +RUN S6_ARCHIVE=s6-overlay.tar.gz && \ + wget -O "$S6_ARCHIVE" "https://github.com/just-containers/s6-overlay/releases/download/v2.2.0.3/s6-overlay-amd64.tar.gz" --progress=dot:giga && \ + tar xzvf "$S6_ARCHIVE" -C / && \ + rm -f "$S6_ARCHIVE" COPY ./docker/sshd_config /etc/ssh/ COPY ./docker/services /etc/services.d/ # retrieve auth integration from build image -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.4.0/binary/guacamole-1.4.0.war' +COPY --from=client_build /target/lib/* "${GUACAMOLE_LIB}" +COPY --from=client_build "/target/guacamole-auth-tre-${GUACAMOLE_AZURE_VERSION}.jar" "${GUACAMOLE_HOME}/extensions/" -RUN mkdir /etc/oauth2 +RUN wget -O "${GUACAMOLE_HOME}/guacamole.war" "http://apache.org/dyn/closer.cgi?action=download&filename=guacamole/1.4.0/binary/guacamole-1.4.0.war" --progress=dot:giga -RUN wget -O /etc/oauth2/oauth2-proxy-v7.2.1.linux-amd64.tar.gz 'https://github.com/oauth2-proxy/oauth2-proxy/releases/download/v7.2.1/oauth2-proxy-v7.2.1.linux-amd64.tar.gz' +ENV OAUTH2_PROXY_HOME=/etc/oauth2-proxy +RUN OAUTH2_PROXY_ARCHIVE=oauth2-proxy.tar.gz && \ + wget -O "$OAUTH2_PROXY_ARCHIVE" "https://github.com/oauth2-proxy/oauth2-proxy/releases/download/v7.2.1/oauth2-proxy-v7.2.1.linux-amd64.tar.gz" --progress=dot:giga && \ + mkdir -p "$OAUTH2_PROXY_HOME" && \ + tar zxpf "$OAUTH2_PROXY_ARCHIVE" -C "$OAUTH2_PROXY_HOME" --strip-components=1 && \ + rm -f "$OAUTH2_PROXY_ARCHIVE" -COPY ./docker/index.jsp /usr/share/tomcat9/webapps/ROOT/index.jsp +COPY ./docker/index.jsp "$CATALINA_BASE"/webapps/ROOT/index.jsp ENTRYPOINT [ "/init" ] diff --git a/templates/workspace_services/guacamole/guacamole-server/docker/services/oauth/run b/templates/workspace_services/guacamole/guacamole-server/docker/services/oauth/run index 422935a1d8..7b66bc0d88 100644 --- a/templates/workspace_services/guacamole/guacamole-server/docker/services/oauth/run +++ b/templates/workspace_services/guacamole/guacamole-server/docker/services/oauth/run @@ -2,28 +2,23 @@ set -x echo >&2 "starting oauth2-proxy" -tar zxvpf /etc/oauth2/oauth2-proxy-v7.2.1.linux-amd64.tar.gz - -chmod +x ./oauth2-proxy-v7.2.1.linux-amd64/oauth2-proxy -./oauth2-proxy-v7.2.1.linux-amd64/oauth2-proxy --version - cookiesecret=$(dd if=/dev/urandom bs=32 count=1 2>/dev/null | base64 | tr -d -- '\n' | tr -- '+/' '-_'; echo) -./oauth2-proxy-v7.2.1.linux-amd64/oauth2-proxy \ +"${OAUTH2_PROXY_HOME}"/oauth2-proxy \ --provider oidc \ --skip-provider-button \ --cookie-secret "${cookiesecret}" \ --oidc-issuer-url "${OAUTH2_PROXY_OIDC_ISSUER_URL}" \ ---upstream http://0.0.0.0:8080 \ ---email-domain "${OAUTH2_PROXY_EMAIL_DOMAIN}" \ +--upstream http://0.0.0.0:8080 \ +--email-domain "${OAUTH2_PROXY_EMAIL_DOMAIN}" \ --redirect-url "${OAUTH2_PROXY_REDIRECT_URI}" --pass-host-header true \ --show-debug-on-error true --pass-authorization-header true --pass-user-headers true \ --http-address http://0.0.0.0:8085 \ --https-address https://0.0.0.0:8086 \ ---cookie-secure false \ +--cookie-secure true \ --reverse-proxy true \ --pass-access-token true \ --set-xauthrequest true \ --pass-basic-auth true \ --cookie-refresh 50m \ ---scope "openid offline_access api://${AUDIENCE}/user_impersonation" +--scope "openid offline_access ${AUDIENCE}/user_impersonation" diff --git a/templates/workspace_services/guacamole/porter.yaml b/templates/workspace_services/guacamole/porter.yaml index d145a0046b..f4bafbc727 100644 --- a/templates/workspace_services/guacamole/porter.yaml +++ b/templates/workspace_services/guacamole/porter.yaml @@ -1,6 +1,6 @@ --- name: tre-service-guacamole -version: 0.3.3 +version: 0.3.6 description: "An Azure TRE service for Guacamole" registry: azuretre dockerfile: Dockerfile.tmpl @@ -70,9 +70,11 @@ parameters: type: boolean default: false env: IS_EXPOSED_EXTERNALLY - description: - "Determines if the web app will be available over public/internet - or private networks" + description: "Determines if the web app will be available over public/internet or private networks" + - name: workspace_identifier_uri + type: string + env: WORKSPACE_IDENTIFIER_URI + description: "This is used to define the scope of the oauth2 redirection (e.g. api://treid_ws_wsid)" # the following are added automatically by the resource processor - name: id type: string @@ -114,8 +116,7 @@ install: image_name: "{{ bundle.parameters.image_name }}" image_tag: "{{ bundle.parameters.image_tag }}" mgmt_acr_name: "{{ bundle.parameters.mgmt_acr_name }}" - mgmt_resource_group_name: - "{{ bundle.parameters.mgmt_resource_group_name }}" + mgmt_resource_group_name: "{{ bundle.parameters.mgmt_resource_group_name }}" arm_client_id: "{{ bundle.credentials.azure_client_id }}" arm_client_secret: "{{ bundle.credentials.azure_client_secret }}" arm_tenant_id: "{{ bundle.credentials.azure_tenant_id }}" @@ -128,11 +129,10 @@ install: guac_disable_download: "{{ bundle.parameters.guac_disable_download }}" is_exposed_externally: "{{ bundle.parameters.is_exposed_externally }}" tre_resource_id: "{{ bundle.parameters.id }}" + workspace_identifier_uri: "{{ bundle.parameters.workspace_identifier_uri }}" backendConfig: - resource_group_name: - "{{ bundle.parameters.tfstate_resource_group_name }}" - storage_account_name: - "{{ bundle.parameters.tfstate_storage_account_name }}" + resource_group_name: "{{ bundle.parameters.tfstate_resource_group_name }}" + storage_account_name: "{{ bundle.parameters.tfstate_storage_account_name }}" container_name: "{{ bundle.parameters.tfstate_container_name }}" key: "tre-service-guacamole-{{ bundle.parameters.id }}" outputs: @@ -154,8 +154,7 @@ uninstall: image_name: "{{ bundle.parameters.image_name }}" image_tag: "{{ bundle.parameters.image_tag }}" mgmt_acr_name: "{{ bundle.parameters.mgmt_acr_name }}" - mgmt_resource_group_name: - "{{ bundle.parameters.mgmt_resource_group_name }}" + mgmt_resource_group_name: "{{ bundle.parameters.mgmt_resource_group_name }}" arm_client_id: "{{ bundle.credentials.azure_client_id }}" arm_client_secret: "{{ bundle.credentials.azure_client_secret }}" arm_tenant_id: "{{ bundle.credentials.azure_tenant_id }}" @@ -168,10 +167,9 @@ uninstall: guac_disable_download: "{{ bundle.parameters.guac_disable_download }}" is_exposed_externally: "{{ bundle.parameters.is_exposed_externally }}" tre_resource_id: "{{ bundle.parameters.id }}" + workspace_identifier_uri: "{{ bundle.parameters.workspace_identifier_uri }}" backendConfig: - resource_group_name: - "{{ bundle.parameters.tfstate_resource_group_name }}" - storage_account_name: - "{{ bundle.parameters.tfstate_storage_account_name }}" + resource_group_name: "{{ bundle.parameters.tfstate_resource_group_name }}" + storage_account_name: "{{ bundle.parameters.tfstate_storage_account_name }}" container_name: "{{ bundle.parameters.tfstate_container_name }}" key: "tre-service-guacamole-{{ bundle.parameters.id }}" diff --git a/templates/workspace_services/guacamole/template_schema.json b/templates/workspace_services/guacamole/template_schema.json index 39e013bbb5..707c2ceff5 100644 --- a/templates/workspace_services/guacamole/template_schema.json +++ b/templates/workspace_services/guacamole/template_schema.json @@ -39,6 +39,12 @@ "type": "boolean", "title": "Expose externally", "description": "Is the Guacamole service exposed outside of the vnet" + }, + "workspace_identifier_uri": { + "$id": "#/properties/workspace_identifier_uri", + "type": "string", + "title": "Workspace Identifier URI (Scope)", + "description": "The audience/scope/identifier uri of the workspace in AAD" } } } diff --git a/templates/workspace_services/guacamole/terraform/.terraform.lock.hcl b/templates/workspace_services/guacamole/terraform/.terraform.lock.hcl index 58b8923d3e..52c9fad139 100644 --- a/templates/workspace_services/guacamole/terraform/.terraform.lock.hcl +++ b/templates/workspace_services/guacamole/terraform/.terraform.lock.hcl @@ -2,40 +2,60 @@ # Manual edits may be lost in future updates. provider "registry.terraform.io/hashicorp/azurerm" { - version = "2.97.0" - constraints = "2.97.0" + version = "3.5.0" + constraints = "3.5.0" hashes = [ - "h1:XxT+XM/leTXa21aTnJjPBfNBQ8cLE4gYDg01WEZsV1U=", - "zh:0aac80e6d2b8ddf33d558ac893d52688e8abf8a0b995cfc3c35eb84afbf432a3", - "zh:11191068cb732208ebc8662651782f63db329a25f7ea1cd50cd91622a2c247b7", - "zh:36c8334194e7d605682053c7c70fbb2a650d9b0a7bcc44d5cdda4f205818438a", - "zh:3a5e01276added995e875b42ecc6b36ff73d267f0c096c87195bd2b1fff4f5b2", - "zh:557e38371657e6ed8aae9192d01480c4cca7c0f7ade6022f1aec247a6384922b", - "zh:67b913c280c5858549477a4b05e77078b1a5234de77c7bddd4ee1e8e237d5665", - "zh:7aeca864ce45b295db734cd968f7596ff12cd7c522ee89d53f432dae7c2b5d18", - "zh:b6127d7a796eaf9756dd212667eb48f79c0e78729589ec8ccf68e0b36ebb4e54", - "zh:bed448238740f897d1b399e5123b3a9eba256b981846f9ee92b71493446ca684", - "zh:c351a1bba34c3bd06fff75e4c15e4db0456268479463c2471598068ea1c5c884", - "zh:d073c24d0a4756e79b39f41f552d526800f9fb0ad0a74f742ac8de61b6416a3a", + "h1:T4XsCHDT839VehWKdxbVsLn0ECjcQaUTzbSGW055pgM=", + "zh:0d8ae6d6e87f44ed4a178be03d6466339b0bb578ab54c2677e365a8281b0bb7d", + "zh:29d250d1a18d49652b28f234ecd17687b36c875dc47877a678e587d5d136b054", + "zh:2e69ba373cf009e8a60b36d04f3dbc4638708d1bf88be9f96b3e52cbf8f47f31", + "zh:53d525dd84ac63b5f749bfbc6b70a202dacf29597664d2ab1165efea6f24f630", + "zh:a25024d574ccd5ae6c2962f3bb71d510f62899f493b1ed096f2f7f0e2b18f975", + "zh:aabc64fe64319b95aaba1d1866f87abc7b10adae37d2eafa2f85f37317fdd49f", + "zh:acc6a977814897cb23d3b3753213281334238f8bce6d2b21e9f04fc4087ee980", + "zh:b24987e9416c39cd59c0fa41c139a97406b9955f0607fcafbf3315014456338a", + "zh:c550eae45fd32acdbe32b4e5c450ae95df6cb18903ac7216b1b07b23a16ce045", + "zh:c8f83b763b643893dcb6933a6bcee824cb514e06e7e5c5f5ac4ba187e66d7e22", + "zh:dcdac07e7ea18464dea729717870c275de9453775243c231e1fb305cad0ee597", + "zh:f569b65999264a9416862bca5cd2a6177d94ccb0424f3a4ef424428912b9cb3c", ] } provider "registry.terraform.io/hashicorp/external" { - version = "2.2.0" + version = "2.2.2" hashes = [ - "h1:iU5OVMibHvIxbj2Dye1q3aYpjYXS3bKL9iZWZyh+xTg=", - "zh:094c3cfae140fbb70fb0e272b1df833b4d7467c6c819fbf59a3e8ac0922f95b6", - "zh:15c3906abbc1cd03a72afd02bda9caeeb5f6ca421292c32ddeb2acd7a3488669", - "zh:388c14bceeb1593bb16cadedc8f5ad7d41d398197db049dc0871bc847aa61083", - "zh:5696772136b6763faade0cc065fafc2bf06493021b943826be0144790fae514a", - "zh:6427c693b1b750644d5b633395e54617dc36ae717a531a5cde8cb0246b6593ca", - "zh:7196d9845eeffa3158f5e3067bf8b7ad489490aa26d29e2da1ad4c8924463469", + "h1:e7RpnZ2PbJEEPnfsg7V0FNwbfSk0/Z3FdrLsXINBmDY=", + "zh:0b84ab0af2e28606e9c0c1289343949339221c3ab126616b831ddb5aaef5f5ca", + "zh:10cf5c9b9524ca2e4302bf02368dc6aac29fb50aeaa6f7758cce9aa36ae87a28", + "zh:56a016ee871c8501acb3f2ee3b51592ad7c3871a1757b098838349b17762ba6b", + "zh:719d6ef39c50e4cffc67aa67d74d195adaf42afcf62beab132dafdb500347d39", "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", - "zh:8850d3ce9e5f5776b9349890ce4e2c4056defe16ed741dc845045942a6d9e025", - "zh:a2c6fc6cf087b35ebd6b6f20272ed32d4217ea9936c1dd630baa46d86718a455", - "zh:ac709be4ea5c9a6e1ab80e864d24cd9f8e6aaea29fb5dbe1de0897e2e86c3c17", - "zh:dcf806f044801fae5b21ae2754dc3c19c68e458d4584965752ce49be75305ff5", - "zh:f875b34be86c3439899828978638ef7e2d41a9e5e32397858a0c31daeaa1abc2", + "zh:7fbfc4d37435ac2f717b0316f872f558f608596b389b895fcb549f118462d327", + "zh:8ac71408204db606ce63fe8f9aeaf1ddc7751d57d586ec421e62d440c402e955", + "zh:a4cacdb06f114454b6ed0033add28006afa3f65a0ea7a43befe45fc82e6809fb", + "zh:bb5ce3132b52ae32b6cc005bc9f7627b95259b9ffe556de4dad60d47d47f21f0", + "zh:bb60d2976f125ffd232a7ccb4b3f81e7109578b23c9c6179f13a11d125dca82a", + "zh:f9540ecd2e056d6e71b9ea5f5a5cf8f63dd5c25394b9db831083a9d4ea99b372", + "zh:ffd998b55b8a64d4335a090b6956b4bf8855b290f7554dd38db3302de9c41809", + ] +} + +provider "registry.terraform.io/hashicorp/local" { + version = "2.2.3" + hashes = [ + "h1:aWp5iSUxBGgPv1UnV5yag9Pb0N+U1I0sZb38AXBFO8A=", + "zh:04f0978bb3e052707b8e82e46780c371ac1c66b689b4a23bbc2f58865ab7d5c0", + "zh:6484f1b3e9e3771eb7cc8e8bab8b35f939a55d550b3f4fb2ab141a24269ee6aa", + "zh:78a56d59a013cb0f7eb1c92815d6eb5cf07f8b5f0ae20b96d049e73db915b238", + "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", + "zh:8aa9950f4c4db37239bcb62e19910c49e47043f6c8587e5b0396619923657797", + "zh:996beea85f9084a725ff0e6473a4594deb5266727c5f56e9c1c7c62ded6addbb", + "zh:9a7ef7a21f48fabfd145b2e2a4240ca57517ad155017e86a30860d7c0c109de3", + "zh:a63e70ac052aa25120113bcddd50c1f3cfe61f681a93a50cea5595a4b2cc3e1c", + "zh:a6e8d46f94108e049ad85dbed60354236dc0b9b5ec8eabe01c4580280a43d3b8", + "zh:bb112ce7efbfcfa0e65ed97fa245ef348e0fd5bfa5a7e4ab2091a9bd469f0a9e", + "zh:d7bec0da5c094c6955efed100f3fe22fca8866859f87c025be1760feb174d6d9", + "zh:fb9f271b72094d07cef8154cd3d50e9aa818a0ea39130bc193132ad7b23076fd", ] } @@ -59,19 +79,20 @@ provider "registry.terraform.io/hashicorp/local" { } provider "registry.terraform.io/hashicorp/null" { - version = "3.1.0" + version = "3.1.1" hashes = [ - "h1:vpC6bgUQoJ0znqIKVFevOdq+YQw42bRq0u+H3nto8nA=", - "zh:02a1675fd8de126a00460942aaae242e65ca3380b5bb192e8773ef3da9073fd2", - "zh:53e30545ff8926a8e30ad30648991ca8b93b6fa496272cd23b26763c8ee84515", - "zh:5f9200bf708913621d0f6514179d89700e9aa3097c77dac730e8ba6e5901d521", - "zh:9ebf4d9704faba06b3ec7242c773c0fbfe12d62db7d00356d4f55385fc69bfb2", - "zh:a6576c81adc70326e4e1c999c04ad9ca37113a6e925aefab4765e5a5198efa7e", - "zh:a8a42d13346347aff6c63a37cda9b2c6aa5cc384a55b2fe6d6adfa390e609c53", - "zh:c797744d08a5307d50210e0454f91ca4d1c7621c68740441cf4579390452321d", - "zh:cecb6a304046df34c11229f20a80b24b1603960b794d68361a67c5efe58e62b8", - "zh:e1371aa1e502000d9974cfaff5be4cfa02f47b17400005a16f14d2ef30dc2a70", - "zh:fc39cc1fe71234a0b0369d5c5c7f876c71b956d23d7d6f518289737a001ba69b", - "zh:fea4227271ebf7d9e2b61b89ce2328c7262acd9fd190e1fd6d15a591abfa848e", + "h1:71sNUDvmiJcijsvfXpiLCz0lXIBSsEJjMxljt7hxMhw=", + "zh:063466f41f1d9fd0dd93722840c1314f046d8760b1812fa67c34de0afcba5597", + "zh:08c058e367de6debdad35fc24d97131c7cf75103baec8279aba3506a08b53faf", + "zh:73ce6dff935150d6ddc6ac4a10071e02647d10175c173cfe5dca81f3d13d8afe", + "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", + "zh:8fdd792a626413502e68c195f2097352bdc6a0df694f7df350ed784741eb587e", + "zh:976bbaf268cb497400fd5b3c774d218f3933271864345f18deebe4dcbfcd6afa", + "zh:b21b78ca581f98f4cdb7a366b03ae9db23a73dfa7df12c533d7c19b68e9e72e5", + "zh:b7fc0c1615dbdb1d6fd4abb9c7dc7da286631f7ca2299fb9cd4664258ccfbff4", + "zh:d1efc942b2c44345e0c29bc976594cb7278c38cfb8897b344669eafbc3cddf46", + "zh:e356c245b3cd9d4789bab010893566acace682d7db877e52d40fc4ca34a50924", + "zh:ea98802ba92fcfa8cf12cbce2e9e7ebe999afbf8ed47fa45fc847a098d89468b", + "zh:eff8872458806499889f6927b5d954560f3d74bf20b6043409edf94d26cd906f", ] } diff --git a/templates/workspace_services/guacamole/terraform/firewall.tf b/templates/workspace_services/guacamole/terraform/firewall.tf index 044aa42cf5..383865bb76 100644 --- a/templates/workspace_services/guacamole/terraform/firewall.tf +++ b/templates/workspace_services/guacamole/terraform/firewall.tf @@ -50,7 +50,7 @@ resource "azurerm_firewall_network_rule_collection" "networkrulecollection" { action = "Allow" rule { - name = "allowStorage" + name = "AllowAzureAD" source_addresses = data.azurerm_virtual_network.ws.address_space diff --git a/templates/workspace_services/guacamole/terraform/locals.tf b/templates/workspace_services/guacamole/terraform/locals.tf index 400d9cb2e8..bb95fde0ac 100644 --- a/templates/workspace_services/guacamole/terraform/locals.tf +++ b/templates/workspace_services/guacamole/terraform/locals.tf @@ -12,4 +12,9 @@ locals { keyvault_name = lower("kv-${substr(local.workspace_resource_name_suffix, -20, -1)}") image_tag_from_file = replace(replace(replace(data.local_file.version.content, "__version__ = \"", ""), "\"", ""), "\n", "") image_tag = var.image_tag == "" ? local.image_tag_from_file : var.image_tag + workspace_service_tags = { + tre_id = var.tre_id + tre_workspace_id = var.workspace_id + tre_workspace_service_id = var.tre_resource_id + } } diff --git a/templates/workspace_services/guacamole/terraform/main.tf b/templates/workspace_services/guacamole/terraform/main.tf index c9cee03161..f4f544bb7f 100644 --- a/templates/workspace_services/guacamole/terraform/main.tf +++ b/templates/workspace_services/guacamole/terraform/main.tf @@ -3,7 +3,7 @@ terraform { required_providers { azurerm = { source = "hashicorp/azurerm" - version = "=2.97.0" + version = "=3.5.0" } } backend "azurerm" { diff --git a/templates/workspace_services/guacamole/terraform/variables.tf b/templates/workspace_services/guacamole/terraform/variables.tf index 39e53683d8..805735c6ad 100644 --- a/templates/workspace_services/guacamole/terraform/variables.tf +++ b/templates/workspace_services/guacamole/terraform/variables.tf @@ -16,3 +16,4 @@ variable "guac_drive_path" {} variable "guac_disable_download" {} variable "is_exposed_externally" {} variable "tre_resource_id" {} +variable "workspace_identifier_uri" {} diff --git a/templates/workspace_services/guacamole/terraform/web_app.tf b/templates/workspace_services/guacamole/terraform/web_app.tf index 4e49395b29..b48ca56f73 100644 --- a/templates/workspace_services/guacamole/terraform/web_app.tf +++ b/templates/workspace_services/guacamole/terraform/web_app.tf @@ -19,6 +19,7 @@ resource "azurerm_app_service" "guacamole" { app_service_plan_id = data.azurerm_app_service_plan.workspace.id https_only = true key_vault_reference_identity_id = azurerm_user_assigned_identity.guacamole_id.id + tags = local.workspace_service_tags site_config { linux_fx_version = "DOCKER|${data.azurerm_container_registry.mgmt_acr.login_server}/microsoft/azuretre/${var.image_name}:${local.image_tag}" @@ -37,18 +38,18 @@ resource "azurerm_app_service" "guacamole" { TENANT_ID = data.azurerm_client_config.current.tenant_id KEYVAULT_URL = data.azurerm_key_vault.ws.vault_uri API_URL = local.api_url - SERVICE_ID = "${var.tre_resource_id}" - WORKSPACE_ID = "${var.workspace_id}" + SERVICE_ID = var.tre_resource_id + WORKSPACE_ID = var.workspace_id MANAGED_IDENTITY_CLIENT_ID = azurerm_user_assigned_identity.guacamole_id.client_id # Guacmole configuration - GUAC_DISABLE_COPY = "${var.guac_disable_copy}" - GUAC_DISABLE_PASTE = "${var.guac_disable_paste}" - GUAC_ENABLE_DRIVE = "${var.guac_enable_drive}" - GUAC_DRIVE_NAME = "${var.guac_drive_name}" - GUAC_DRIVE_PATH = "${var.guac_drive_path}" - GUAC_DISABLE_DOWNLOAD = "${var.guac_disable_download}" - AUDIENCE = "@Microsoft.KeyVault(SecretUri=${data.azurerm_key_vault_secret.workspace_client_id.id})" + GUAC_DISABLE_COPY = var.guac_disable_copy + GUAC_DISABLE_PASTE = var.guac_disable_paste + GUAC_ENABLE_DRIVE = var.guac_enable_drive + GUAC_DRIVE_NAME = var.guac_drive_name + GUAC_DRIVE_PATH = var.guac_drive_path + GUAC_DISABLE_DOWNLOAD = var.guac_disable_download + AUDIENCE = var.workspace_identifier_uri ISSUER = local.issuer OAUTH2_PROXY_CLIENT_ID = "@Microsoft.KeyVault(SecretUri=${data.azurerm_key_vault_secret.workspace_client_id.id})" @@ -197,6 +198,7 @@ resource "azurerm_private_endpoint" "guacamole" { location = data.azurerm_resource_group.ws.location resource_group_name = data.azurerm_resource_group.ws.name subnet_id = data.azurerm_subnet.services.id + tags = local.workspace_service_tags private_service_connection { private_connection_resource_id = azurerm_app_service.guacamole.id diff --git a/templates/workspace_services/guacamole/user_resources/guacamole-azure-linuxvm/Dockerfile.tmpl b/templates/workspace_services/guacamole/user_resources/guacamole-azure-linuxvm/Dockerfile.tmpl deleted file mode 100644 index eea9a7f790..0000000000 --- a/templates/workspace_services/guacamole/user_resources/guacamole-azure-linuxvm/Dockerfile.tmpl +++ /dev/null @@ -1,30 +0,0 @@ -FROM debian:buster - -# Install Azure CLI -RUN apt-get update \ - && apt-get install -y ca-certificates jq curl apt-transport-https lsb-release gnupg \ - && curl -sL https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor | tee /etc/apt/trusted.gpg.d/microsoft.gpg > /dev/null \ - && AZ_REPO=$(lsb_release -cs) \ - && echo "deb [arch=amd64] https://packages.microsoft.com/repos/azure-cli/ $AZ_REPO main" | tee /etc/apt/sources.list.d/azure-cli.list \ - && apt-get update && apt-get -y install azure-cli - -RUN az config set extension.use_dynamic_install=yes_without_prompt - -ARG BUNDLE_DIR - -# This is a template Dockerfile for the bundle's invocation image -# You can customize it to use different base images, install tools and copy configuration files. -# -# Porter will use it as a template and append lines to it for the mixins -# and to set the CMD appropriately for the CNAB specification. -# -# Add the following line to porter.yaml to instruct Porter to use this template -# dockerfile: Dockerfile.tmpl - -# You can control where the mixin's Dockerfile lines are inserted into this file by moving "# PORTER_MIXINS" line -# another location in this file. If you remove that line, the mixins generated content is appended to this file. -# PORTER_MIXINS - -# Use the BUNDLE_DIR build argument to copy files into the bundle - -COPY . $BUNDLE_DIR diff --git a/templates/workspace_services/guacamole/user_resources/guacamole-azure-linuxvm/porter.yaml b/templates/workspace_services/guacamole/user_resources/guacamole-azure-linuxvm/porter.yaml index 5520924be6..916d83aec7 100644 --- a/templates/workspace_services/guacamole/user_resources/guacamole-azure-linuxvm/porter.yaml +++ b/templates/workspace_services/guacamole/user_resources/guacamole-azure-linuxvm/porter.yaml @@ -1,9 +1,8 @@ --- name: tre-service-guacamole-linuxvm -version: 0.3.2 +version: 0.3.3 description: "An Azure TRE User Resource Template for Guacamole (Linux)" registry: azuretre -dockerfile: Dockerfile.tmpl credentials: - name: azure_tenant_id @@ -43,6 +42,7 @@ parameters: description: "The name of the Terraform state storage container" - name: arm_use_msi env: ARM_USE_MSI + type: boolean default: false - name: os_image type: string @@ -59,7 +59,9 @@ parameters: - name: nexus_version type: string default: "V1" - description: "Which Nexus proxy service to use, i.e. V1 for the App Service-based Nexus or V2 for the VM-based service" + description: >- + "Which Nexus proxy service to use, i.e. V1 for the App Service-based + Nexus or V2 for the VM-based service" outputs: - name: ip @@ -104,10 +106,8 @@ install: shared_storage_name: "{{ bundle.parameters.shared_storage_name }}" nexus_version: "{{ bundle.parameters.nexus_version }}" backendConfig: - resource_group_name: - "{{ bundle.parameters.tfstate_resource_group_name }}" - storage_account_name: - "{{ bundle.parameters.tfstate_storage_account_name }}" + resource_group_name: "{{ bundle.parameters.tfstate_resource_group_name }}" + storage_account_name: "{{ bundle.parameters.tfstate_storage_account_name }}" container_name: "{{ bundle.parameters.tfstate_container_name }}" key: "{{ bundle.parameters.id }}" outputs: @@ -133,10 +133,8 @@ upgrade: shared_storage_name: "{{ bundle.parameters.shared_storage_name }}" nexus_version: "{{ bundle.parameters.nexus_version }}" backendConfig: - resource_group_name: - "{{ bundle.parameters.tfstate_resource_group_name }}" - storage_account_name: - "{{ bundle.parameters.tfstate_storage_account_name }}" + resource_group_name: "{{ bundle.parameters.tfstate_resource_group_name }}" + storage_account_name: "{{ bundle.parameters.tfstate_storage_account_name }}" container_name: "{{ bundle.parameters.tfstate_container_name }}" key: "{{ bundle.parameters.id }}" outputs: @@ -162,10 +160,8 @@ uninstall: shared_storage_name: "{{ bundle.parameters.shared_storage_name }}" nexus_version: "{{ bundle.parameters.nexus_version }}" backendConfig: - resource_group_name: - "{{ bundle.parameters.tfstate_resource_group_name }}" - storage_account_name: - "{{ bundle.parameters.tfstate_storage_account_name }}" + resource_group_name: "{{ bundle.parameters.tfstate_resource_group_name }}" + storage_account_name: "{{ bundle.parameters.tfstate_storage_account_name }}" container_name: "{{ bundle.parameters.tfstate_container_name }}" key: "{{ bundle.parameters.id }}" @@ -175,25 +171,21 @@ start: - "output" description: "Get resource ID from Terraform outputs" backendConfig: - resource_group_name: - "{{ bundle.parameters.tfstate_resource_group_name }}" - storage_account_name: - "{{ bundle.parameters.tfstate_storage_account_name }}" + resource_group_name: "{{ bundle.parameters.tfstate_resource_group_name }}" + storage_account_name: "{{ bundle.parameters.tfstate_storage_account_name }}" container_name: "{{ bundle.parameters.tfstate_container_name }}" key: "{{ bundle.parameters.id }}" outputs: - name: azure_resource_id - az: - description: - "Login to Azure" + description: "Login to Azure" arguments: - login flags: identity: username: "{{ bundle.credentials.azure_client_id }}" - az: - description: - "Start the VM" + description: "Start the VM" arguments: - vm - start @@ -206,25 +198,21 @@ stop: - "output" description: "Get VM hostname and rg from Terraform outputs" backendConfig: - resource_group_name: - "{{ bundle.parameters.tfstate_resource_group_name }}" - storage_account_name: - "{{ bundle.parameters.tfstate_storage_account_name }}" + resource_group_name: "{{ bundle.parameters.tfstate_resource_group_name }}" + storage_account_name: "{{ bundle.parameters.tfstate_storage_account_name }}" container_name: "{{ bundle.parameters.tfstate_container_name }}" key: "{{ bundle.parameters.id }}" outputs: - name: azure_resource_id - az: - description: - "Login to Azure" + description: "Login to Azure" arguments: - login flags: identity: username: "{{ bundle.credentials.azure_client_id }}" - az: - description: - "Stop the VM" + description: "Stop the VM" arguments: - vm - stop diff --git a/templates/workspace_services/guacamole/user_resources/guacamole-azure-linuxvm/terraform/.terraform.lock.hcl b/templates/workspace_services/guacamole/user_resources/guacamole-azure-linuxvm/terraform/.terraform.lock.hcl index 61c54c45c8..3748610cfc 100644 --- a/templates/workspace_services/guacamole/user_resources/guacamole-azure-linuxvm/terraform/.terraform.lock.hcl +++ b/templates/workspace_services/guacamole/user_resources/guacamole-azure-linuxvm/terraform/.terraform.lock.hcl @@ -2,39 +2,41 @@ # Manual edits may be lost in future updates. provider "registry.terraform.io/hashicorp/azurerm" { - version = "2.97.0" - constraints = "2.97.0" + version = "3.5.0" + constraints = "3.5.0" hashes = [ - "h1:XxT+XM/leTXa21aTnJjPBfNBQ8cLE4gYDg01WEZsV1U=", - "zh:0aac80e6d2b8ddf33d558ac893d52688e8abf8a0b995cfc3c35eb84afbf432a3", - "zh:11191068cb732208ebc8662651782f63db329a25f7ea1cd50cd91622a2c247b7", - "zh:36c8334194e7d605682053c7c70fbb2a650d9b0a7bcc44d5cdda4f205818438a", - "zh:3a5e01276added995e875b42ecc6b36ff73d267f0c096c87195bd2b1fff4f5b2", - "zh:557e38371657e6ed8aae9192d01480c4cca7c0f7ade6022f1aec247a6384922b", - "zh:67b913c280c5858549477a4b05e77078b1a5234de77c7bddd4ee1e8e237d5665", - "zh:7aeca864ce45b295db734cd968f7596ff12cd7c522ee89d53f432dae7c2b5d18", - "zh:b6127d7a796eaf9756dd212667eb48f79c0e78729589ec8ccf68e0b36ebb4e54", - "zh:bed448238740f897d1b399e5123b3a9eba256b981846f9ee92b71493446ca684", - "zh:c351a1bba34c3bd06fff75e4c15e4db0456268479463c2471598068ea1c5c884", - "zh:d073c24d0a4756e79b39f41f552d526800f9fb0ad0a74f742ac8de61b6416a3a", + "h1:T4XsCHDT839VehWKdxbVsLn0ECjcQaUTzbSGW055pgM=", + "zh:0d8ae6d6e87f44ed4a178be03d6466339b0bb578ab54c2677e365a8281b0bb7d", + "zh:29d250d1a18d49652b28f234ecd17687b36c875dc47877a678e587d5d136b054", + "zh:2e69ba373cf009e8a60b36d04f3dbc4638708d1bf88be9f96b3e52cbf8f47f31", + "zh:53d525dd84ac63b5f749bfbc6b70a202dacf29597664d2ab1165efea6f24f630", + "zh:a25024d574ccd5ae6c2962f3bb71d510f62899f493b1ed096f2f7f0e2b18f975", + "zh:aabc64fe64319b95aaba1d1866f87abc7b10adae37d2eafa2f85f37317fdd49f", + "zh:acc6a977814897cb23d3b3753213281334238f8bce6d2b21e9f04fc4087ee980", + "zh:b24987e9416c39cd59c0fa41c139a97406b9955f0607fcafbf3315014456338a", + "zh:c550eae45fd32acdbe32b4e5c450ae95df6cb18903ac7216b1b07b23a16ce045", + "zh:c8f83b763b643893dcb6933a6bcee824cb514e06e7e5c5f5ac4ba187e66d7e22", + "zh:dcdac07e7ea18464dea729717870c275de9453775243c231e1fb305cad0ee597", + "zh:f569b65999264a9416862bca5cd2a6177d94ccb0424f3a4ef424428912b9cb3c", ] } provider "registry.terraform.io/hashicorp/random" { - version = "3.1.0" + version = "3.2.0" hashes = [ - "h1:BZMEPucF+pbu9gsPk0G0BHx7YP04+tKdq2MrRDF1EDM=", - "zh:2bbb3339f0643b5daa07480ef4397bd23a79963cc364cdfbb4e86354cb7725bc", - "zh:3cd456047805bf639fbf2c761b1848880ea703a054f76db51852008b11008626", - "zh:4f251b0eda5bb5e3dc26ea4400dba200018213654b69b4a5f96abee815b4f5ff", - "zh:7011332745ea061e517fe1319bd6c75054a314155cb2c1199a5b01fe1889a7e2", - "zh:738ed82858317ccc246691c8b85995bc125ac3b4143043219bd0437adc56c992", - "zh:7dbe52fac7bb21227acd7529b487511c91f4107db9cc4414f50d04ffc3cab427", - "zh:a3a9251fb15f93e4cfc1789800fc2d7414bbc18944ad4c5c98f466e6477c42bc", - "zh:a543ec1a3a8c20635cf374110bd2f87c07374cf2c50617eee2c669b3ceeeaa9f", - "zh:d9ab41d556a48bd7059f0810cf020500635bfc696c9fc3adab5ea8915c1d886b", - "zh:d9e13427a7d011dbd654e591b0337e6074eef8c3b9bb11b2e39eaaf257044fd7", - "zh:f7605bd1437752114baf601bdf6931debe6dc6bfe3006eb7e9bb9080931dca8a", + "h1:eeUh6cJ6wKLLuo4q9uQ0CA1Zvfqya4Wn1LecLCN8KKs=", + "zh:2960977ce9a7d6a7d3e934e75ec5814735626f95c186ad95a9102344a1a38ac1", + "zh:2fd012abfabe7076f3f2f402eeef4970e20574d20ffec57c162b02b6e848c32f", + "zh:4cd3234671cf01c913023418b227eb78b0659f2cd2e0b387be1f0bb607d29889", + "zh:52e695b4fa3fae735ffc901edff8183745f980923510a744db7616e8f10dc499", + "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", + "zh:848b4a294e5ba15192ee4bfd199c07f60a437d7572efcd2d89db036e1ebc0e6e", + "zh:9d49aa432a05748a9527e95448cebee1238c87c97c7e8dec694bfd709683f9c7", + "zh:b4ad4cf289d3f7408649b74b8639918833613f2a1f3cf51b51f4b2fdaa412dd2", + "zh:c1544c4b416096fb8d8dbf84c4488584a2844a30dd533b957e9e9e60a165f24e", + "zh:dc737d6b4591cad8c9a1d0b347e587e846d8d901789b29b4dd401b6cdf82c017", + "zh:f5645fd39f749dbbf847cbdc87ba0dbd141143f12917a6a8904faf8a9b64111e", + "zh:fdedf610e0d020878a8f1fedda8105e0c33a7e23c4792fca54460685552de308", ] } diff --git a/templates/workspace_services/guacamole/user_resources/guacamole-azure-linuxvm/terraform/main.tf b/templates/workspace_services/guacamole/user_resources/guacamole-azure-linuxvm/terraform/main.tf index 01b0ce69bb..c0d76a1f20 100644 --- a/templates/workspace_services/guacamole/user_resources/guacamole-azure-linuxvm/terraform/main.tf +++ b/templates/workspace_services/guacamole/user_resources/guacamole-azure-linuxvm/terraform/main.tf @@ -3,7 +3,7 @@ terraform { required_providers { azurerm = { source = "hashicorp/azurerm" - version = "=2.97.0" + version = "=3.5.0" } } backend "azurerm" { diff --git a/templates/workspace_services/guacamole/user_resources/guacamole-azure-windowsvm/Dockerfile.tmpl b/templates/workspace_services/guacamole/user_resources/guacamole-azure-windowsvm/Dockerfile.tmpl deleted file mode 100644 index eea9a7f790..0000000000 --- a/templates/workspace_services/guacamole/user_resources/guacamole-azure-windowsvm/Dockerfile.tmpl +++ /dev/null @@ -1,30 +0,0 @@ -FROM debian:buster - -# Install Azure CLI -RUN apt-get update \ - && apt-get install -y ca-certificates jq curl apt-transport-https lsb-release gnupg \ - && curl -sL https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor | tee /etc/apt/trusted.gpg.d/microsoft.gpg > /dev/null \ - && AZ_REPO=$(lsb_release -cs) \ - && echo "deb [arch=amd64] https://packages.microsoft.com/repos/azure-cli/ $AZ_REPO main" | tee /etc/apt/sources.list.d/azure-cli.list \ - && apt-get update && apt-get -y install azure-cli - -RUN az config set extension.use_dynamic_install=yes_without_prompt - -ARG BUNDLE_DIR - -# This is a template Dockerfile for the bundle's invocation image -# You can customize it to use different base images, install tools and copy configuration files. -# -# Porter will use it as a template and append lines to it for the mixins -# and to set the CMD appropriately for the CNAB specification. -# -# Add the following line to porter.yaml to instruct Porter to use this template -# dockerfile: Dockerfile.tmpl - -# You can control where the mixin's Dockerfile lines are inserted into this file by moving "# PORTER_MIXINS" line -# another location in this file. If you remove that line, the mixins generated content is appended to this file. -# PORTER_MIXINS - -# Use the BUNDLE_DIR build argument to copy files into the bundle - -COPY . $BUNDLE_DIR diff --git a/templates/workspace_services/guacamole/user_resources/guacamole-azure-windowsvm/porter.yaml b/templates/workspace_services/guacamole/user_resources/guacamole-azure-windowsvm/porter.yaml index c904a2fefd..c0a46a219d 100644 --- a/templates/workspace_services/guacamole/user_resources/guacamole-azure-windowsvm/porter.yaml +++ b/templates/workspace_services/guacamole/user_resources/guacamole-azure-windowsvm/porter.yaml @@ -1,9 +1,8 @@ --- name: tre-service-guacamole-windowsvm -version: 0.3.2 +version: 0.3.3 description: "An Azure TRE User Resource Template for Guacamole (Windows 10)" registry: azuretre -dockerfile: Dockerfile.tmpl credentials: - name: azure_tenant_id @@ -43,6 +42,7 @@ parameters: description: "The name of the Terraform state storage container" - name: arm_use_msi env: ARM_USE_MSI + type: boolean default: false - name: os_image type: string @@ -59,8 +59,9 @@ parameters: - name: nexus_version type: string default: "V1" - description: "Which Nexus proxy service to use, i.e. V1 for the App Service-based Nexus or V2 for the VM-based service" - + description: >- + "Which Nexus proxy service to use, i.e. V1 for the App Service-based + Nexus or V2 for the VM-based service" outputs: - name: ip @@ -105,10 +106,8 @@ install: shared_storage_name: "{{ bundle.parameters.shared_storage_name }}" nexus_version: "{{ bundle.parameters.nexus_version }}" backendConfig: - resource_group_name: - "{{ bundle.parameters.tfstate_resource_group_name }}" - storage_account_name: - "{{ bundle.parameters.tfstate_storage_account_name }}" + resource_group_name: "{{ bundle.parameters.tfstate_resource_group_name }}" + storage_account_name: "{{ bundle.parameters.tfstate_storage_account_name }}" container_name: "{{ bundle.parameters.tfstate_container_name }}" key: "{{ bundle.parameters.id }}" outputs: @@ -134,10 +133,8 @@ upgrade: shared_storage_name: "{{ bundle.parameters.shared_storage_name }}" nexus_version: "{{ bundle.parameters.nexus_version }}" backendConfig: - resource_group_name: - "{{ bundle.parameters.tfstate_resource_group_name }}" - storage_account_name: - "{{ bundle.parameters.tfstate_storage_account_name }}" + resource_group_name: "{{ bundle.parameters.tfstate_resource_group_name }}" + storage_account_name: "{{ bundle.parameters.tfstate_storage_account_name }}" container_name: "{{ bundle.parameters.tfstate_container_name }}" key: "{{ bundle.parameters.id }}" outputs: @@ -163,10 +160,8 @@ uninstall: shared_storage_name: "{{ bundle.parameters.shared_storage_name }}" nexus_version: "{{ bundle.parameters.nexus_version }}" backendConfig: - resource_group_name: - "{{ bundle.parameters.tfstate_resource_group_name }}" - storage_account_name: - "{{ bundle.parameters.tfstate_storage_account_name }}" + resource_group_name: "{{ bundle.parameters.tfstate_resource_group_name }}" + storage_account_name: "{{ bundle.parameters.tfstate_storage_account_name }}" container_name: "{{ bundle.parameters.tfstate_container_name }}" key: "{{ bundle.parameters.id }}" @@ -176,25 +171,21 @@ start: - "output" description: "Get resource ID from Terraform outputs" backendConfig: - resource_group_name: - "{{ bundle.parameters.tfstate_resource_group_name }}" - storage_account_name: - "{{ bundle.parameters.tfstate_storage_account_name }}" + resource_group_name: "{{ bundle.parameters.tfstate_resource_group_name }}" + storage_account_name: "{{ bundle.parameters.tfstate_storage_account_name }}" container_name: "{{ bundle.parameters.tfstate_container_name }}" key: "{{ bundle.parameters.id }}" outputs: - name: azure_resource_id - az: - description: - "Login to Azure" + description: "Login to Azure" arguments: - login flags: identity: username: "{{ bundle.credentials.azure_client_id }}" - az: - description: - "Start the VM" + description: "Start the VM" arguments: - vm - start @@ -207,25 +198,21 @@ stop: - "output" description: "Get VM hostname and rg from Terraform outputs" backendConfig: - resource_group_name: - "{{ bundle.parameters.tfstate_resource_group_name }}" - storage_account_name: - "{{ bundle.parameters.tfstate_storage_account_name }}" + resource_group_name: "{{ bundle.parameters.tfstate_resource_group_name }}" + storage_account_name: "{{ bundle.parameters.tfstate_storage_account_name }}" container_name: "{{ bundle.parameters.tfstate_container_name }}" key: "{{ bundle.parameters.id }}" outputs: - name: azure_resource_id - az: - description: - "Login to Azure" + description: "Login to Azure" arguments: - login flags: identity: username: "{{ bundle.credentials.azure_client_id }}" - az: - description: - "Stop the VM" + description: "Stop the VM" arguments: - vm - stop diff --git a/templates/workspace_services/guacamole/user_resources/guacamole-azure-windowsvm/terraform/.terraform.lock.hcl b/templates/workspace_services/guacamole/user_resources/guacamole-azure-windowsvm/terraform/.terraform.lock.hcl index 61c54c45c8..3748610cfc 100644 --- a/templates/workspace_services/guacamole/user_resources/guacamole-azure-windowsvm/terraform/.terraform.lock.hcl +++ b/templates/workspace_services/guacamole/user_resources/guacamole-azure-windowsvm/terraform/.terraform.lock.hcl @@ -2,39 +2,41 @@ # Manual edits may be lost in future updates. provider "registry.terraform.io/hashicorp/azurerm" { - version = "2.97.0" - constraints = "2.97.0" + version = "3.5.0" + constraints = "3.5.0" hashes = [ - "h1:XxT+XM/leTXa21aTnJjPBfNBQ8cLE4gYDg01WEZsV1U=", - "zh:0aac80e6d2b8ddf33d558ac893d52688e8abf8a0b995cfc3c35eb84afbf432a3", - "zh:11191068cb732208ebc8662651782f63db329a25f7ea1cd50cd91622a2c247b7", - "zh:36c8334194e7d605682053c7c70fbb2a650d9b0a7bcc44d5cdda4f205818438a", - "zh:3a5e01276added995e875b42ecc6b36ff73d267f0c096c87195bd2b1fff4f5b2", - "zh:557e38371657e6ed8aae9192d01480c4cca7c0f7ade6022f1aec247a6384922b", - "zh:67b913c280c5858549477a4b05e77078b1a5234de77c7bddd4ee1e8e237d5665", - "zh:7aeca864ce45b295db734cd968f7596ff12cd7c522ee89d53f432dae7c2b5d18", - "zh:b6127d7a796eaf9756dd212667eb48f79c0e78729589ec8ccf68e0b36ebb4e54", - "zh:bed448238740f897d1b399e5123b3a9eba256b981846f9ee92b71493446ca684", - "zh:c351a1bba34c3bd06fff75e4c15e4db0456268479463c2471598068ea1c5c884", - "zh:d073c24d0a4756e79b39f41f552d526800f9fb0ad0a74f742ac8de61b6416a3a", + "h1:T4XsCHDT839VehWKdxbVsLn0ECjcQaUTzbSGW055pgM=", + "zh:0d8ae6d6e87f44ed4a178be03d6466339b0bb578ab54c2677e365a8281b0bb7d", + "zh:29d250d1a18d49652b28f234ecd17687b36c875dc47877a678e587d5d136b054", + "zh:2e69ba373cf009e8a60b36d04f3dbc4638708d1bf88be9f96b3e52cbf8f47f31", + "zh:53d525dd84ac63b5f749bfbc6b70a202dacf29597664d2ab1165efea6f24f630", + "zh:a25024d574ccd5ae6c2962f3bb71d510f62899f493b1ed096f2f7f0e2b18f975", + "zh:aabc64fe64319b95aaba1d1866f87abc7b10adae37d2eafa2f85f37317fdd49f", + "zh:acc6a977814897cb23d3b3753213281334238f8bce6d2b21e9f04fc4087ee980", + "zh:b24987e9416c39cd59c0fa41c139a97406b9955f0607fcafbf3315014456338a", + "zh:c550eae45fd32acdbe32b4e5c450ae95df6cb18903ac7216b1b07b23a16ce045", + "zh:c8f83b763b643893dcb6933a6bcee824cb514e06e7e5c5f5ac4ba187e66d7e22", + "zh:dcdac07e7ea18464dea729717870c275de9453775243c231e1fb305cad0ee597", + "zh:f569b65999264a9416862bca5cd2a6177d94ccb0424f3a4ef424428912b9cb3c", ] } provider "registry.terraform.io/hashicorp/random" { - version = "3.1.0" + version = "3.2.0" hashes = [ - "h1:BZMEPucF+pbu9gsPk0G0BHx7YP04+tKdq2MrRDF1EDM=", - "zh:2bbb3339f0643b5daa07480ef4397bd23a79963cc364cdfbb4e86354cb7725bc", - "zh:3cd456047805bf639fbf2c761b1848880ea703a054f76db51852008b11008626", - "zh:4f251b0eda5bb5e3dc26ea4400dba200018213654b69b4a5f96abee815b4f5ff", - "zh:7011332745ea061e517fe1319bd6c75054a314155cb2c1199a5b01fe1889a7e2", - "zh:738ed82858317ccc246691c8b85995bc125ac3b4143043219bd0437adc56c992", - "zh:7dbe52fac7bb21227acd7529b487511c91f4107db9cc4414f50d04ffc3cab427", - "zh:a3a9251fb15f93e4cfc1789800fc2d7414bbc18944ad4c5c98f466e6477c42bc", - "zh:a543ec1a3a8c20635cf374110bd2f87c07374cf2c50617eee2c669b3ceeeaa9f", - "zh:d9ab41d556a48bd7059f0810cf020500635bfc696c9fc3adab5ea8915c1d886b", - "zh:d9e13427a7d011dbd654e591b0337e6074eef8c3b9bb11b2e39eaaf257044fd7", - "zh:f7605bd1437752114baf601bdf6931debe6dc6bfe3006eb7e9bb9080931dca8a", + "h1:eeUh6cJ6wKLLuo4q9uQ0CA1Zvfqya4Wn1LecLCN8KKs=", + "zh:2960977ce9a7d6a7d3e934e75ec5814735626f95c186ad95a9102344a1a38ac1", + "zh:2fd012abfabe7076f3f2f402eeef4970e20574d20ffec57c162b02b6e848c32f", + "zh:4cd3234671cf01c913023418b227eb78b0659f2cd2e0b387be1f0bb607d29889", + "zh:52e695b4fa3fae735ffc901edff8183745f980923510a744db7616e8f10dc499", + "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", + "zh:848b4a294e5ba15192ee4bfd199c07f60a437d7572efcd2d89db036e1ebc0e6e", + "zh:9d49aa432a05748a9527e95448cebee1238c87c97c7e8dec694bfd709683f9c7", + "zh:b4ad4cf289d3f7408649b74b8639918833613f2a1f3cf51b51f4b2fdaa412dd2", + "zh:c1544c4b416096fb8d8dbf84c4488584a2844a30dd533b957e9e9e60a165f24e", + "zh:dc737d6b4591cad8c9a1d0b347e587e846d8d901789b29b4dd401b6cdf82c017", + "zh:f5645fd39f749dbbf847cbdc87ba0dbd141143f12917a6a8904faf8a9b64111e", + "zh:fdedf610e0d020878a8f1fedda8105e0c33a7e23c4792fca54460685552de308", ] } diff --git a/templates/workspace_services/guacamole/user_resources/guacamole-azure-windowsvm/terraform/main.tf b/templates/workspace_services/guacamole/user_resources/guacamole-azure-windowsvm/terraform/main.tf index abd02809e1..9fb33dbc1a 100644 --- a/templates/workspace_services/guacamole/user_resources/guacamole-azure-windowsvm/terraform/main.tf +++ b/templates/workspace_services/guacamole/user_resources/guacamole-azure-windowsvm/terraform/main.tf @@ -3,16 +3,28 @@ terraform { required_providers { azurerm = { source = "hashicorp/azurerm" - version = "=2.97.0" + version = "=3.5.0" } } backend "azurerm" { } } - provider "azurerm" { - features {} + features { + key_vault { + # Don't purge on destroy (this would fail due to purge protection being enabled on keyvault) + purge_soft_delete_on_destroy = false + purge_soft_deleted_secrets_on_destroy = false + purge_soft_deleted_certificates_on_destroy = false + purge_soft_deleted_keys_on_destroy = false + # When recreating an environment, recover any previously soft deleted secrets - set to true by default + recover_soft_deleted_key_vaults = true + recover_soft_deleted_secrets = true + recover_soft_deleted_certificates = true + recover_soft_deleted_keys = true + } + } } data "azurerm_client_config" "current" {} diff --git a/templates/workspace_services/guacamole/user_resources/guacamole-dev-vm/Dockerfile.tmpl b/templates/workspace_services/guacamole/user_resources/guacamole-dev-vm/Dockerfile.tmpl deleted file mode 100644 index eea9a7f790..0000000000 --- a/templates/workspace_services/guacamole/user_resources/guacamole-dev-vm/Dockerfile.tmpl +++ /dev/null @@ -1,30 +0,0 @@ -FROM debian:buster - -# Install Azure CLI -RUN apt-get update \ - && apt-get install -y ca-certificates jq curl apt-transport-https lsb-release gnupg \ - && curl -sL https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor | tee /etc/apt/trusted.gpg.d/microsoft.gpg > /dev/null \ - && AZ_REPO=$(lsb_release -cs) \ - && echo "deb [arch=amd64] https://packages.microsoft.com/repos/azure-cli/ $AZ_REPO main" | tee /etc/apt/sources.list.d/azure-cli.list \ - && apt-get update && apt-get -y install azure-cli - -RUN az config set extension.use_dynamic_install=yes_without_prompt - -ARG BUNDLE_DIR - -# This is a template Dockerfile for the bundle's invocation image -# You can customize it to use different base images, install tools and copy configuration files. -# -# Porter will use it as a template and append lines to it for the mixins -# and to set the CMD appropriately for the CNAB specification. -# -# Add the following line to porter.yaml to instruct Porter to use this template -# dockerfile: Dockerfile.tmpl - -# You can control where the mixin's Dockerfile lines are inserted into this file by moving "# PORTER_MIXINS" line -# another location in this file. If you remove that line, the mixins generated content is appended to this file. -# PORTER_MIXINS - -# Use the BUNDLE_DIR build argument to copy files into the bundle - -COPY . $BUNDLE_DIR diff --git a/templates/workspace_services/guacamole/user_resources/guacamole-dev-vm/porter.yaml b/templates/workspace_services/guacamole/user_resources/guacamole-dev-vm/porter.yaml index 116073f4df..27becd079c 100644 --- a/templates/workspace_services/guacamole/user_resources/guacamole-dev-vm/porter.yaml +++ b/templates/workspace_services/guacamole/user_resources/guacamole-dev-vm/porter.yaml @@ -1,9 +1,8 @@ --- name: tre-service-dev-vm -version: 0.3.2 +version: 0.3.3 description: "An Azure TRE User Resource Template for a Dev VM" registry: azuretre -dockerfile: Dockerfile.tmpl credentials: - name: azure_tenant_id @@ -43,6 +42,7 @@ parameters: description: "The name of the Terraform state storage container" - name: arm_use_msi env: ARM_USE_MSI + type: boolean default: false - name: os_image type: string @@ -59,7 +59,9 @@ parameters: - name: nexus_version type: string default: "V1" - description: "Which Nexus proxy service to use, i.e. V1 for the App Service-based Nexus or V2 for the VM-based service" + description: >- + "Which Nexus proxy service to use, i.e. V1 for the App Service-based + Nexus or V2 for the VM-based service" outputs: - name: ip @@ -104,10 +106,8 @@ install: shared_storage_name: "{{ bundle.parameters.shared_storage_name }}" nexus_version: "{{ bundle.parameters.nexus_version }}" backendConfig: - resource_group_name: - "{{ bundle.parameters.tfstate_resource_group_name }}" - storage_account_name: - "{{ bundle.parameters.tfstate_storage_account_name }}" + resource_group_name: "{{ bundle.parameters.tfstate_resource_group_name }}" + storage_account_name: "{{ bundle.parameters.tfstate_storage_account_name }}" container_name: "{{ bundle.parameters.tfstate_container_name }}" key: "{{ bundle.parameters.id }}" outputs: @@ -133,10 +133,8 @@ upgrade: shared_storage_name: "{{ bundle.parameters.shared_storage_name }}" nexus_version: "{{ bundle.parameters.nexus_version }}" backendConfig: - resource_group_name: - "{{ bundle.parameters.tfstate_resource_group_name }}" - storage_account_name: - "{{ bundle.parameters.tfstate_storage_account_name }}" + resource_group_name: "{{ bundle.parameters.tfstate_resource_group_name }}" + storage_account_name: "{{ bundle.parameters.tfstate_storage_account_name }}" container_name: "{{ bundle.parameters.tfstate_container_name }}" key: "{{ bundle.parameters.id }}" outputs: @@ -162,10 +160,8 @@ uninstall: shared_storage_name: "{{ bundle.parameters.shared_storage_name }}" nexus_version: "{{ bundle.parameters.nexus_version }}" backendConfig: - resource_group_name: - "{{ bundle.parameters.tfstate_resource_group_name }}" - storage_account_name: - "{{ bundle.parameters.tfstate_storage_account_name }}" + resource_group_name: "{{ bundle.parameters.tfstate_resource_group_name }}" + storage_account_name: "{{ bundle.parameters.tfstate_storage_account_name }}" container_name: "{{ bundle.parameters.tfstate_container_name }}" key: "{{ bundle.parameters.id }}" @@ -175,25 +171,21 @@ start: - "output" description: "Get resource ID from Terraform outputs" backendConfig: - resource_group_name: - "{{ bundle.parameters.tfstate_resource_group_name }}" - storage_account_name: - "{{ bundle.parameters.tfstate_storage_account_name }}" + resource_group_name: "{{ bundle.parameters.tfstate_resource_group_name }}" + storage_account_name: "{{ bundle.parameters.tfstate_storage_account_name }}" container_name: "{{ bundle.parameters.tfstate_container_name }}" key: "{{ bundle.parameters.id }}" outputs: - name: azure_resource_id - az: - description: - "Login to Azure" + description: "Login to Azure" arguments: - login flags: identity: username: "{{ bundle.credentials.azure_client_id }}" - az: - description: - "Start the VM" + description: "Start the VM" arguments: - vm - start @@ -206,25 +198,21 @@ stop: - "output" description: "Get VM hostname and rg from Terraform outputs" backendConfig: - resource_group_name: - "{{ bundle.parameters.tfstate_resource_group_name }}" - storage_account_name: - "{{ bundle.parameters.tfstate_storage_account_name }}" + resource_group_name: "{{ bundle.parameters.tfstate_resource_group_name }}" + storage_account_name: "{{ bundle.parameters.tfstate_storage_account_name }}" container_name: "{{ bundle.parameters.tfstate_container_name }}" key: "{{ bundle.parameters.id }}" outputs: - name: azure_resource_id - az: - description: - "Login to Azure" + description: "Login to Azure" arguments: - login flags: identity: username: "{{ bundle.credentials.azure_client_id }}" - az: - description: - "Stop the VM" + description: "Stop the VM" arguments: - vm - stop diff --git a/templates/workspace_services/guacamole/user_resources/guacamole-dev-vm/terraform/.terraform.lock.hcl b/templates/workspace_services/guacamole/user_resources/guacamole-dev-vm/terraform/.terraform.lock.hcl index 61c54c45c8..3748610cfc 100644 --- a/templates/workspace_services/guacamole/user_resources/guacamole-dev-vm/terraform/.terraform.lock.hcl +++ b/templates/workspace_services/guacamole/user_resources/guacamole-dev-vm/terraform/.terraform.lock.hcl @@ -2,39 +2,41 @@ # Manual edits may be lost in future updates. provider "registry.terraform.io/hashicorp/azurerm" { - version = "2.97.0" - constraints = "2.97.0" + version = "3.5.0" + constraints = "3.5.0" hashes = [ - "h1:XxT+XM/leTXa21aTnJjPBfNBQ8cLE4gYDg01WEZsV1U=", - "zh:0aac80e6d2b8ddf33d558ac893d52688e8abf8a0b995cfc3c35eb84afbf432a3", - "zh:11191068cb732208ebc8662651782f63db329a25f7ea1cd50cd91622a2c247b7", - "zh:36c8334194e7d605682053c7c70fbb2a650d9b0a7bcc44d5cdda4f205818438a", - "zh:3a5e01276added995e875b42ecc6b36ff73d267f0c096c87195bd2b1fff4f5b2", - "zh:557e38371657e6ed8aae9192d01480c4cca7c0f7ade6022f1aec247a6384922b", - "zh:67b913c280c5858549477a4b05e77078b1a5234de77c7bddd4ee1e8e237d5665", - "zh:7aeca864ce45b295db734cd968f7596ff12cd7c522ee89d53f432dae7c2b5d18", - "zh:b6127d7a796eaf9756dd212667eb48f79c0e78729589ec8ccf68e0b36ebb4e54", - "zh:bed448238740f897d1b399e5123b3a9eba256b981846f9ee92b71493446ca684", - "zh:c351a1bba34c3bd06fff75e4c15e4db0456268479463c2471598068ea1c5c884", - "zh:d073c24d0a4756e79b39f41f552d526800f9fb0ad0a74f742ac8de61b6416a3a", + "h1:T4XsCHDT839VehWKdxbVsLn0ECjcQaUTzbSGW055pgM=", + "zh:0d8ae6d6e87f44ed4a178be03d6466339b0bb578ab54c2677e365a8281b0bb7d", + "zh:29d250d1a18d49652b28f234ecd17687b36c875dc47877a678e587d5d136b054", + "zh:2e69ba373cf009e8a60b36d04f3dbc4638708d1bf88be9f96b3e52cbf8f47f31", + "zh:53d525dd84ac63b5f749bfbc6b70a202dacf29597664d2ab1165efea6f24f630", + "zh:a25024d574ccd5ae6c2962f3bb71d510f62899f493b1ed096f2f7f0e2b18f975", + "zh:aabc64fe64319b95aaba1d1866f87abc7b10adae37d2eafa2f85f37317fdd49f", + "zh:acc6a977814897cb23d3b3753213281334238f8bce6d2b21e9f04fc4087ee980", + "zh:b24987e9416c39cd59c0fa41c139a97406b9955f0607fcafbf3315014456338a", + "zh:c550eae45fd32acdbe32b4e5c450ae95df6cb18903ac7216b1b07b23a16ce045", + "zh:c8f83b763b643893dcb6933a6bcee824cb514e06e7e5c5f5ac4ba187e66d7e22", + "zh:dcdac07e7ea18464dea729717870c275de9453775243c231e1fb305cad0ee597", + "zh:f569b65999264a9416862bca5cd2a6177d94ccb0424f3a4ef424428912b9cb3c", ] } provider "registry.terraform.io/hashicorp/random" { - version = "3.1.0" + version = "3.2.0" hashes = [ - "h1:BZMEPucF+pbu9gsPk0G0BHx7YP04+tKdq2MrRDF1EDM=", - "zh:2bbb3339f0643b5daa07480ef4397bd23a79963cc364cdfbb4e86354cb7725bc", - "zh:3cd456047805bf639fbf2c761b1848880ea703a054f76db51852008b11008626", - "zh:4f251b0eda5bb5e3dc26ea4400dba200018213654b69b4a5f96abee815b4f5ff", - "zh:7011332745ea061e517fe1319bd6c75054a314155cb2c1199a5b01fe1889a7e2", - "zh:738ed82858317ccc246691c8b85995bc125ac3b4143043219bd0437adc56c992", - "zh:7dbe52fac7bb21227acd7529b487511c91f4107db9cc4414f50d04ffc3cab427", - "zh:a3a9251fb15f93e4cfc1789800fc2d7414bbc18944ad4c5c98f466e6477c42bc", - "zh:a543ec1a3a8c20635cf374110bd2f87c07374cf2c50617eee2c669b3ceeeaa9f", - "zh:d9ab41d556a48bd7059f0810cf020500635bfc696c9fc3adab5ea8915c1d886b", - "zh:d9e13427a7d011dbd654e591b0337e6074eef8c3b9bb11b2e39eaaf257044fd7", - "zh:f7605bd1437752114baf601bdf6931debe6dc6bfe3006eb7e9bb9080931dca8a", + "h1:eeUh6cJ6wKLLuo4q9uQ0CA1Zvfqya4Wn1LecLCN8KKs=", + "zh:2960977ce9a7d6a7d3e934e75ec5814735626f95c186ad95a9102344a1a38ac1", + "zh:2fd012abfabe7076f3f2f402eeef4970e20574d20ffec57c162b02b6e848c32f", + "zh:4cd3234671cf01c913023418b227eb78b0659f2cd2e0b387be1f0bb607d29889", + "zh:52e695b4fa3fae735ffc901edff8183745f980923510a744db7616e8f10dc499", + "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", + "zh:848b4a294e5ba15192ee4bfd199c07f60a437d7572efcd2d89db036e1ebc0e6e", + "zh:9d49aa432a05748a9527e95448cebee1238c87c97c7e8dec694bfd709683f9c7", + "zh:b4ad4cf289d3f7408649b74b8639918833613f2a1f3cf51b51f4b2fdaa412dd2", + "zh:c1544c4b416096fb8d8dbf84c4488584a2844a30dd533b957e9e9e60a165f24e", + "zh:dc737d6b4591cad8c9a1d0b347e587e846d8d901789b29b4dd401b6cdf82c017", + "zh:f5645fd39f749dbbf847cbdc87ba0dbd141143f12917a6a8904faf8a9b64111e", + "zh:fdedf610e0d020878a8f1fedda8105e0c33a7e23c4792fca54460685552de308", ] } diff --git a/templates/workspace_services/guacamole/user_resources/guacamole-dev-vm/terraform/main.tf b/templates/workspace_services/guacamole/user_resources/guacamole-dev-vm/terraform/main.tf index 01b0ce69bb..c0d76a1f20 100644 --- a/templates/workspace_services/guacamole/user_resources/guacamole-dev-vm/terraform/main.tf +++ b/templates/workspace_services/guacamole/user_resources/guacamole-dev-vm/terraform/main.tf @@ -3,7 +3,7 @@ terraform { required_providers { azurerm = { source = "hashicorp/azurerm" - version = "=2.97.0" + version = "=3.5.0" } } backend "azurerm" { diff --git a/templates/workspace_services/guacamole/version.txt b/templates/workspace_services/guacamole/version.txt index 493f7415d7..f9aa3e1109 100644 --- a/templates/workspace_services/guacamole/version.txt +++ b/templates/workspace_services/guacamole/version.txt @@ -1 +1 @@ -__version__ = "0.3.0" +__version__ = "0.3.2" diff --git a/templates/workspace_services/innereye/Dockerfile.tmpl b/templates/workspace_services/innereye/Dockerfile.tmpl index 1040ceb1c1..094631eed0 100644 --- a/templates/workspace_services/innereye/Dockerfile.tmpl +++ b/templates/workspace_services/innereye/Dockerfile.tmpl @@ -1,18 +1,23 @@ -FROM debian:buster +FROM debian:stretch-slim + +SHELL ["/bin/bash", "-o", "pipefail", "-c"] # Install Azure CLI +# It's useless to specify azcli version since the mixin installs the latest anyway +# hadolint ignore=DL3008 RUN apt-get update \ - && apt-get install -y ca-certificates jq curl apt-transport-https lsb-release gnupg \ + && apt-get install -y ca-certificates="20200601~deb9u2" jq="1.5+dfsg-1.3" curl="7.52.1-5+deb9u16" apt-transport-https="1.4.11" lsb-release="9.20161125" gnupg="2.1.18-8~deb9u4" \ && curl -sL https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor | tee /etc/apt/trusted.gpg.d/microsoft.gpg > /dev/null \ && AZ_REPO=$(lsb_release -cs) \ && echo "deb [arch=amd64] https://packages.microsoft.com/repos/azure-cli/ $AZ_REPO main" | tee /etc/apt/sources.list.d/azure-cli.list \ - && apt-get update && apt-get -y install azure-cli + && apt-get update && apt-get -y install azure-cli \ + && apt-get clean -y && rm -rf /var/lib/apt/lists/* RUN az extension add --name azure-firewall -RUN export PORTER_HOME=/home/$USER/.porter \ +RUN export PORTER_HOME=/home/"${USER}"/.porter \ && curl -L https://cdn.porter.sh/latest/install-linux.sh | bash \ - && ${PORTER_HOME}/porter mixin install docker + && "${PORTER_HOME}"/porter mixin install docker ENV PATH /home/$USER/.porter/:$PATH diff --git a/templates/workspace_services/innereye/porter.yaml b/templates/workspace_services/innereye/porter.yaml index e03ede698d..80df96c821 100644 --- a/templates/workspace_services/innereye/porter.yaml +++ b/templates/workspace_services/innereye/porter.yaml @@ -1,6 +1,6 @@ --- name: tre-service-innereye -version: 0.3.0 +version: 0.3.1 description: "An Azure TRE service for InnerEye Deep Learning" registry: azuretre dockerfile: Dockerfile.tmpl @@ -44,6 +44,7 @@ parameters: env: TERRAFORM_STATE_CONTAINER_NAME - name: arm_use_msi env: ARM_USE_MSI + type: boolean default: false mixins: diff --git a/templates/workspace_services/mlflow/Dockerfile.tmpl b/templates/workspace_services/mlflow/Dockerfile.tmpl deleted file mode 100644 index 6ac76276f4..0000000000 --- a/templates/workspace_services/mlflow/Dockerfile.tmpl +++ /dev/null @@ -1,20 +0,0 @@ -FROM debian:buster - -ARG BUNDLE_DIR - -# This is a template Dockerfile for the bundle's invocation image -# You can customize it to use different base images, install tools and copy configuration files. -# -# Porter will use it as a template and append lines to it for the mixins -# and to set the CMD appropriately for the CNAB specification. -# -# Add the following line to porter.yaml to instruct Porter to use this template -# dockerfile: Dockerfile.tmpl - -# You can control where the mixin's Dockerfile lines are inserted into this file by moving "# PORTER_MIXINS" line -# another location in this file. If you remove that line, the mixins generated content is appended to this file. -# PORTER_MIXINS - -# Use the BUNDLE_DIR build argument to copy files into the bundle - -COPY . $BUNDLE_DIR diff --git a/templates/workspace_services/mlflow/porter.yaml b/templates/workspace_services/mlflow/porter.yaml index ae71ec1666..6f76b67043 100644 --- a/templates/workspace_services/mlflow/porter.yaml +++ b/templates/workspace_services/mlflow/porter.yaml @@ -1,9 +1,8 @@ --- name: tre-service-mlflow -version: 0.3.1 +version: 0.3.2 description: "An Azure TRE service for MLflow machine learning lifecycle" registry: azuretre -dockerfile: Dockerfile.tmpl credentials: - name: azure_tenant_id diff --git a/templates/workspaces/base/.env.sample b/templates/workspaces/base/.env.sample index cea6cbf038..575f7f2b3a 100644 --- a/templates/workspaces/base/.env.sample +++ b/templates/workspaces/base/.env.sample @@ -6,14 +6,20 @@ ARM_SUBSCRIPTION_ID="__CHANGE_ME__" AUTH_TENANT_ID="__CHANGE_ME__" # These are passed in if Terraform will create the Workspace AAD Application +#REGISTER_AAD_APPLICATION=true AUTH_CLIENT_ID="__CHANGE_ME__" AUTH_CLIENT_SECRET="__CHANGE_ME__" +WORKSPACE_OWNER_OBJECT_ID="__CHANGE_ME__" # These are passed in if you register the Workspace AAD Application before hand +REGISTER_AAD_APPLICATION=false CLIENT_ID="__CHANGE_ME__ CLIENT_SECRET="__CHANGE_ME__ +ID="MadeUp123" # Used by Porter +SP_ID="" +APP_ROLE_ID_WORKSPACE_OWNER="" +APP_ROLE_ID_WORKSPACE_RESEARCHER="" ADDRESS_SPACE="10.2.8.0/24" SHARED_STORAGE_QUOTA=50 ENABLE_LOCAL_DEBUGGING=true -REGISTER_AAD_APPLICATION=false diff --git a/templates/workspaces/base/parameters.json b/templates/workspaces/base/parameters.json index 6a03b6620f..e55d43950f 100755 --- a/templates/workspaces/base/parameters.json +++ b/templates/workspaces/base/parameters.json @@ -70,6 +70,24 @@ "env": "CLIENT_ID" } }, + { + "name": "client_secret", + "source": { + "env": "CLIENT_SECRET" + } + }, + { + "name": "scope_id", + "source": { + "env": "SCOPE_ID" + } + }, + { + "name": "workspace_owner_object_id", + "source": { + "env": "WORKSPACE_OWNER_OBJECT_ID" + } + }, { "name": "sp_id", "source": { diff --git a/templates/workspaces/base/porter.yaml b/templates/workspaces/base/porter.yaml index b5c077e387..30b7f4abcd 100644 --- a/templates/workspaces/base/porter.yaml +++ b/templates/workspaces/base/porter.yaml @@ -1,6 +1,6 @@ --- name: tre-workspace-base -version: 0.3.4 +version: 0.3.5 description: "A base Azure TRE workspace" registry: azuretre @@ -58,6 +58,9 @@ parameters: type: boolean default: false description: "Whether this bundle should register the workspace in AAD" + - name: workspace_owner_object_id + type: string + description: "The object id of the user that will be granted WorkspaceOwner after it is created." - name: client_id type: string description: "The client id of the workspace in the identity provider. This value is typically provided to you @@ -132,6 +135,7 @@ install: auth_client_id: "{{ bundle.credentials.auth_client_id }}" auth_client_secret: "{{ bundle.credentials.auth_client_secret }}" auth_tenant_id: "{{ bundle.credentials.auth_tenant_id }}" + workspace_owner_object_id: "{{ bundle.parameters.workspace_owner_object_id }}" client_id: "{{ bundle.parameters.client_id }}" client_secret: "{{ bundle.parameters.client_secret }}" scope_id: "{{ bundle.parameters.scope_id }}" @@ -175,6 +179,7 @@ uninstall: auth_client_id: "{{ bundle.credentials.auth_client_id }}" auth_client_secret: "{{ bundle.credentials.auth_client_secret }}" auth_tenant_id: "{{ bundle.credentials.auth_tenant_id }}" + workspace_owner_object_id: "{{ bundle.parameters.workspace_owner_object_id }}" client_id: "{{ bundle.parameters.client_id }}" scope_id: "{{ bundle.parameters.scope_id }}" sp_id: "{{ bundle.parameters.sp_id }}" diff --git a/templates/workspaces/base/terraform/.terraform.lock.hcl b/templates/workspaces/base/terraform/.terraform.lock.hcl index 5c12a0f59f..ac63de398b 100644 --- a/templates/workspaces/base/terraform/.terraform.lock.hcl +++ b/templates/workspaces/base/terraform/.terraform.lock.hcl @@ -22,21 +22,21 @@ provider "registry.terraform.io/hashicorp/azuread" { } provider "registry.terraform.io/hashicorp/azurerm" { - version = "3.4.0" - constraints = "3.4.0" + version = "3.5.0" + constraints = "3.5.0" hashes = [ - "h1:h78yKGgOFrU/N5ntockxN7XF/ufv47j77+oauO2GKqk=", - "zh:4e9913fc3378436d19150c334e5906eafb83a4af3a270423cb7cdda94b27371f", - "zh:5b3d0cec2a600dc1f6633baa8fc36368c5c330fd7654861edcfa76f760a8f6a9", - "zh:5e0e1f899027bc182f31d996c9611e5ba27a034c848d7b0519b39e559fc4f38d", - "zh:66e3a1383ed6a0370989f6fd6abcfa63ccf6918ae535108595af57b9c20a9257", - "zh:688493baf6a116a399b737d74c11080051aca1ab087e5cddd14cc683b7e45c76", - "zh:9e471d85d52343e3ba778f3a94626d820fbec97bb589a3ac7a6a0939b9387770", - "zh:be1e85635daca1768f26962a4cbbadbf7fd13d9da8f9f188e938beca542c2ad5", - "zh:c00e14b6aa566eb9995cb0e1611a18fb8650d9f35c7636a7643a1b6e22660226", - "zh:c40711e5021838fd879da4c9e6b8f7e72104ada2adf0f3ba22e1cc32c3c54086", - "zh:cc62f8541de8d79577e57664e4f03c1fca893d455e5fb238d20668389c0f09ee", - "zh:cd9cbb5c6e5ceb5fcc7c4d0cab516ff209667d1b539b8c7436bd5e452c6aba8f", + "h1:T4XsCHDT839VehWKdxbVsLn0ECjcQaUTzbSGW055pgM=", + "zh:0d8ae6d6e87f44ed4a178be03d6466339b0bb578ab54c2677e365a8281b0bb7d", + "zh:29d250d1a18d49652b28f234ecd17687b36c875dc47877a678e587d5d136b054", + "zh:2e69ba373cf009e8a60b36d04f3dbc4638708d1bf88be9f96b3e52cbf8f47f31", + "zh:53d525dd84ac63b5f749bfbc6b70a202dacf29597664d2ab1165efea6f24f630", + "zh:a25024d574ccd5ae6c2962f3bb71d510f62899f493b1ed096f2f7f0e2b18f975", + "zh:aabc64fe64319b95aaba1d1866f87abc7b10adae37d2eafa2f85f37317fdd49f", + "zh:acc6a977814897cb23d3b3753213281334238f8bce6d2b21e9f04fc4087ee980", + "zh:b24987e9416c39cd59c0fa41c139a97406b9955f0607fcafbf3315014456338a", + "zh:c550eae45fd32acdbe32b4e5c450ae95df6cb18903ac7216b1b07b23a16ce045", + "zh:c8f83b763b643893dcb6933a6bcee824cb514e06e7e5c5f5ac4ba187e66d7e22", + "zh:dcdac07e7ea18464dea729717870c275de9453775243c231e1fb305cad0ee597", "zh:f569b65999264a9416862bca5cd2a6177d94ccb0424f3a4ef424428912b9cb3c", ] } diff --git a/templates/workspaces/base/terraform/aad/aad.tf b/templates/workspaces/base/terraform/aad/aad.tf index 8f985748fa..3ac54e10fb 100644 --- a/templates/workspaces/base/terraform/aad/aad.tf +++ b/templates/workspaces/base/terraform/aad/aad.tf @@ -102,3 +102,9 @@ resource "azurerm_key_vault_secret" "client_secret" { value = azuread_service_principal_password.workspace.value key_vault_id = var.key_vault_id } + +resource "azuread_app_role_assignment" "workspace_owner" { + app_role_id = azuread_service_principal.workspace.app_role_ids["WorkspaceOwner"] + principal_object_id = var.workspace_owner_object_id + resource_object_id = azuread_service_principal.workspace.object_id +} diff --git a/templates/workspaces/base/terraform/aad/variables.tf b/templates/workspaces/base/terraform/aad/variables.tf index 220dc4c7e6..4f4b8ce6ad 100644 --- a/templates/workspaces/base/terraform/aad/variables.tf +++ b/templates/workspaces/base/terraform/aad/variables.tf @@ -1,2 +1,3 @@ variable "key_vault_id" {} -variable "workspace_resource_name_suffix" {} \ No newline at end of file +variable "workspace_resource_name_suffix" {} +variable "workspace_owner_object_id" {} diff --git a/templates/workspaces/base/terraform/providers.tf b/templates/workspaces/base/terraform/providers.tf index c5ddaeb448..6fbcc43ebb 100644 --- a/templates/workspaces/base/terraform/providers.tf +++ b/templates/workspaces/base/terraform/providers.tf @@ -2,7 +2,7 @@ terraform { required_providers { azurerm = { source = "hashicorp/azurerm" - version = "=3.4.0" + version = "=3.5.0" } azuread = { source = "hashicorp/azuread" diff --git a/templates/workspaces/base/terraform/workspace.tf b/templates/workspaces/base/terraform/workspace.tf index 76885bf653..f7b16732d6 100644 --- a/templates/workspaces/base/terraform/workspace.tf +++ b/templates/workspaces/base/terraform/workspace.tf @@ -28,10 +28,25 @@ module "aad" { count = var.register_aad_application ? 1 : 0 key_vault_id = azurerm_key_vault.kv.id workspace_resource_name_suffix = local.workspace_resource_name_suffix + workspace_owner_object_id = var.workspace_owner_object_id depends_on = [ azurerm_key_vault_access_policy.deployer, azurerm_key_vault_access_policy.resource_processor, - azurerm_private_endpoint.kvpe + null_resource.wait_for_dns_vault + ] +} + +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, ] } diff --git a/templates/workspaces/innereye/porter.yaml b/templates/workspaces/innereye/porter.yaml index c3bb249f64..c869320d11 100644 --- a/templates/workspaces/innereye/porter.yaml +++ b/templates/workspaces/innereye/porter.yaml @@ -53,6 +53,7 @@ parameters: env: TERRAFORM_STATE_CONTAINER_NAME - name: arm_use_msi env: ARM_USE_MSI + type: boolean default: false mixins: diff --git a/ui/README.md b/ui/README.md index aa02edf81d..3d6fef4a84 100644 --- a/ui/README.md +++ b/ui/README.md @@ -1,16 +1,20 @@ # TRE UI -This is very much a work in progress. +Please see the docs for a full overview and deployment instructions. -To run: -- Open this folder (`ui`) in the devcontainer -- Couple of manual steps (for now): - - We currently use the Swagger AAD app as it's set up for web logins. Find that app, and add `http://localhost:3000` as a reply URI. - - Find the API wep app in the core TRE resource group, and add `http://localhost:3000` as a CORS reply URI. - - Change the values in `./app/src/config.json`: - - `rootClientId` / `rootTenantId` => swagger App - - `treApiClientId` => API client ID - - `debug` => true or false to show debug info in the UI -- `cd ./app` -- `yarn start` +The UI was built using Create React App and Microsoft Fluent UI. Further details on this in the ./app/README. +## Run the UI +- Ensure `DEPLOY_UI=true` is set in your `./templates/core/.env` file +- In the root of the repo, run `make tre-deploy`. This will provision the necessary resources in Azure, build and deploy the UI to Azure blob storage, behind the App Gateway used for the API. The deployment process will also create the necessary `config.json`, using the `config.source.json` as a template. +- In Azure AD, locate the TRE Client Apps app (possibly called Swagger App). In the Authentication section add reply URIs for: + - `http://localhost:3000` (if wanting to run locally) + - Your deployed App Url - `https://{TRE_ID}.{LOCATION}.cloudapp.azure.com`. + +At this point you should be able to navigate to the web app in Azure, log in, and see your workspaces. + +### To run locally +- `cd ./ui/app` +- `yarn start` + +After making changes to the code, redeploy to Azure by running `make build-and-deploy-ui` in the root of the dev container. diff --git a/ui/app/.gitignore b/ui/app/.gitignore index 5ef0b10adf..1dcfb14871 100644 --- a/ui/app/.gitignore +++ b/ui/app/.gitignore @@ -23,6 +23,6 @@ yarn-debug.log* yarn-error.log* .eslintcache -config.json +src/config.json !public/index.html diff --git a/ui/app/public/index.html b/ui/app/public/index.html index ca57ec7227..7df16453cd 100644 --- a/ui/app/public/index.html +++ b/ui/app/public/index.html @@ -19,6 +19,7 @@ work correctly both with client-side routing and a non-root public URL. Learn how to configure a non-root public URL by running `npm run build`. --> + Azure TRE diff --git a/ui/app/public/ms_icon.png b/ui/app/public/ms_icon.png new file mode 100644 index 0000000000..0651bd2b77 Binary files /dev/null and b/ui/app/public/ms_icon.png differ diff --git a/ui/app/src/App.scss b/ui/app/src/App.scss index 9dcd926e4b..f2b5db510d 100644 --- a/ui/app/src/App.scss +++ b/ui/app/src/App.scss @@ -78,6 +78,7 @@ ul.tre-notifications-steps-list li { .tre-home-link { color: #fff; text-decoration: none; + font-size:1.2rem; } .tre-user-menu .ms-Persona-primaryText:hover { diff --git a/ui/app/src/components/root/RootLayout.tsx b/ui/app/src/components/root/RootLayout.tsx index 384d33d14f..b7ff6e03a9 100644 --- a/ui/app/src/components/root/RootLayout.tsx +++ b/ui/app/src/components/root/RootLayout.tsx @@ -57,7 +57,7 @@ export const RootLayout: React.FunctionComponent = () => { case LoadingState.Ok: return ( - + diff --git a/ui/app/src/components/shared/TopNav.tsx b/ui/app/src/components/shared/TopNav.tsx index b622faeb32..3dd4a1df3e 100644 --- a/ui/app/src/components/shared/TopNav.tsx +++ b/ui/app/src/components/shared/TopNav.tsx @@ -4,14 +4,13 @@ import { Link } from 'react-router-dom'; import { UserMenu } from './UserMenu'; import { NotificationPanel } from './notifications/NotificationPanel'; - export const TopNav: React.FunctionComponent = () => { return ( <>
- Azure TRE + Azure Trusted Research Environment @@ -31,6 +30,6 @@ const contentClass = mergeStyles([ backgroundColor: theme.palette.themeDark, color: theme.palette.white, lineHeight: '50px', - padding: '0 20px' + padding: '0 10px 0 10px' } -]); \ No newline at end of file +]); diff --git a/ui/app/src/config.json b/ui/app/src/config.json deleted file mode 100644 index a8ce0272ce..0000000000 --- a/ui/app/src/config.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "rootClientId": "78b5368f-4543-48fa-a1b4-0795d7a11a21", - "rootTenantId": "64bdc039-7c7f-4290-949e-d4ae71101008", - "treApiClientId": "88da88b4-32eb-4743-b828-b1b83edf481a", - "treUrl": "https://ocwtre32.northeurope.cloudapp.azure.com/api", - "pollingDelayMilliseconds": 10000, - "loadAllOpsOnStart": true, - "debug": true -} \ No newline at end of file diff --git a/ui/app/src/config.sample.json b/ui/app/src/config.source.json similarity index 100% rename from ui/app/src/config.sample.json rename to ui/app/src/config.source.json