зеркало из https://github.com/microsoft/AzureTRE.git
Add OHDSI workspace service (#3562)
* add ohdsi workspace service (before adjustments to the OSS) * add execute permission to scripts * Fix Postgres timeouts when install OHDSI (#3559) [ohdsi] fix postgres timeouts * Add OHDSI workspace service (#3552) * remove todos * link core vnet to postgres private dns zone when deploying core * remove synapse references, and add other data sources to the options * remove postgres_core_dns_link references * revert synapse reference deletions * remove non supported dialects * add execute permission to scripts * make some of the daimons required * add required zone field to postgres: https://github.com/hashicorp/terraform-provider-azurerm/issues/16888 * add fw rule to allow open id authentication in atlas * fix firewall step * add README * update README * fix linting errors * fix linting errors * update changelog * Update CHANGELOG.md Co-authored-by: Tamir Kamara <26870601+tamirkamara@users.noreply.github.com> * add ohdsi ws service to the CI * clarified README * added name, description and overview to the template_schema * move README content to docs * change default display name * add diagram to and instructions about setting up the CDM data source * add link to ohdsi-on-azure * move ohdsi-on-azure to the top * link to OHDSIonAzure for deploying synapse * Update docs/tre-templates/workspace-services/ohdsi.md Co-authored-by: Marcus Robinson <marrobi@microsoft.com> * add Using a sample CDM data source section --------- Co-authored-by: Tamir Kamara <26870601+tamirkamara@users.noreply.github.com> Co-authored-by: Marcus Robinson <marrobi@microsoft.com>
This commit is contained in:
Родитель
0ed36d0280
Коммит
8c82fd75ee
|
@ -392,6 +392,8 @@ jobs:
|
|||
BUNDLE_DIR: "./templates/workspace_services/health-services"}
|
||||
- {BUNDLE_TYPE: "workspace_service",
|
||||
BUNDLE_DIR: "./templates/workspace_services/databricks"}
|
||||
- {BUNDLE_TYPE: "workspace_service",
|
||||
BUNDLE_DIR: "./templates/workspace_services/ohdsi"}
|
||||
- {BUNDLE_TYPE: "user_resource",
|
||||
BUNDLE_DIR: "./templates/workspace_services/guacamole/user_resources/guacamole-azure-windowsvm"}
|
||||
- {BUNDLE_TYPE: "user_resource",
|
||||
|
@ -549,6 +551,8 @@ jobs:
|
|||
BUNDLE_DIR: "./templates/workspace_services/health-services"}
|
||||
- {BUNDLE_TYPE: "workspace_service",
|
||||
BUNDLE_DIR: "./templates/workspace_services/databricks"}
|
||||
- {BUNDLE_TYPE: "workspace_service",
|
||||
BUNDLE_DIR: "./templates/workspace_services/ohdsi"}
|
||||
|
||||
environment: ${{ inputs.environmentName }}
|
||||
steps:
|
||||
|
|
|
@ -9,6 +9,7 @@ FEATURES:
|
|||
ENHANCEMENTS:
|
||||
* Workspace networking peering sync is handled natively by Terraform ([#3534](https://github.com/microsoft/AzureTRE/issues/3534))
|
||||
* Use SMTP built in connector vs API connector in Airlock Notifier ([#3572](https://github.com/microsoft/AzureTRE/issues/3572))
|
||||
* Added OHDSI workspace service ([#3562](https://github.com/microsoft/AzureTRE/issues/3562))
|
||||
|
||||
BUG FIXES:
|
||||
* Nexus might fail to deploy due to wrong identity used in key-vault extension ([#3492](https://github.com/microsoft/AzureTRE/issues/3492))
|
||||
|
|
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 158 KiB |
|
@ -0,0 +1,38 @@
|
|||
# OHDSI Workspace Service
|
||||
|
||||
!!! warning
|
||||
- This workspace service does not work "out of the box". It requires additional networking configuration to work properly. See the [networking configuration](#networking-configuration) section for more details.
|
||||
- Currently the only CDM data source supported by the workspace service is Azure Synapse.
|
||||
|
||||
See the [official OHDSI website](https://www.ohdsi.org/) and [The Book of OHDSI](https://ohdsi.github.io/TheBookOfOhdsi/).
|
||||
|
||||
This service installs the following resources into an existing virtual network within the workspace:
|
||||
![OHDSI ATLAS Workspace Service](images/ohdsi_service.png)
|
||||
|
||||
## Networking configuration
|
||||
Deploying the OHDSI workspace is not enough for it to function properly, in order for it to work properly, the following networking configuration should be in place:
|
||||
|
||||
### 1. The resource processor should be able to access the CDM data source
|
||||
Multiple OHDSI workspace services cannot share the same RESULTS and TEMP schemas because each OHDSI instance is changing the schemas, which could potentially cause conflicts.
|
||||
To avoid this, every workspace service must work on its own schemas. To do this, we use golden copying.
|
||||
This means that the "main" schemas remain untouched, and every workspace service has its own copy of the RESULTS and TEMP schemas, in the CDM data source, which it can modify.
|
||||
|
||||
Since the resource processor is in charge of duplicating the schemas, the CDM data source has to be accessible from the resource processor's VNet in order to be able to create them.
|
||||
|
||||
### 2. The workspace should be able to access the CDM data source
|
||||
In order to access the CDM from ATLAS, the CDM data source should be accessible from the workspace's VNet.
|
||||
Since the CDM data source is outside of TRE, this is not part of the template, however, there are many ways in which this can be done,
|
||||
one example would be to to deploy a private endpoint for the CDM data source in the workspace's VNet as part of a custom workspace template.
|
||||
|
||||
## Setting up a CDM data source
|
||||
Currently the only CDM data source supported by the workspace service is Azure Synapse.
|
||||
|
||||
If you already have an OMOP CDM data source, then all you have to do is to configure the network as described in the [networking configuration](#networking-configuration) section.
|
||||
|
||||
If you're data is in a different format, you can read [here](https://ohdsi.github.io/TheBookOfOhdsi/ExtractTransformLoad.html) how to set up the ETL process to convert your medical data to OMOP format.
|
||||
|
||||
## Using a sample CDM data source
|
||||
If you don't have any data yet, or if you just want a quick start, you can deploy an Azure Synapse CDM data source with sample data using the [OHDSI on Azure](https://github.com/microsoft/OHDSIonAzure) repository.
|
||||
When deploying set `OMOP CDM Database Type` to `Synapse Dedicated Pool` as per the [deployment guide](https://github.com/microsoft/OHDSIonAzure/blob/main/docs/DeploymentGuide.md#:~:text=OMOP%20CDM%20Database%20Type).
|
||||
|
||||
Note that you will need to provision a private endpoint into the Azure TRE workspace that connects to the SQL Dedicated Pool as described in the [networking configuration](#networking-configuration) section.
|
|
@ -101,6 +101,7 @@ nav:
|
|||
- MLFlow: tre-templates/workspace-services/mlflow.md
|
||||
- Health Services: tre-templates/workspace-services/health_services.md
|
||||
- Azure Databricks: tre-templates/workspace-services/databricks.md
|
||||
- OHDSI: tre-templates/workspace-services/ohdsi.md
|
||||
- Shared Services:
|
||||
- Gitea (Source Mirror): tre-templates/shared-services/gitea.md
|
||||
- Nexus (Package Mirror): tre-templates/shared-services/nexus.md
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
# Local .terraform directories
|
||||
**/.terraform/*
|
||||
|
||||
# TF backend files
|
||||
**/*_backend.tf
|
||||
|
||||
Dockerfile.tmpl
|
|
@ -0,0 +1,5 @@
|
|||
ID="__CHANGE_ME__"
|
||||
WORKSPACE_ID="__CHANGE_ME__"
|
||||
TRE_ID="__CHANGE_ME__"
|
||||
MGMT_RESOURCE_GROUP_NAME="__CHANGE_ME__"
|
||||
MGMT_ACR_NAME="__CHANGE_ME__"
|
|
@ -0,0 +1,29 @@
|
|||
# syntax=docker/dockerfile-upstream:1.4.0
|
||||
FROM debian:bullseye-slim
|
||||
|
||||
# PORTER_INIT
|
||||
|
||||
RUN rm -f /etc/apt/apt.conf.d/docker-clean; echo 'Binary::apt::APT::Keep-Downloaded-Packages "true";' > /etc/apt/apt.conf.d/keep-cache
|
||||
|
||||
# sqlcmd is required for schemas initialization in AzureSynapse
|
||||
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
|
||||
# ignore lint rule that requires `--no-install-recommends` to allow the microsoft packeges to get everything they need and clear it all up in the end
|
||||
# hadolint ignore=DL3015
|
||||
RUN apt-get update && apt-get install -y curl gnupg && \
|
||||
curl https://packages.microsoft.com/keys/microsoft.asc | apt-key add - && \
|
||||
echo 'deb https://packages.microsoft.com/debian/11/prod bullseye main'> /etc/apt/sources.list.d/prod.list && \
|
||||
apt-get update && apt-get -y install sqlcmd --no-install-recommends && \
|
||||
apt-get clean && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Git is required for terraform_azurerm_environment_configuration
|
||||
RUN --mount=type=cache,target=/var/cache/apt --mount=type=cache,target=/var/lib/apt \
|
||||
apt-get update && apt-get install -y git --no-install-recommends
|
||||
|
||||
# PostgreSql is required by Atlas
|
||||
RUN --mount=type=cache,target=/var/cache/apt --mount=type=cache,target=/var/lib/apt \
|
||||
apt-get update && apt-get install -y postgresql-client gettext apache2-utils curl jq --no-install-recommends
|
||||
|
||||
# PORTER_MIXINS
|
||||
|
||||
# Use the BUNDLE_DIR build argument to copy files into the bundle
|
||||
COPY --link . ${BUNDLE_DIR}/
|
|
@ -0,0 +1,7 @@
|
|||
# OHDSI Workspace Service
|
||||
|
||||
## IMPORTANT
|
||||
- This workspace service does not work "out of the box". It requires additional networking configuration to work properly.
|
||||
- Currently the only CDM data source supported by the workspace service is Azure Synapse.
|
||||
|
||||
Further details are provided in the [documentation](https://microsoft.github.io/AzureTRE/latest/tre-templates/workspace-services/ohdsi/).
|
|
@ -0,0 +1,80 @@
|
|||
{
|
||||
"schemaType": "ParameterSet",
|
||||
"schemaVersion": "1.0.1",
|
||||
"namespace": "",
|
||||
"name": "tre-workspace-service-ohdsi",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "tre_id",
|
||||
"source": {
|
||||
"env": "TRE_ID"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "id",
|
||||
"source": {
|
||||
"env": "ID"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "tfstate_container_name",
|
||||
"source": {
|
||||
"env": "TERRAFORM_STATE_CONTAINER_NAME"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "tfstate_resource_group_name",
|
||||
"source": {
|
||||
"env": "MGMT_RESOURCE_GROUP_NAME"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "tfstate_storage_account_name",
|
||||
"source": {
|
||||
"env": "MGMT_STORAGE_ACCOUNT_NAME"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "workspace_id",
|
||||
"source": {
|
||||
"env": "WORKSPACE_ID"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "address_space",
|
||||
"source": {
|
||||
"env": "ADDRESS_SPACE"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "arm_environment",
|
||||
"source": {
|
||||
"env": "ARM_ENVIRONMENT"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "azure_environment",
|
||||
"source": {
|
||||
"env": "AZURE_ENVIRONMENT"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "configure_data_source",
|
||||
"source": {
|
||||
"env": "CONFIGURE_DATA_SOURCE"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "data_source_config",
|
||||
"source": {
|
||||
"env": "DATA_SOURCE_CONFIG"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "data_source_daimons",
|
||||
"source": {
|
||||
"env": "DATA_SOURCE_DAIMONS"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,185 @@
|
|||
---
|
||||
schemaVersion: 1.0.0
|
||||
name: tre-workspace-service-ohdsi
|
||||
version: 0.1.94
|
||||
description: "An OHDSI workspace service"
|
||||
registry: azuretre
|
||||
dockerfile: Dockerfile.tmpl
|
||||
|
||||
custom:
|
||||
dialects:
|
||||
"Azure Synapse": "synapse"
|
||||
|
||||
credentials:
|
||||
- name: azure_tenant_id
|
||||
env: ARM_TENANT_ID
|
||||
- name: azure_subscription_id
|
||||
env: ARM_SUBSCRIPTION_ID
|
||||
- name: azure_client_id
|
||||
env: ARM_CLIENT_ID
|
||||
- name: azure_client_secret
|
||||
env: ARM_CLIENT_SECRET
|
||||
|
||||
parameters:
|
||||
- name: workspace_id
|
||||
type: string
|
||||
- name: tre_id
|
||||
type: string
|
||||
- name: address_space
|
||||
type: string
|
||||
description: "Address space for PostgreSQL's subnet"
|
||||
|
||||
- name: id
|
||||
type: string
|
||||
description: "An Id for this installation"
|
||||
env: id
|
||||
- name: tfstate_resource_group_name
|
||||
type: string
|
||||
description: "Resource group containing the Terraform state storage account"
|
||||
- name: tfstate_storage_account_name
|
||||
type: string
|
||||
description: "The name of the Terraform state storage account"
|
||||
- name: tfstate_container_name
|
||||
env: tfstate_container_name
|
||||
type: string
|
||||
default: "tfstate"
|
||||
description: "The name of the Terraform state storage container"
|
||||
- name: arm_use_msi
|
||||
env: ARM_USE_MSI
|
||||
type: boolean
|
||||
default: false
|
||||
- name: arm_environment
|
||||
type: string
|
||||
- name: azure_environment
|
||||
type: string
|
||||
description: "Used by Azure CLI to set the Azure environment"
|
||||
|
||||
# parameters for configuring the data source
|
||||
- name: configure_data_source
|
||||
type: boolean
|
||||
default: false
|
||||
- name: data_source_config
|
||||
type: string
|
||||
default: ""
|
||||
- name: data_source_daimons
|
||||
type: string
|
||||
default: ""
|
||||
|
||||
mixins:
|
||||
- terraform:
|
||||
clientVersion: 1.4.6
|
||||
- az:
|
||||
clientVersion: 2.37.0
|
||||
|
||||
outputs:
|
||||
- name: connection_uri
|
||||
type: string
|
||||
applyTo:
|
||||
- install
|
||||
- upgrade
|
||||
- name: webapi_uri
|
||||
type: string
|
||||
applyTo:
|
||||
- install
|
||||
- upgrade
|
||||
- name: authentication_callback_uri
|
||||
type: string
|
||||
applyTo:
|
||||
- install
|
||||
- upgrade
|
||||
- name: is_exposed_externally
|
||||
type: boolean
|
||||
applyTo:
|
||||
- install
|
||||
- upgrade
|
||||
|
||||
|
||||
install:
|
||||
- az:
|
||||
description: "Set Azure Cloud Environment"
|
||||
arguments:
|
||||
- cloud
|
||||
- set
|
||||
flags:
|
||||
name: ${ bundle.parameters.azure_environment }
|
||||
- az:
|
||||
description: "Login to Azure"
|
||||
arguments:
|
||||
- login
|
||||
flags:
|
||||
identity:
|
||||
username: ${ bundle.credentials.azure_client_id }
|
||||
- terraform:
|
||||
description: "Deploy OHDSI workspace service"
|
||||
vars:
|
||||
workspace_id: ${ bundle.parameters.workspace_id }
|
||||
tre_id: ${ bundle.parameters.tre_id }
|
||||
tre_resource_id: ${ bundle.parameters.id }
|
||||
address_space: ${ bundle.parameters.address_space }
|
||||
arm_environment: ${ bundle.parameters.arm_environment }
|
||||
configure_data_source: ${ bundle.parameters.configure_data_source }
|
||||
data_source_config: ${ bundle.parameters.data_source_config }
|
||||
data_source_daimons: ${ bundle.parameters.data_source_daimons }
|
||||
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: tre-workspace-service-ohdsi-${ bundle.parameters.id }
|
||||
outputs:
|
||||
- name: connection_uri
|
||||
- name: webapi_uri
|
||||
- name: authentication_callback_uri
|
||||
- name: is_exposed_externally
|
||||
upgrade:
|
||||
- az:
|
||||
description: "Set Azure Cloud Environment"
|
||||
arguments:
|
||||
- cloud
|
||||
- set
|
||||
flags:
|
||||
name: ${ bundle.parameters.azure_environment }
|
||||
- az:
|
||||
description: "Login to Azure"
|
||||
arguments:
|
||||
- login
|
||||
flags:
|
||||
identity:
|
||||
username: ${ bundle.credentials.azure_client_id }
|
||||
- terraform:
|
||||
description: "Upgrade shared service"
|
||||
vars:
|
||||
workspace_id: ${ bundle.parameters.workspace_id }
|
||||
tre_id: ${ bundle.parameters.tre_id }
|
||||
tre_resource_id: ${ bundle.parameters.id }
|
||||
address_space: ${ bundle.parameters.address_space }
|
||||
arm_environment: ${ bundle.parameters.arm_environment }
|
||||
configure_data_source: ${ bundle.parameters.configure_data_source }
|
||||
data_source_config: ${ bundle.parameters.data_source_config }
|
||||
data_source_daimons: ${ bundle.parameters.data_source_daimons }
|
||||
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: tre-workspace-service-ohdsi-${ bundle.parameters.id }
|
||||
outputs:
|
||||
- name: connection_uri
|
||||
- name: webapi_uri
|
||||
- name: authentication_callback_uri
|
||||
- name: is_exposed_externally
|
||||
uninstall:
|
||||
- terraform:
|
||||
description: "Tear down OHDSI workspace service"
|
||||
vars:
|
||||
workspace_id: ${ bundle.parameters.workspace_id }
|
||||
tre_id: ${ bundle.parameters.tre_id }
|
||||
tre_resource_id: ${ bundle.parameters.id }
|
||||
address_space: ${ bundle.parameters.address_space }
|
||||
arm_environment: ${ bundle.parameters.arm_environment }
|
||||
configure_data_source: ${ bundle.parameters.configure_data_source }
|
||||
data_source_config: ${ bundle.parameters.data_source_config }
|
||||
data_source_daimons: ${ bundle.parameters.data_source_daimons }
|
||||
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: tre-workspace-service-ohdsi-${ bundle.parameters.id }
|
|
@ -0,0 +1,69 @@
|
|||
#!/bin/bash
|
||||
set -o errexit
|
||||
set -o pipefail
|
||||
set -o nounset
|
||||
|
||||
function build_daimon_object() {
|
||||
local DAIMON_TYPE=$1
|
||||
local VALUE=$2
|
||||
|
||||
echo '{
|
||||
"tableQualifier": "'"$VALUE"'",
|
||||
"priority": 0,
|
||||
"sourceDaimonId": null,
|
||||
"daimonType": "'"$DAIMON_TYPE"'"
|
||||
}'
|
||||
}
|
||||
|
||||
|
||||
# Login
|
||||
login_response=$(curl "https://${OHDSI_WEB_API_URL}/WebAPI/user/login/db" \
|
||||
--data-raw "login=$OHDSI_WEB_API_USER&password=$OHDSI_WEB_API_PASSWORD" \
|
||||
--compressed -i)
|
||||
|
||||
token=$(echo "$login_response" | grep -i bearer: | sed 's/Bearer: //' | tr -d '[:space:]')
|
||||
|
||||
|
||||
# Build the request payload
|
||||
JSON_PAYLOAD="{}"
|
||||
JSON_PAYLOAD=$(echo "$JSON_PAYLOAD" | jq '.dialect = $DIALECT' --arg DIALECT "$DIALECT")
|
||||
JSON_PAYLOAD=$(echo "$JSON_PAYLOAD" | jq '.name = $SOURCE_NAME' --arg SOURCE_NAME "$SOURCE_NAME")
|
||||
JSON_PAYLOAD=$(echo "$JSON_PAYLOAD" | jq '.key = $SOURCE_KEY' --arg SOURCE_KEY "$SOURCE_KEY")
|
||||
JSON_PAYLOAD=$(echo "$JSON_PAYLOAD" | jq '.connectionString = $CONNECTION_STRING' --arg CONNECTION_STRING "$CONNECTION_STRING")
|
||||
JSON_PAYLOAD=$(echo "$JSON_PAYLOAD" | jq '.username = $USERNAME' --arg USERNAME "$USERNAME")
|
||||
JSON_PAYLOAD=$(echo "$JSON_PAYLOAD" | jq '.password = $PASSWORD' --arg PASSWORD "$PASSWORD")
|
||||
JSON_PAYLOAD=$(echo "$JSON_PAYLOAD" | jq '.krbAuthMethod = "password"')
|
||||
JSON_PAYLOAD=$(echo "$JSON_PAYLOAD" | jq '.krbAdminServer = null')
|
||||
JSON_PAYLOAD=$(echo "$JSON_PAYLOAD" | jq '.daimons = []')
|
||||
|
||||
if [[ -v DAIMON_CDM ]]; then
|
||||
JSON_PAYLOAD=$(echo "$JSON_PAYLOAD" | jq '.daimons += [$DAIMON_CDM]' --argjson DAIMON_CDM "$(build_daimon_object "CDM" "${DAIMON_CDM}")")
|
||||
fi
|
||||
|
||||
if [[ -v DAIMON_VOCABULARY ]]; then
|
||||
JSON_PAYLOAD=$(echo "$JSON_PAYLOAD" | jq '.daimons += [$DAIMON_VOCABULARY]' --argjson DAIMON_VOCABULARY "$(build_daimon_object "Vocabulary" "${DAIMON_VOCABULARY}")")
|
||||
fi
|
||||
|
||||
if [[ -v DAIMON_RESULTS ]]; then
|
||||
JSON_PAYLOAD=$(echo "$JSON_PAYLOAD" | jq '.daimons += [$DAIMON_RESULTS]' --argjson DAIMON_RESULTS "$(build_daimon_object "Results" "${DAIMON_RESULTS}")")
|
||||
fi
|
||||
|
||||
if [[ -v DAIMON_CEM ]]; then
|
||||
JSON_PAYLOAD=$(echo "$JSON_PAYLOAD" | jq '.daimons += [$DAIMON_CEM]' --argjson DAIMON_CEM "$(build_daimon_object "CEM" "${DAIMON_CEM}")")
|
||||
fi
|
||||
|
||||
if [[ -v DAIMON_CEM_RESULTS ]]; then
|
||||
JSON_PAYLOAD=$(echo "$JSON_PAYLOAD" | jq '.daimons += [$DAIMON_CEM_RESULTS]' --argjson DAIMON_CEM_RESULTS "$(build_daimon_object "CEMResults" "${DAIMON_CEM_RESULTS}")")
|
||||
fi
|
||||
|
||||
if [[ -v DAIMON_TEMP ]]; then
|
||||
JSON_PAYLOAD=$(echo "$JSON_PAYLOAD" | jq '.daimons += [$DAIMON_TEMP]' --argjson DAIMON_TEMP "$(build_daimon_object "Temp" "${DAIMON_TEMP}")")
|
||||
fi
|
||||
|
||||
|
||||
# Add the data source
|
||||
curl -v "https://${OHDSI_WEB_API_URL}/WebAPI/source/" \
|
||||
-H "Authorization: Bearer ${token}" \
|
||||
-H 'Content-Type: multipart/form-data; boundary=----WebKitFormBoundary2C72lleJPQ9UH4DL' \
|
||||
--data-raw $'------WebKitFormBoundary2C72lleJPQ9UH4DL\r\nContent-Disposition: form-data; name="keyfile"\r\n\r\nundefined\r\n------WebKitFormBoundary2C72lleJPQ9UH4DL\r\nContent-Disposition: form-data; name="source"; filename="blob"\r\nContent-Type: application/json\r\n\r\n'"${JSON_PAYLOAD}"$'\r\n------WebKitFormBoundary2C72lleJPQ9UH4DL--\r\n' \
|
||||
--compressed
|
|
@ -0,0 +1,21 @@
|
|||
#!/bin/bash
|
||||
set -o errexit
|
||||
set -o pipefail
|
||||
set -o nounset
|
||||
|
||||
admin_user_password="${OHDSI_ADMIN_PASSWORD}${OHDSI_ADMIN_USERNAME}"
|
||||
app_user_password="${OHDSI_APP_PASSWORD}${OHDSI_APP_USERNAME}"
|
||||
admin_md5=("md5$(echo -n "$admin_user_password" | md5sum | awk '{ print $1 }')")
|
||||
export admin_md5
|
||||
app_md5=("md5$(echo -n "$app_user_password" | md5sum | awk '{ print $1 }')'")
|
||||
export app_md5
|
||||
|
||||
printf 'Creating roles and users'
|
||||
envsubst < ../sql/atlas_create_roles_users.sql | psql -v ON_ERROR_STOP=0 -e "$MAIN_CONNECTION_STRING"
|
||||
printf 'Creating roles and users: done.'
|
||||
|
||||
printf 'Creating schema'
|
||||
envsubst < ../sql/atlas_create_schema.sql | psql -v ON_ERROR_STOP=1 -e "$OHDSI_ADMIN_CONNECTION_STRING"
|
||||
printf 'Creating schema: done.'
|
||||
|
||||
printf 'Done'
|
|
@ -0,0 +1,29 @@
|
|||
#!/bin/bash
|
||||
set -o errexit
|
||||
set -o pipefail
|
||||
set -o nounset
|
||||
|
||||
psql -v ON_ERROR_STOP=1 -e "$OHDSI_ADMIN_CONNECTION_STRING" -f "../sql/atlas_create_security.sql"
|
||||
|
||||
psql -v ON_ERROR_STOP=1 -e "$OHDSI_ADMIN_CONNECTION_STRING" -f "../sql/atlas_default_roles.sql"
|
||||
|
||||
count=1
|
||||
for i in ${ATLAS_USERS//,/ }
|
||||
do
|
||||
if [ "$(("$count" % 2))" -eq "1" ]; then
|
||||
username=$i
|
||||
else
|
||||
# shellcheck disable=SC2016
|
||||
atlaspw=$(htpasswd -bnBC 4 "" "$i" | tr -d ':\n' | sed 's/$2y/$2a/')
|
||||
psql -v ON_ERROR_STOP=1 -e "$OHDSI_ADMIN_CONNECTION_STRING" -c "insert into webapi_security.security (email,password) values ('$username', E'$atlaspw');"
|
||||
# this step adds some required rows/ids in the db
|
||||
curl "$WEB_API_URL/user/login/db" --data-urlencode "login=$username" --data-urlencode "password=$i" --fail
|
||||
|
||||
if [ "$count" = "2" ]; then
|
||||
psql -v ON_ERROR_STOP=1 -e "$OHDSI_ADMIN_CONNECTION_STRING" -c "insert into webapi.sec_user_role (user_id, role_id) values ((select id from webapi.sec_user where login='$username'),2);" #admin role
|
||||
else
|
||||
psql -v ON_ERROR_STOP=1 -e "$OHDSI_ADMIN_CONNECTION_STRING" -c "insert into webapi.sec_user_role (user_id, role_id) values ((select id from webapi.sec_user where login='$username'),10);" #atlas user role
|
||||
fi
|
||||
fi
|
||||
((count++))
|
||||
done
|
|
@ -0,0 +1,17 @@
|
|||
#!/bin/bash
|
||||
set -o errexit
|
||||
set -o pipefail
|
||||
set -o nounset
|
||||
|
||||
link_name="core"
|
||||
|
||||
result=$(az network private-dns link vnet list --resource-group "${RESOURCE_GROUP}" -z "${DNS_ZONE_NAME}" --query "[?name=='${link_name}'] | length(@)")
|
||||
|
||||
if [[ "${result}" == 0 ]];
|
||||
then
|
||||
az network private-dns link vnet create \
|
||||
--name ${link_name} --resource-group "${RESOURCE_GROUP}" --virtual-network "${VNET}" --zone-name "${DNS_ZONE_NAME}" \
|
||||
--registration-enabled false
|
||||
else
|
||||
echo "Zone already linked."
|
||||
fi
|
|
@ -0,0 +1,12 @@
|
|||
#!/bin/bash
|
||||
set -o errexit
|
||||
set -o pipefail
|
||||
set -o nounset
|
||||
|
||||
export SQLCMDPASSWORD="${ADMIN_USER_PASSWORD}"
|
||||
|
||||
printf 'Initializing Results and Temp schemas'
|
||||
sqlcmd -U "${ADMIN_USERNAME}" -S "${SYNAPSE_SERVER}" -d "${SYNAPSE_DATABASE}" -W -v RESULTS_SCHEMA_NAME="${RESULTS_SCHEMA_NAME}" -v TEMP_SCHEMA_NAME="${TEMP_SCHEMA_NAME}" -v ORIGIN_RESULTS_SCHEMA_NAME="${ORIGIN_RESULTS_SCHEMA_NAME}" -i "${SQL_FILE_PATH}"
|
||||
printf 'Initializing Results and Temp schemas: done.'
|
||||
|
||||
printf 'Done'
|
|
@ -0,0 +1,23 @@
|
|||
CREATE ROLE ${OHDSI_ADMIN_ROLE} CREATEDB REPLICATION VALID UNTIL 'infinity';
|
||||
|
||||
COMMENT ON ROLE ${OHDSI_ADMIN_ROLE} IS 'Administration group for OHDSI applications';
|
||||
|
||||
CREATE ROLE ${OHDSI_APP_ROLE} VALID UNTIL 'infinity';
|
||||
|
||||
COMMENT ON ROLE ${OHDSI_APP_ROLE} IS 'Application groupfor OHDSI applications';
|
||||
|
||||
CREATE ROLE ${OHDSI_ADMIN_USERNAME} LOGIN ENCRYPTED PASSWORD ${admin_md5} VALID UNTIL 'infinity';
|
||||
|
||||
GRANT ${OHDSI_ADMIN_ROLE} TO ${OHDSI_ADMIN_USERNAME};
|
||||
|
||||
COMMENT ON ROLE ${OHDSI_ADMIN_USERNAME} IS 'Admin user account for OHDSI applications';
|
||||
|
||||
CREATE ROLE ${OHDSI_APP_USERNAME} LOGIN ENCRYPTED PASSWORD ${app_md5} VALID UNTIL 'infinity';
|
||||
|
||||
GRANT ${OHDSI_APP_ROLE} TO ${OHDSI_APP_USERNAME};
|
||||
|
||||
COMMENT ON ROLE ${OHDSI_APP_USERNAME} IS 'Application user account for OHDSI applications';
|
||||
|
||||
GRANT ALL ON DATABASE ${DATABASE_NAME} TO GROUP ${OHDSI_ADMIN_ROLE};
|
||||
|
||||
GRANT CONNECT, TEMPORARY ON DATABASE ${DATABASE_NAME} TO GROUP ${OHDSI_APP_ROLE};
|
|
@ -0,0 +1,24 @@
|
|||
CREATE SCHEMA ${SCHEMA_NAME}
|
||||
AUTHORIZATION ${OHDSI_ADMIN_ROLE};
|
||||
|
||||
COMMENT ON SCHEMA ${SCHEMA_NAME} IS 'Schema containing tables to support WebAPI functionality';
|
||||
|
||||
GRANT USAGE ON SCHEMA ${SCHEMA_NAME} TO PUBLIC;
|
||||
|
||||
GRANT ALL ON SCHEMA ${SCHEMA_NAME} TO GROUP ${OHDSI_ADMIN_ROLE};
|
||||
|
||||
GRANT USAGE ON SCHEMA ${SCHEMA_NAME} TO GROUP ${OHDSI_APP_ROLE};
|
||||
|
||||
ALTER DEFAULT PRIVILEGES IN SCHEMA ${SCHEMA_NAME} GRANT
|
||||
INSERT,
|
||||
SELECT,
|
||||
UPDATE,
|
||||
DELETE, REFERENCES,
|
||||
TRIGGER ON TABLES TO ${OHDSI_APP_ROLE};
|
||||
|
||||
ALTER DEFAULT PRIVILEGES IN SCHEMA ${SCHEMA_NAME} GRANT
|
||||
SELECT, USAGE ON SEQUENCES TO ${OHDSI_APP_ROLE};
|
||||
|
||||
ALTER DEFAULT PRIVILEGES IN SCHEMA ${SCHEMA_NAME} GRANT EXECUTE ON FUNCTIONS TO ${OHDSI_APP_ROLE};
|
||||
|
||||
ALTER DEFAULT PRIVILEGES IN SCHEMA ${SCHEMA_NAME} GRANT USAGE ON TYPES TO ${OHDSI_APP_ROLE};
|
|
@ -0,0 +1,49 @@
|
|||
create schema IF NOT EXISTS webapi_security;
|
||||
|
||||
DROP TABLE IF EXISTS webapi_security.security;
|
||||
|
||||
CREATE TABLE webapi_security.security
|
||||
(
|
||||
email character varying(255),
|
||||
password character varying(255)
|
||||
);
|
||||
|
||||
GRANT USAGE ON SCHEMA webapi_security TO PUBLIC;
|
||||
GRANT ALL ON SCHEMA webapi_security TO GROUP ohdsi_admin;
|
||||
|
||||
|
||||
do $$
|
||||
|
||||
declare tables_count integer := 0;
|
||||
declare roles_count integer := 0;
|
||||
|
||||
begin
|
||||
|
||||
while tables_count <> 3 loop
|
||||
raise notice 'Waiting for application security tables to become ready...';
|
||||
PERFORM pg_sleep(10);
|
||||
tables_count := (
|
||||
SELECT COUNT(*)
|
||||
FROM pg_tables
|
||||
WHERE schemaname = 'webapi'
|
||||
AND tablename in ('sec_user', 'sec_role', 'sec_user_role')
|
||||
);
|
||||
end loop;
|
||||
|
||||
raise notice 'All tables are ready.';
|
||||
|
||||
while roles_count <> 3 loop
|
||||
raise notice 'Waiting for application security roles to become ready...';
|
||||
PERFORM pg_sleep(10);
|
||||
roles_count := (
|
||||
SELECT COUNT(*)
|
||||
FROM webapi.sec_role
|
||||
WHERE id in (1, 2, 10)
|
||||
);
|
||||
end loop;
|
||||
|
||||
raise notice 'All roles are ready.';
|
||||
|
||||
raise notice 'Done.';
|
||||
|
||||
end$$;
|
|
@ -0,0 +1,27 @@
|
|||
-- This gives each new user access to all sources plus 'Atlas User' role.
|
||||
|
||||
CREATE OR REPLACE FUNCTION function_default_user_roles() RETURNS TRIGGER AS
|
||||
$BODY$
|
||||
BEGIN
|
||||
INSERT INTO webapi.sec_user_role (role_id, user_id)
|
||||
SELECT r.id as role_id, new.id as user_id
|
||||
FROM webapi.sec_role as r
|
||||
WHERE r.name LIKE 'Source user%' OR r.name = 'Atlas users';
|
||||
|
||||
RETURN new;
|
||||
END;
|
||||
$BODY$
|
||||
language plpgsql;
|
||||
|
||||
|
||||
DROP TRIGGER IF EXISTS trigger_sec_user_insert ON webapi.sec_user;
|
||||
|
||||
CREATE TRIGGER trigger_sec_user_insert
|
||||
AFTER INSERT ON webapi.sec_user
|
||||
FOR EACH ROW
|
||||
EXECUTE PROCEDURE function_default_user_roles();
|
||||
|
||||
DO $$
|
||||
BEGIN
|
||||
RAISE NOTICE 'Finished setting up default roles procedures.';
|
||||
END $$;
|
|
@ -0,0 +1,33 @@
|
|||
/****** Results and temp Schema creation ******/
|
||||
|
||||
CREATE SCHEMA [$(RESULTS_SCHEMA_NAME)]
|
||||
GO
|
||||
|
||||
CREATE SCHEMA [$(TEMP_SCHEMA_NAME)]
|
||||
GO
|
||||
|
||||
/****** Copy Data ******/
|
||||
CREATE TABLE #tbl
|
||||
WITH
|
||||
( DISTRIBUTION = ROUND_ROBIN
|
||||
)
|
||||
AS
|
||||
SELECT ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS Sequence
|
||||
, [name]
|
||||
, 'CREATE TABLE ' + N'$(RESULTS_SCHEMA_NAME)' + '.' + t.name + ' WITH (DISTRIBUTION = ' + d.distribution_policy_desc + ', CLUSTERED COLUMNSTORE INDEX) AS SELECT * FROM ' + N'$(ORIGIN_RESULTS_SCHEMA_NAME)' + '.' + t.name AS sql_code
|
||||
FROM sys.tables AS t left join sys.pdw_table_distribution_properties AS d ON (t.object_id = d.object_id)
|
||||
WHERE t.schema_id = (select schema_id from sys.schemas where name = N'$(ORIGIN_RESULTS_SCHEMA_NAME)')
|
||||
;
|
||||
|
||||
DECLARE @nbr_statements INT = (SELECT COUNT(*) FROM #tbl)
|
||||
, @i INT = 1
|
||||
;
|
||||
|
||||
WHILE @i <= @nbr_statements
|
||||
BEGIN
|
||||
DECLARE @sql_code NVARCHAR(4000) = (SELECT sql_code FROM #tbl WHERE Sequence = @i);
|
||||
EXEC sp_executesql @sql_code;
|
||||
SET @i +=1;
|
||||
END
|
||||
|
||||
DROP TABLE #tbl;
|
|
@ -0,0 +1,377 @@
|
|||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema",
|
||||
"$id": "https://github.com/microsoft/AzureTRE/templates/workspace_services/ohdsi/template_schema.json",
|
||||
"type": "object",
|
||||
"title": "OHDSI Workspace Service",
|
||||
"description": "Provides OHDSI within the workspace",
|
||||
"required": [],
|
||||
"properties": {
|
||||
"display_name": {
|
||||
"type": "string",
|
||||
"title": "Name for the workspace service",
|
||||
"description": "The name of the workspace service to be displayed to users",
|
||||
"default": "OHDSI ATLAS",
|
||||
"updateable": true
|
||||
},
|
||||
"description": {
|
||||
"type": "string",
|
||||
"title": "Description of the workspace service",
|
||||
"description": "Description of the workspace service",
|
||||
"default": "OHDSI empowers researchers and collaborators to bring out the value of health data through large-scale analytics and open-source solutions.",
|
||||
"updateable": true
|
||||
},
|
||||
"overview": {
|
||||
"type": "string",
|
||||
"title": "Workspace Service Overview",
|
||||
"description": "Long form description of the workspace service, in markdown syntax",
|
||||
"default": "OHDSI (Observational Health Data Sciences and Informatics) is a community-driven open-source project that provides tools and resources to help researchers and clinicians make better decisions about healthcare. OHDSI's Common Data Model (CDM) is a standardized format for storing and analyzing observational health data. The CDM can be used to create a variety of machine learning models, including patient-level prediction models, population-level effect estimation models, and risk prediction models.",
|
||||
"updateable": true
|
||||
},
|
||||
"address_space": {
|
||||
"$id": "#/properties/address_space",
|
||||
"type": "string",
|
||||
"title": "Address space",
|
||||
"description": "Address space for PostgreSQL's subnet"
|
||||
},
|
||||
"configure_data_source": {
|
||||
"type": "boolean",
|
||||
"title": "Configure Data Source",
|
||||
"default": true,
|
||||
"updateable": true
|
||||
}
|
||||
},
|
||||
"allOf": [
|
||||
{
|
||||
"if": {
|
||||
"properties": {
|
||||
"configure_data_source": {
|
||||
"const": true
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"configure_data_source"
|
||||
]
|
||||
},
|
||||
"then": {
|
||||
"properties": {
|
||||
"data_source_config": {
|
||||
"type": "object",
|
||||
"title": "Data Source Configuration",
|
||||
"default": null,
|
||||
"properties": {
|
||||
"dialect": {
|
||||
"type": "string",
|
||||
"title": "Dialect",
|
||||
"default": "Azure Synapse",
|
||||
"enum": [
|
||||
"Azure Synapse"
|
||||
],
|
||||
"updateable": true
|
||||
},
|
||||
"source_name": {
|
||||
"type": "string",
|
||||
"title": "Source Name"
|
||||
},
|
||||
"source_key": {
|
||||
"type": "string",
|
||||
"title": "Source Key",
|
||||
"description": "A unique source key"
|
||||
},
|
||||
"connection_string": {
|
||||
"type": "string",
|
||||
"title": "Connection String"
|
||||
},
|
||||
"username": {
|
||||
"type": "string",
|
||||
"title": "Username"
|
||||
},
|
||||
"password": {
|
||||
"type": "string",
|
||||
"title": "Password",
|
||||
"format": "password"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"source_name",
|
||||
"dialect",
|
||||
"source_key",
|
||||
"connection_string",
|
||||
"username",
|
||||
"password"
|
||||
]
|
||||
},
|
||||
"data_source_daimons": {
|
||||
"type": "object",
|
||||
"title": "Source Daimons",
|
||||
"description": "Configure source daimons",
|
||||
"default": null,
|
||||
"properties": {
|
||||
"daimon_cdm": {
|
||||
"type": "string",
|
||||
"title": "CDM"
|
||||
},
|
||||
"daimon_vocabulary": {
|
||||
"type": "string",
|
||||
"title": "Vocabulary"
|
||||
},
|
||||
"daimon_results": {
|
||||
"type": "string",
|
||||
"title": "Results Schema to copy"
|
||||
},
|
||||
"daimon_cem": {
|
||||
"type": "string",
|
||||
"title": "CEM"
|
||||
},
|
||||
"daimon_cem_results": {
|
||||
"type": "string",
|
||||
"title": "CEMResults"
|
||||
},
|
||||
"daimon_temp": {
|
||||
"type": "string",
|
||||
"title": "Temp Schema to copy"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"daimon_cdm",
|
||||
"daimon_vocabulary",
|
||||
"daimon_results"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"uiSchema": {
|
||||
"address_space": {
|
||||
"classNames": "tre-hidden"
|
||||
}
|
||||
},
|
||||
"pipeline": {
|
||||
"install": [
|
||||
{
|
||||
"stepId": "b9d7370e-c624-4263-921c-632329974872",
|
||||
"stepTitle": "Upgrade workspace to ensure the existence of Postgres' address space",
|
||||
"resourceType": "workspace",
|
||||
"resourceAction": "upgrade",
|
||||
"properties": []
|
||||
},
|
||||
{
|
||||
"stepId": "main"
|
||||
},
|
||||
{
|
||||
"stepId": "7276dcc1-7d0e-496a-badf-87c8c25fc06e",
|
||||
"stepTitle": "Add Atlas callback URI as AAD redirect URI",
|
||||
"resourceType": "workspace",
|
||||
"resourceAction": "upgrade",
|
||||
"properties": [
|
||||
{
|
||||
"name": "aad_redirect_uris",
|
||||
"type": "array",
|
||||
"arraySubstitutionAction": "replace",
|
||||
"arrayMatchField": "name",
|
||||
"value": {
|
||||
"name": "{{ resource.id }}",
|
||||
"value": "{{ resource.properties.authentication_callback_uri }}"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"stepId": "37d7fbde-fd61-4096-ac4d-741960474995",
|
||||
"stepTitle": "Add firewall rules for AAD",
|
||||
"resourceTemplateName": "tre-shared-service-firewall",
|
||||
"resourceType": "shared-service",
|
||||
"resourceAction": "upgrade",
|
||||
"properties": [
|
||||
{
|
||||
"name": "network_rule_collections",
|
||||
"type": "array",
|
||||
"arraySubstitutionAction": "replace",
|
||||
"arrayMatchField": "name",
|
||||
"value": {
|
||||
"name": "nrc_svc_{{ resource.id }}",
|
||||
"action": "Allow",
|
||||
"rules": [
|
||||
{
|
||||
"name": "AzureAD",
|
||||
"description": "Allow access to AAD",
|
||||
"source_addresses": "{{ resource.parent.properties.address_spaces }}",
|
||||
"destination_addresses": [
|
||||
"AzureActiveDirectory"
|
||||
],
|
||||
"destination_ports": [
|
||||
"*"
|
||||
],
|
||||
"protocols": [
|
||||
"TCP"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "rule_collections",
|
||||
"type": "array",
|
||||
"arraySubstitutionAction": "replace",
|
||||
"arrayMatchField": "name",
|
||||
"value": {
|
||||
"name": "arc_svc_{{ resource.id }}",
|
||||
"action": "Allow",
|
||||
"rules": [
|
||||
{
|
||||
"name": "microsoft-aad",
|
||||
"description": "Allow AAD FQDNs",
|
||||
"source_addresses": "{{ resource.parent.properties.address_spaces }}",
|
||||
"target_fqdns": [
|
||||
"*.msftauth.net",
|
||||
"*.msauth.net",
|
||||
"login.microsoftonline.com",
|
||||
"aadcdn.msftauthimages.net",
|
||||
"aadcdn.msauthimages.net",
|
||||
"*.login.live.com",
|
||||
"*.microsoftonline-p.com",
|
||||
"msft.sts.microsoft.com"
|
||||
],
|
||||
"protocols": [
|
||||
{
|
||||
"port": "80",
|
||||
"type": "Http"
|
||||
},
|
||||
{
|
||||
"port": "443",
|
||||
"type": "Https"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"upgrade": [
|
||||
{
|
||||
"stepId": "01dfec9b-ecc5-42c4-a022-050930a29916",
|
||||
"stepTitle": "Upgrade workspace to ensure the existence of Postgres' address space",
|
||||
"resourceType": "workspace",
|
||||
"resourceAction": "upgrade",
|
||||
"properties": []
|
||||
},
|
||||
{
|
||||
"stepId": "main"
|
||||
},
|
||||
{
|
||||
"stepId": "0d3961fd-1538-4b0e-a6ed-bf401b65c034",
|
||||
"stepTitle": "Upgrade Atlas callback URI as AAD redirect URI",
|
||||
"resourceType": "workspace",
|
||||
"resourceAction": "upgrade",
|
||||
"properties": [
|
||||
{
|
||||
"name": "aad_redirect_uris",
|
||||
"type": "array",
|
||||
"arraySubstitutionAction": "replace",
|
||||
"arrayMatchField": "name",
|
||||
"value": {
|
||||
"name": "{{ resource.id }}",
|
||||
"value": "{{ resource.properties.authentication_callback_uri }}"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"stepId": "3329d760-3e09-4721-8722-f369b123ca77",
|
||||
"stepTitle": "Add firewall rules for AAD",
|
||||
"resourceTemplateName": "tre-shared-service-firewall",
|
||||
"resourceType": "shared-service",
|
||||
"resourceAction": "upgrade",
|
||||
"properties": [
|
||||
{
|
||||
"name": "network_rule_collections",
|
||||
"type": "array",
|
||||
"arraySubstitutionAction": "replace",
|
||||
"arrayMatchField": "name",
|
||||
"value": {
|
||||
"name": "nrc_svc_{{ resource.id }}",
|
||||
"action": "Allow",
|
||||
"rules": [
|
||||
{
|
||||
"name": "AzureAD",
|
||||
"description": "Allow access to AAD",
|
||||
"source_addresses": "{{ resource.parent.properties.address_spaces }}",
|
||||
"destination_addresses": [
|
||||
"AzureActiveDirectory"
|
||||
],
|
||||
"destination_ports": [
|
||||
"*"
|
||||
],
|
||||
"protocols": [
|
||||
"TCP"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "rule_collections",
|
||||
"type": "array",
|
||||
"arraySubstitutionAction": "replace",
|
||||
"arrayMatchField": "name",
|
||||
"value": {
|
||||
"name": "arc_svc_{{ resource.id }}",
|
||||
"action": "Allow",
|
||||
"rules": [
|
||||
{
|
||||
"name": "microsoft-aad",
|
||||
"description": "Allow AAD FQDNs",
|
||||
"source_addresses": "{{ resource.parent.properties.address_spaces }}",
|
||||
"target_fqdns": [
|
||||
"*.msftauth.net",
|
||||
"*.msauth.net",
|
||||
"login.microsoftonline.com",
|
||||
"aadcdn.msftauthimages.net",
|
||||
"aadcdn.msauthimages.net",
|
||||
"*.login.live.com",
|
||||
"*.microsoftonline-p.com",
|
||||
"msft.sts.microsoft.com"
|
||||
],
|
||||
"protocols": [
|
||||
{
|
||||
"port": "80",
|
||||
"type": "Http"
|
||||
},
|
||||
{
|
||||
"port": "443",
|
||||
"type": "Https"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"uninstall": [
|
||||
{
|
||||
"stepId": "e1986fe8-b1f9-4a9d-abb1-da1ea9a50b41",
|
||||
"stepTitle": "Remove Atlas callback URI as AAD redirect URI",
|
||||
"resourceType": "workspace",
|
||||
"resourceAction": "upgrade",
|
||||
"properties": [
|
||||
{
|
||||
"name": "aad_redirect_uris",
|
||||
"type": "array",
|
||||
"arraySubstitutionAction": "remove",
|
||||
"arrayMatchField": "name",
|
||||
"value": {
|
||||
"name": "{{ resource.id }}"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"stepId": "main"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
# This file is maintained automatically by "terraform init".
|
||||
# Manual edits may be lost in future updates.
|
||||
|
||||
provider "registry.terraform.io/hashicorp/azurerm" {
|
||||
version = "3.58.0"
|
||||
constraints = "3.58.0"
|
||||
hashes = [
|
||||
"h1:Hvlt3hgTiip6xMeq8/EDGqF8NoVuZjYdTZdO79YNXsw=",
|
||||
"zh:22b19802605ca3e2b811e33650438be3647748cf8f75474c78448c30ac1cad0b",
|
||||
"zh:402ce010f4b68337abaccf8059c37294cabcbdbc3cefd9491dcd312e36ceea3c",
|
||||
"zh:53d2cd15f1631c7ffb47918064d644899cc671d47c72f4dafee4e2a5e69afd14",
|
||||
"zh:5a6b1c55629cff555472d1d43ad6e802693f7fd046c7d37718d4de6f52dbf66b",
|
||||
"zh:6181dccb7bca7cd84b0295a0332f19a7347a9586101f0a5e51b53bda1ec74651",
|
||||
"zh:854181d6a8821b3707775c913e91dd7944fcb55098953ef030168fa3cd0224aa",
|
||||
"zh:b44c758424d1a037fd833e0c69b29e3ac4047ab95653bb3e080835e55bd9badb",
|
||||
"zh:b6ee916a1579bba29b1aacce8897c6733fa97ba0dba2808f1ffa9ab492743fab",
|
||||
"zh:b7ab57044649578410dadfdf4412fc5f8aa085a25ea0b061393e843b49b43b63",
|
||||
"zh:cb68ddb922eb4be74dedf58c953d7f778b4e5f3cdcbe2ea83e02b12296ce4969",
|
||||
"zh:f569b65999264a9416862bca5cd2a6177d94ccb0424f3a4ef424428912b9cb3c",
|
||||
"zh:fe9e86173134cd9dc8ed65eae8634abc6d6f6806b5b412f54fccf4047052daa0",
|
||||
]
|
||||
}
|
||||
|
||||
provider "registry.terraform.io/hashicorp/local" {
|
||||
version = "2.4.0"
|
||||
constraints = "2.4.0"
|
||||
hashes = [
|
||||
"h1:R97FTYETo88sT2VHfMgkPU3lzCsZLunPftjSI5vfKe8=",
|
||||
"zh:53604cd29cb92538668fe09565c739358dc53ca56f9f11312b9d7de81e48fab9",
|
||||
"zh:66a46e9c508716a1c98efbf793092f03d50049fa4a83cd6b2251e9a06aca2acf",
|
||||
"zh:70a6f6a852dd83768d0778ce9817d81d4b3f073fab8fa570bff92dcb0824f732",
|
||||
"zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3",
|
||||
"zh:82a803f2f484c8b766e2e9c32343e9c89b91997b9f8d2697f9f3837f62926b35",
|
||||
"zh:9708a4e40d6cc4b8afd1352e5186e6e1502f6ae599867c120967aebe9d90ed04",
|
||||
"zh:973f65ce0d67c585f4ec250c1e634c9b22d9c4288b484ee2a871d7fa1e317406",
|
||||
"zh:c8fa0f98f9316e4cfef082aa9b785ba16e36ff754d6aba8b456dab9500e671c6",
|
||||
"zh:cfa5342a5f5188b20db246c73ac823918c189468e1382cb3c48a9c0c08fc5bf7",
|
||||
"zh:e0e2b477c7e899c63b06b38cd8684a893d834d6d0b5e9b033cedc06dd7ffe9e2",
|
||||
"zh:f62d7d05ea1ee566f732505200ab38d94315a4add27947a60afa29860822d3fc",
|
||||
"zh:fa7ce69dde358e172bd719014ad637634bbdabc49363104f4fca759b4b73f2ce",
|
||||
]
|
||||
}
|
||||
|
||||
provider "registry.terraform.io/hashicorp/random" {
|
||||
version = "3.5.1"
|
||||
constraints = "3.5.1"
|
||||
hashes = [
|
||||
"h1:VSnd9ZIPyfKHOObuQCaKfnjIHRtR7qTw19Rz8tJxm+k=",
|
||||
"zh:04e3fbd610cb52c1017d282531364b9c53ef72b6bc533acb2a90671957324a64",
|
||||
"zh:119197103301ebaf7efb91df8f0b6e0dd31e6ff943d231af35ee1831c599188d",
|
||||
"zh:4d2b219d09abf3b1bb4df93d399ed156cadd61f44ad3baf5cf2954df2fba0831",
|
||||
"zh:6130bdde527587bbe2dcaa7150363e96dbc5250ea20154176d82bc69df5d4ce3",
|
||||
"zh:6cc326cd4000f724d3086ee05587e7710f032f94fc9af35e96a386a1c6f2214f",
|
||||
"zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3",
|
||||
"zh:b6d88e1d28cf2dfa24e9fdcc3efc77adcdc1c3c3b5c7ce503a423efbdd6de57b",
|
||||
"zh:ba74c592622ecbcef9dc2a4d81ed321c4e44cddf7da799faa324da9bf52a22b2",
|
||||
"zh:c7c5cde98fe4ef1143bd1b3ec5dc04baf0d4cc3ca2c5c7d40d17c0e9b2076865",
|
||||
"zh:dac4bad52c940cd0dfc27893507c1e92393846b024c5a9db159a93c534a3da03",
|
||||
"zh:de8febe2a2acd9ac454b844a4106ed295ae9520ef54dc8ed2faf29f12716b602",
|
||||
"zh:eab0d0495e7e711cca367f7d4df6e322e6c562fc52151ec931176115b83ed014",
|
||||
]
|
||||
}
|
|
@ -0,0 +1,227 @@
|
|||
resource "random_password" "postgres_admin_password" {
|
||||
length = 32
|
||||
special = false
|
||||
}
|
||||
|
||||
resource "random_password" "postgres_webapi_admin_password" {
|
||||
length = 32
|
||||
special = false
|
||||
}
|
||||
|
||||
resource "random_password" "postgres_webapi_app_password" {
|
||||
length = 32
|
||||
special = false
|
||||
}
|
||||
|
||||
resource "azurerm_key_vault_secret" "postgres_admin_password" {
|
||||
name = "postgres-admin-password-${local.short_service_id}"
|
||||
key_vault_id = data.azurerm_key_vault.ws.id
|
||||
value = random_password.postgres_admin_password.result
|
||||
tags = local.tre_workspace_service_tags
|
||||
}
|
||||
|
||||
resource "azurerm_key_vault_secret" "postgres_webapi_admin_password" {
|
||||
name = "ohdsi-admin-password-${local.short_service_id}"
|
||||
key_vault_id = data.azurerm_key_vault.ws.id
|
||||
value = random_password.postgres_webapi_admin_password.result
|
||||
tags = local.tre_workspace_service_tags
|
||||
}
|
||||
|
||||
resource "azurerm_key_vault_secret" "postgres_webapi_app_password" {
|
||||
name = "ohdsi-app-password-${local.short_service_id}"
|
||||
key_vault_id = data.azurerm_key_vault.ws.id
|
||||
value = random_password.postgres_webapi_app_password.result
|
||||
tags = local.tre_workspace_service_tags
|
||||
}
|
||||
|
||||
resource "azurerm_network_security_group" "postgres" {
|
||||
name = "nsg-psql-${local.service_suffix}"
|
||||
resource_group_name = data.azurerm_resource_group.ws.name
|
||||
location = data.azurerm_resource_group.ws.location
|
||||
|
||||
tags = local.tre_workspace_service_tags
|
||||
|
||||
lifecycle { ignore_changes = [tags] }
|
||||
|
||||
security_rule {
|
||||
name = "AllowWebAppsToPostgres"
|
||||
priority = 100
|
||||
direction = "Inbound"
|
||||
access = "Allow"
|
||||
protocol = "Tcp"
|
||||
source_port_range = "*"
|
||||
destination_port_range = "5432"
|
||||
source_address_prefixes = [data.azurerm_subnet.web_app.address_prefix]
|
||||
destination_address_prefixes = azurerm_subnet.postgres.address_prefixes
|
||||
}
|
||||
|
||||
security_rule {
|
||||
name = "AllowResourceProcessorToPostgres"
|
||||
priority = 101
|
||||
direction = "Inbound"
|
||||
access = "Allow"
|
||||
protocol = "Tcp"
|
||||
source_port_range = "*"
|
||||
destination_port_range = "5432"
|
||||
source_address_prefixes = [data.azurerm_subnet.resource_processor.address_prefix]
|
||||
destination_address_prefixes = azurerm_subnet.postgres.address_prefixes
|
||||
}
|
||||
|
||||
security_rule {
|
||||
name = "DenyInboundOverride"
|
||||
priority = 4096
|
||||
direction = "Inbound"
|
||||
access = "Deny"
|
||||
protocol = "*"
|
||||
source_port_range = "*"
|
||||
destination_port_range = "*"
|
||||
source_address_prefix = "*"
|
||||
destination_address_prefix = "*"
|
||||
}
|
||||
|
||||
security_rule {
|
||||
name = "DenyOutboundOverride"
|
||||
priority = 4096
|
||||
direction = "Outbound"
|
||||
access = "Deny"
|
||||
protocol = "*"
|
||||
source_port_range = "*"
|
||||
destination_port_range = "*"
|
||||
source_address_prefix = "*"
|
||||
destination_address_prefix = "*"
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
resource "azurerm_subnet" "postgres" {
|
||||
name = "PostgreSQLSubnet${local.short_service_id}"
|
||||
virtual_network_name = data.azurerm_virtual_network.ws.name
|
||||
resource_group_name = data.azurerm_resource_group.ws.name
|
||||
address_prefixes = [var.address_space]
|
||||
|
||||
delegation {
|
||||
name = "psql-delegation"
|
||||
|
||||
service_delegation {
|
||||
name = "Microsoft.DBforPostgreSQL/flexibleServers"
|
||||
actions = ["Microsoft.Network/virtualNetworks/subnets/join/action"]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resource "azurerm_subnet_network_security_group_association" "postgres" {
|
||||
subnet_id = azurerm_subnet.postgres.id
|
||||
network_security_group_id = azurerm_network_security_group.postgres.id
|
||||
}
|
||||
|
||||
resource "terraform_data" "postgres_core_dns_link" {
|
||||
provisioner "local-exec" {
|
||||
|
||||
environment = {
|
||||
RESOURCE_GROUP = local.core_resource_group_name
|
||||
DNS_ZONE_NAME = data.azurerm_private_dns_zone.postgres.name
|
||||
VNET = data.azurerm_virtual_network.core.name
|
||||
}
|
||||
|
||||
command = "../scripts/postgres_dns_link.sh"
|
||||
}
|
||||
}
|
||||
|
||||
resource "terraform_data" "postgres_subnet_wait" {
|
||||
provisioner "local-exec" {
|
||||
command = "sleep 30"
|
||||
}
|
||||
|
||||
depends_on = [
|
||||
azurerm_subnet.postgres,
|
||||
azurerm_subnet_network_security_group_association.postgres,
|
||||
terraform_data.postgres_core_dns_link
|
||||
]
|
||||
}
|
||||
|
||||
resource "azurerm_postgresql_flexible_server" "postgres" {
|
||||
name = "psql-server-${local.service_suffix}"
|
||||
resource_group_name = data.azurerm_resource_group.ws.name
|
||||
location = data.azurerm_resource_group.ws.location
|
||||
delegated_subnet_id = azurerm_subnet.postgres.id
|
||||
private_dns_zone_id = data.azurerm_private_dns_zone.postgres.id
|
||||
sku_name = var.postgres_sku
|
||||
version = local.postgres_version
|
||||
administrator_login = local.postgres_admin_username
|
||||
administrator_password = azurerm_key_vault_secret.postgres_admin_password.value
|
||||
storage_mb = var.postgres_storage_size_in_mb
|
||||
zone = "1"
|
||||
tags = local.tre_workspace_service_tags
|
||||
|
||||
timeouts {
|
||||
# If this doesn't complete in a realistic time, no point in waiting the full/default 60m
|
||||
create = "15m"
|
||||
}
|
||||
|
||||
depends_on = [
|
||||
terraform_data.postgres_subnet_wait,
|
||||
]
|
||||
}
|
||||
|
||||
resource "azurerm_postgresql_flexible_server_database" "db" {
|
||||
name = local.postgres_webapi_database_name
|
||||
server_id = azurerm_postgresql_flexible_server.postgres.id
|
||||
charset = "utf8"
|
||||
collation = "en_US.utf8"
|
||||
}
|
||||
|
||||
resource "azurerm_monitor_diagnostic_setting" "postgres" {
|
||||
name = azurerm_postgresql_flexible_server.postgres.name
|
||||
target_resource_id = azurerm_postgresql_flexible_server.postgres.id
|
||||
log_analytics_workspace_id = data.azurerm_log_analytics_workspace.workspace.id
|
||||
|
||||
dynamic "enabled_log" {
|
||||
for_each = local.postgres_server_log_analytics_categories
|
||||
content {
|
||||
category = enabled_log.value
|
||||
retention_policy {
|
||||
enabled = true
|
||||
days = 30
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
metric {
|
||||
category = "AllMetrics"
|
||||
enabled = true
|
||||
|
||||
retention_policy {
|
||||
enabled = true
|
||||
days = 365
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resource "terraform_data" "deployment_ohdsi_webapi_init" {
|
||||
triggers_replace = {
|
||||
postgres_database_id = azurerm_postgresql_flexible_server_database.db.id
|
||||
}
|
||||
|
||||
provisioner "local-exec" {
|
||||
|
||||
environment = {
|
||||
MAIN_CONNECTION_STRING = "host=${azurerm_postgresql_flexible_server.postgres.fqdn} port=5432 dbname=${local.postgres_webapi_database_name} user=${local.postgres_admin_username} password=${azurerm_key_vault_secret.postgres_admin_password.value} sslmode=require"
|
||||
OHDSI_ADMIN_CONNECTION_STRING = "host=${azurerm_postgresql_flexible_server.postgres.fqdn} port=5432 dbname=${local.postgres_webapi_database_name} user=${local.postgres_webapi_admin_username} password=${azurerm_key_vault_secret.postgres_webapi_admin_password.value} sslmode=require"
|
||||
DATABASE_NAME = local.postgres_webapi_database_name
|
||||
SCHEMA_NAME = local.postgres_schema_name
|
||||
OHDSI_ADMIN_PASSWORD = azurerm_key_vault_secret.postgres_webapi_admin_password.value
|
||||
OHDSI_APP_PASSWORD = azurerm_key_vault_secret.postgres_webapi_app_password.value
|
||||
OHDSI_APP_USERNAME = local.postgres_webapi_app_username
|
||||
OHDSI_ADMIN_USERNAME = local.postgres_webapi_admin_username
|
||||
OHDSI_ADMIN_ROLE = local.postgres_webapi_admin_role
|
||||
OHDSI_APP_ROLE = local.postgres_webapi_app_role
|
||||
}
|
||||
|
||||
command = "sleep 60 && ../scripts/atlas_db_init.sh"
|
||||
}
|
||||
|
||||
depends_on = [
|
||||
terraform_data.postgres_core_dns_link,
|
||||
azurerm_subnet_network_security_group_association.postgres
|
||||
]
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
resource "random_password" "atlas_security_admin_password" {
|
||||
length = 8
|
||||
special = false
|
||||
}
|
||||
|
||||
resource "azurerm_key_vault_secret" "atlas_security_admin_password" {
|
||||
name = "atlas-security-admin-password-${local.short_service_id}"
|
||||
key_vault_id = data.azurerm_key_vault.ws.id
|
||||
value = random_password.atlas_security_admin_password.result
|
||||
tags = local.tre_workspace_service_tags
|
||||
}
|
||||
|
||||
resource "terraform_data" "deployment_atlas_security" {
|
||||
triggers_replace = {
|
||||
postgres_database_id = azurerm_postgresql_flexible_server_database.db.id
|
||||
}
|
||||
|
||||
provisioner "local-exec" {
|
||||
environment = {
|
||||
OHDSI_ADMIN_CONNECTION_STRING = "host=${azurerm_postgresql_flexible_server.postgres.fqdn} port=5432 dbname=${local.postgres_webapi_database_name} user=${local.postgres_webapi_admin_username} password=${azurerm_key_vault_secret.postgres_webapi_admin_password.value} sslmode=require"
|
||||
ATLAS_SECURITY_ADMIN_PASSWORD = azurerm_key_vault_secret.atlas_security_admin_password.value
|
||||
ATLAS_USERS = "admin,${azurerm_key_vault_secret.atlas_security_admin_password.value}"
|
||||
WEB_API_URL = local.ohdsi_webapi_url
|
||||
}
|
||||
|
||||
command = "../scripts/atlas_security.sh"
|
||||
}
|
||||
|
||||
depends_on = [
|
||||
azurerm_postgresql_flexible_server_database.db,
|
||||
terraform_data.deployment_ohdsi_webapi_init,
|
||||
terraform_data.postgres_core_dns_link,
|
||||
azurerm_private_endpoint.webapi_private_endpoint,
|
||||
azurerm_subnet_network_security_group_association.postgres
|
||||
]
|
||||
}
|
|
@ -0,0 +1,121 @@
|
|||
resource "azurerm_storage_share" "atlas_ui" {
|
||||
name = local.atlas_ui_storage_share_name
|
||||
storage_account_name = data.azurerm_storage_account.stg.name
|
||||
quota = 1
|
||||
}
|
||||
|
||||
resource "local_file" "config_local" {
|
||||
content = templatefile("${path.module}/config_local.tftpl", { OHDSI_WEBAPI_URL = local.ohdsi_webapi_url })
|
||||
filename = local.config_local_file_path
|
||||
}
|
||||
|
||||
resource "azurerm_storage_share_file" "config_local" {
|
||||
name = "config-local.js"
|
||||
storage_share_id = azurerm_storage_share.atlas_ui.id
|
||||
source = local.config_local_file_path
|
||||
|
||||
depends_on = [
|
||||
local_file.config_local
|
||||
]
|
||||
}
|
||||
|
||||
resource "azurerm_linux_web_app" "atlas_ui" {
|
||||
name = local.atlas_ui_name
|
||||
location = data.azurerm_resource_group.ws.location
|
||||
resource_group_name = data.azurerm_resource_group.ws.name
|
||||
virtual_network_subnet_id = data.azurerm_subnet.web_app.id
|
||||
|
||||
service_plan_id = data.azurerm_service_plan.workspace.id
|
||||
https_only = true
|
||||
client_affinity_enabled = false
|
||||
|
||||
site_config {
|
||||
always_on = false
|
||||
ftps_state = "Disabled"
|
||||
|
||||
application_stack {
|
||||
docker_image = "index.docker.io/${local.atlas_ui_docker_image_name}"
|
||||
docker_image_tag = local.atlas_ui_docker_image_tag
|
||||
}
|
||||
}
|
||||
|
||||
storage_account {
|
||||
access_key = data.azurerm_storage_account.stg.primary_access_key
|
||||
account_name = data.azurerm_storage_account.stg.name
|
||||
name = "ui-storage-${local.service_suffix}"
|
||||
share_name = local.atlas_ui_storage_share_name
|
||||
type = "AzureFiles"
|
||||
mount_path = local.atlas_ui_mount_path
|
||||
}
|
||||
|
||||
app_settings = {
|
||||
WEBSITES_ENABLE_APP_SERVICE_STORAGE = false
|
||||
WEBSITES_PORT = "8080"
|
||||
}
|
||||
|
||||
logs {
|
||||
application_logs {
|
||||
file_system_level = "Information"
|
||||
}
|
||||
|
||||
http_logs {
|
||||
file_system {
|
||||
retention_in_days = 7
|
||||
retention_in_mb = 100
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
depends_on = [
|
||||
azurerm_storage_share_file.config_local,
|
||||
]
|
||||
|
||||
tags = local.tre_workspace_service_tags
|
||||
}
|
||||
|
||||
resource "azurerm_private_endpoint" "atlas_ui_private_endpoint" {
|
||||
name = "pe-${azurerm_linux_web_app.atlas_ui.name}"
|
||||
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.tre_workspace_service_tags
|
||||
|
||||
private_service_connection {
|
||||
private_connection_resource_id = azurerm_linux_web_app.atlas_ui.id
|
||||
name = "psc-${azurerm_linux_web_app.atlas_ui.name}"
|
||||
subresource_names = ["sites"]
|
||||
is_manual_connection = false
|
||||
}
|
||||
|
||||
private_dns_zone_group {
|
||||
name = module.terraform_azurerm_environment_configuration.private_links["privatelink.azurewebsites.net"]
|
||||
private_dns_zone_ids = [data.azurerm_private_dns_zone.azurewebsites.id]
|
||||
}
|
||||
}
|
||||
|
||||
resource "azurerm_monitor_diagnostic_setting" "atlas_ui" {
|
||||
name = azurerm_linux_web_app.atlas_ui.name
|
||||
target_resource_id = azurerm_linux_web_app.atlas_ui.id
|
||||
log_analytics_workspace_id = data.azurerm_log_analytics_workspace.workspace.id
|
||||
|
||||
dynamic "enabled_log" {
|
||||
for_each = local.atals_ui_log_analytics_categories
|
||||
content {
|
||||
category = enabled_log.value
|
||||
retention_policy {
|
||||
enabled = true
|
||||
days = 30
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
metric {
|
||||
category = "AllMetrics"
|
||||
enabled = true
|
||||
|
||||
retention_policy {
|
||||
enabled = true
|
||||
days = 365
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
define([], function () {
|
||||
var configLocal = {};
|
||||
|
||||
// clearing local storage otherwise source cache will obscure the override settings
|
||||
localStorage.clear();
|
||||
|
||||
// WebAPI
|
||||
configLocal.api = {
|
||||
name: 'OHDSI',
|
||||
url: "${OHDSI_WEBAPI_URL}"
|
||||
};
|
||||
|
||||
configLocal.cohortComparisonResultsEnabled = false;
|
||||
configLocal.userAuthenticationEnabled = true;
|
||||
configLocal.plpResultsEnabled = false;
|
||||
configLocal.authProviders = [
|
||||
{
|
||||
"name": "OpenID",
|
||||
"url": "user/login/openid",
|
||||
"ajax": false,
|
||||
"icon": "fab fa-openid"
|
||||
},
|
||||
{
|
||||
"name": "Local Security Test DB",
|
||||
"url": "user/login/db",
|
||||
"ajax": true,
|
||||
"icon": "fa fa-database",
|
||||
"isUseCredentialsForm": true
|
||||
}
|
||||
];
|
||||
|
||||
return configLocal;
|
||||
});
|
|
@ -0,0 +1,76 @@
|
|||
data "azurerm_resource_group" "ws" {
|
||||
name = "rg-${var.tre_id}-ws-${local.short_workspace_id}"
|
||||
}
|
||||
|
||||
data "azurerm_key_vault" "ws" {
|
||||
name = local.key_vault_name
|
||||
resource_group_name = data.azurerm_resource_group.ws.name
|
||||
}
|
||||
|
||||
data "azurerm_key_vault_secret" "aad_tenant_id" {
|
||||
name = "auth-tenant-id"
|
||||
key_vault_id = data.azurerm_key_vault.ws.id
|
||||
}
|
||||
|
||||
data "azurerm_key_vault_secret" "workspace_client_id" {
|
||||
name = "workspace-client-id"
|
||||
key_vault_id = data.azurerm_key_vault.ws.id
|
||||
}
|
||||
|
||||
data "azurerm_key_vault_secret" "workspace_client_secret" {
|
||||
name = "workspace-client-secret"
|
||||
key_vault_id = data.azurerm_key_vault.ws.id
|
||||
}
|
||||
|
||||
data "azurerm_log_analytics_workspace" "workspace" {
|
||||
name = "log-${var.tre_id}-ws-${local.short_workspace_id}"
|
||||
resource_group_name = data.azurerm_resource_group.ws.name
|
||||
}
|
||||
|
||||
data "azurerm_storage_account" "stg" {
|
||||
name = local.storage_name
|
||||
resource_group_name = data.azurerm_resource_group.ws.name
|
||||
}
|
||||
|
||||
data "azurerm_service_plan" "workspace" {
|
||||
name = "plan-${var.workspace_id}"
|
||||
resource_group_name = data.azurerm_resource_group.ws.name
|
||||
}
|
||||
|
||||
data "azurerm_virtual_network" "ws" {
|
||||
name = "vnet-${var.tre_id}-ws-${local.short_workspace_id}"
|
||||
resource_group_name = data.azurerm_resource_group.ws.name
|
||||
}
|
||||
|
||||
data "azurerm_virtual_network" "core" {
|
||||
name = "vnet-${var.tre_id}"
|
||||
resource_group_name = local.core_resource_group_name
|
||||
}
|
||||
|
||||
data "azurerm_subnet" "web_app" {
|
||||
name = "WebAppsSubnet"
|
||||
virtual_network_name = data.azurerm_virtual_network.ws.name
|
||||
resource_group_name = data.azurerm_resource_group.ws.name
|
||||
}
|
||||
|
||||
data "azurerm_subnet" "services" {
|
||||
name = "ServicesSubnet"
|
||||
virtual_network_name = data.azurerm_virtual_network.ws.name
|
||||
resource_group_name = data.azurerm_resource_group.ws.name
|
||||
}
|
||||
|
||||
data "azurerm_subnet" "resource_processor" {
|
||||
name = "ResourceProcessorSubnet"
|
||||
resource_group_name = local.core_resource_group_name
|
||||
virtual_network_name = data.azurerm_virtual_network.core.name
|
||||
}
|
||||
|
||||
data "azurerm_private_dns_zone" "azurewebsites" {
|
||||
name = module.terraform_azurerm_environment_configuration.private_links["privatelink.azurewebsites.net"]
|
||||
resource_group_name = local.core_resource_group_name
|
||||
}
|
||||
|
||||
data "azurerm_private_dns_zone" "postgres" {
|
||||
name = module.terraform_azurerm_environment_configuration.private_links["privatelink.postgres.database.azure.com"]
|
||||
resource_group_name = local.core_resource_group_name
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
resource "terraform_data" "add_data_source" {
|
||||
|
||||
count = var.configure_data_source ? 1 : 0
|
||||
|
||||
triggers_replace = {
|
||||
postgres_database_id = azurerm_postgresql_flexible_server_database.db.id
|
||||
}
|
||||
|
||||
provisioner "local-exec" {
|
||||
|
||||
environment = {
|
||||
OHDSI_WEB_API_URL = local.ohdsi_webapi_fqdn
|
||||
OHDSI_WEB_API_USER = "admin"
|
||||
OHDSI_WEB_API_PASSWORD = azurerm_key_vault_secret.atlas_security_admin_password.value
|
||||
DIALECT = local.dialects[local.data_source_config.dialect]
|
||||
SOURCE_NAME = local.data_source_config.source_name
|
||||
SOURCE_KEY = local.data_source_config.source_key
|
||||
CONNECTION_STRING = local.data_source_config.connection_string
|
||||
USERNAME = local.data_source_config.username
|
||||
PASSWORD = local.data_source_config.password
|
||||
DAIMON_CDM = try(local.data_source_daimons.daimon_cdm, null)
|
||||
DAIMON_VOCABULARY = try(local.data_source_daimons.daimon_vocabulary, null)
|
||||
DAIMON_RESULTS = local.results_schema_name
|
||||
DAIMON_CEM = try(local.data_source_daimons.daimon_cem, null)
|
||||
DAIMON_CEM_RESULTS = try(local.data_source_daimons.daimon_cem_results, null)
|
||||
DAIMON_TEMP = local.temp_schema_name
|
||||
}
|
||||
|
||||
command = "../scripts/add_data_source.sh"
|
||||
}
|
||||
|
||||
depends_on = [terraform_data.deployment_atlas_security]
|
||||
}
|
||||
|
||||
resource "terraform_data" "init_synapse_schemas" {
|
||||
count = local.is_synapse_data_source && local.daimon_results != null && local.daimon_temp != null ? 1 : 0
|
||||
|
||||
provisioner "local-exec" {
|
||||
environment = {
|
||||
ADMIN_USERNAME = local.data_source_config.username
|
||||
ADMIN_USER_PASSWORD = local.data_source_config.password
|
||||
SCHEMA_NAME = local.short_service_id
|
||||
SQL_FILE_PATH = "../sql/init_results_and_temp_schemas.sql"
|
||||
SYNAPSE_SERVER = tostring(regex("(?:jdbc:sqlserver://)(.*)(:?:1433)", local.data_source_config.connection_string)[0])
|
||||
SYNAPSE_DATABASE = tostring(regex("(?:database=)(.*)(:?;user)", local.data_source_config.connection_string)[0])
|
||||
RESULTS_SCHEMA_NAME = local.results_schema_name
|
||||
TEMP_SCHEMA_NAME = local.temp_schema_name
|
||||
ORIGIN_RESULTS_SCHEMA_NAME = local.data_source_daimons.daimon_results
|
||||
}
|
||||
command = "../scripts/synapse_runner.sh"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
# This script is used to install the bundle directly without having to interact with Porter
|
||||
|
||||
# This script assumes you have created an .env from the sample and the variables
|
||||
# will come from there.
|
||||
# shellcheck disable=SC2154
|
||||
terraform init -reconfigure -input=false -backend=true \
|
||||
-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-workspace-service-ohdsi-${TF_VAR_tre_resource_id}"
|
||||
terraform apply -auto-approve
|
|
@ -0,0 +1,15 @@
|
|||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
# This script is used to uninstall the bundle directly without having to interact with Porter
|
||||
|
||||
# This script assumes you have created an .env from the sample and the variables
|
||||
# will come from there.
|
||||
# shellcheck disable=SC2154
|
||||
terraform init -reconfigure -input=false -backend=true \
|
||||
-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-workspace-service-ohdsi-${TF_VAR_tre_resource_id}"
|
||||
|
||||
terraform destroy -auto-approve
|
|
@ -0,0 +1,70 @@
|
|||
locals {
|
||||
short_service_id = substr(var.tre_resource_id, -4, -1)
|
||||
short_workspace_id = substr(var.workspace_id, -4, -1)
|
||||
workspace_resource_name_suffix = "${var.tre_id}-ws-${local.short_workspace_id}"
|
||||
core_resource_group_name = "rg-${var.tre_id}"
|
||||
service_suffix = "${local.workspace_resource_name_suffix}-svc-${local.short_service_id}"
|
||||
key_vault_name = lower("kv-${substr(local.workspace_resource_name_suffix, -20, -1)}")
|
||||
storage_name = lower(replace("stg${substr(local.workspace_resource_name_suffix, -8, -1)}", "-", ""))
|
||||
porter_yaml = yamldecode(file("${path.module}/../porter.yaml"))
|
||||
|
||||
# ATLAS Database
|
||||
postgres_admin_username = "postgres_admin"
|
||||
postgres_webapi_admin_username = "ohdsi_admin_user"
|
||||
postgres_webapi_admin_role = "ohdsi_admin"
|
||||
postgres_webapi_app_username = "ohdsi_app_user"
|
||||
postgres_webapi_app_role = "ohdsi_app"
|
||||
postgres_webapi_database_name = "atlas_webapi_db"
|
||||
postgres_schema_name = "webapi"
|
||||
postgres_version = "14"
|
||||
postgres_server_log_analytics_categories = [
|
||||
"PostgreSQLLogs"
|
||||
]
|
||||
|
||||
# ATLAS UI
|
||||
atlas_ui_name = "app-ohdsi-atlas-${local.service_suffix}"
|
||||
atlas_ui_fqdn = "${local.atlas_ui_name}.${module.terraform_azurerm_environment_configuration.web_app_suffix}"
|
||||
atlas_ui_url = "https://${local.atlas_ui_fqdn}/atlas"
|
||||
atlas_ui_url_welcome = "${local.atlas_ui_url}/#/welcome"
|
||||
atlas_ui_storage_share_name = "atlas-${local.service_suffix}"
|
||||
atlas_ui_mount_path = "/etc/atlas"
|
||||
atlas_ui_docker_image_name = "ohdsi/atlas"
|
||||
atlas_ui_docker_image_tag = "2.12.1"
|
||||
config_local_file_path = "/tmp/config-local.js"
|
||||
atals_ui_log_analytics_categories = [
|
||||
"AppServiceAppLogs",
|
||||
"AppServiceConsoleLogs",
|
||||
"AppServiceHTTPLogs"
|
||||
]
|
||||
|
||||
# OHDSI WEB API
|
||||
ohdsi_webapi_name = "app-ohdsi-webapi-${local.service_suffix}"
|
||||
ohdsi_webapi_fqdn = "${local.ohdsi_webapi_name}.${module.terraform_azurerm_environment_configuration.web_app_suffix}"
|
||||
ohdsi_webapi_url = "https://${local.ohdsi_webapi_fqdn}/WebAPI/"
|
||||
ohdsi_webapi_url_auth_callback = "${local.ohdsi_webapi_url}user/oauth/callback"
|
||||
ohdsi_api_docker_image_name = "ohdsi/webapi"
|
||||
ohdsi_api_docker_image_tag = "2.12.1"
|
||||
ohdsi_api_flyway_baseline_version = "2.2.5.20180212152023"
|
||||
ohdsi_api_log_analytics_categories = [
|
||||
"AppServiceAppLogs",
|
||||
"AppServiceConsoleLogs",
|
||||
"AppServiceHTTPLogs"
|
||||
]
|
||||
|
||||
tre_workspace_service_tags = {
|
||||
tre_id = var.tre_id
|
||||
tre_workspace_id = var.workspace_id
|
||||
tre_workspace_service_id = var.tre_resource_id
|
||||
}
|
||||
|
||||
# Data Source configuration
|
||||
dialects = local.porter_yaml["custom"]["dialects"]
|
||||
data_source_config = try(jsondecode(base64decode(var.data_source_config)), {})
|
||||
data_source_daimons = try(jsondecode(base64decode(var.data_source_daimons)), {})
|
||||
data_source_dialect = try(local.data_source_config.dialect, null)
|
||||
is_synapse_data_source = var.configure_data_source && local.data_source_dialect == "Azure Synapse"
|
||||
daimon_results = try(local.data_source_daimons.daimon_results, null)
|
||||
daimon_temp = try(local.data_source_daimons.daimon_temp, null)
|
||||
results_schema_name = local.is_synapse_data_source && local.daimon_results != null ? "${local.data_source_daimons.daimon_results}_${replace(var.tre_resource_id, "-", "_")}" : local.daimon_results
|
||||
temp_schema_name = local.is_synapse_data_source && local.daimon_temp != null ? "${local.data_source_daimons.daimon_temp}_${replace(var.tre_resource_id, "-", "_")}" : local.daimon_temp
|
||||
}
|
|
@ -0,0 +1,162 @@
|
|||
resource "azurerm_key_vault_secret" "jdbc_connection_string_webapi_admin" {
|
||||
name = "jdbc-connectionstring-${local.short_service_id}"
|
||||
key_vault_id = data.azurerm_key_vault.ws.id
|
||||
value = "jdbc:postgresql://${azurerm_postgresql_flexible_server.postgres.fqdn}:5432/${local.postgres_webapi_database_name}?user=${local.postgres_webapi_admin_username}&password=${azurerm_key_vault_secret.postgres_webapi_admin_password.value}&sslmode=require"
|
||||
tags = local.tre_workspace_service_tags
|
||||
}
|
||||
|
||||
resource "azurerm_user_assigned_identity" "ohdsi_webapi_id" {
|
||||
name = "id-ohdsi-webapi-${local.service_suffix}"
|
||||
location = data.azurerm_resource_group.ws.location
|
||||
resource_group_name = data.azurerm_resource_group.ws.name
|
||||
tags = local.tre_workspace_service_tags
|
||||
}
|
||||
|
||||
resource "azurerm_key_vault_access_policy" "ohdsi_webapi" {
|
||||
key_vault_id = data.azurerm_key_vault.ws.id
|
||||
tenant_id = azurerm_user_assigned_identity.ohdsi_webapi_id.tenant_id
|
||||
object_id = azurerm_user_assigned_identity.ohdsi_webapi_id.principal_id
|
||||
|
||||
secret_permissions = [
|
||||
"Get", "List"
|
||||
]
|
||||
}
|
||||
|
||||
resource "azurerm_linux_web_app" "ohdsi_webapi" {
|
||||
name = local.ohdsi_webapi_name
|
||||
location = data.azurerm_resource_group.ws.location
|
||||
resource_group_name = data.azurerm_resource_group.ws.name
|
||||
virtual_network_subnet_id = data.azurerm_subnet.web_app.id
|
||||
|
||||
service_plan_id = data.azurerm_service_plan.workspace.id
|
||||
https_only = true
|
||||
client_affinity_enabled = false
|
||||
|
||||
site_config {
|
||||
always_on = true
|
||||
ftps_state = "Disabled"
|
||||
|
||||
application_stack {
|
||||
docker_image = "index.docker.io/${local.ohdsi_api_docker_image_name}"
|
||||
docker_image_tag = local.ohdsi_api_docker_image_tag
|
||||
}
|
||||
}
|
||||
|
||||
key_vault_reference_identity_id = azurerm_user_assigned_identity.ohdsi_webapi_id.id
|
||||
|
||||
identity {
|
||||
type = "UserAssigned"
|
||||
identity_ids = [azurerm_user_assigned_identity.ohdsi_webapi_id.id]
|
||||
}
|
||||
|
||||
app_settings = {
|
||||
"DATASOURCE_DRIVERCLASSNAME" = "org.postgresql.Driver"
|
||||
"DATASOURCE_OHDSI_SCHEMA" = local.postgres_schema_name
|
||||
"DATASOURCE_USERNAME" = local.postgres_webapi_app_username
|
||||
"DATASOURCE_PASSWORD" = "@Microsoft.KeyVault(VaultName=${data.azurerm_key_vault.ws.name};SecretName=${azurerm_key_vault_secret.postgres_webapi_app_password.name})"
|
||||
"DATASOURCE_URL" = "@Microsoft.KeyVault(VaultName=${data.azurerm_key_vault.ws.name};SecretName=${azurerm_key_vault_secret.jdbc_connection_string_webapi_admin.name})"
|
||||
"FLYWAY_BASELINEDESCRIPTION" = "Base Migration"
|
||||
"FLYWAY_BASELINEONMIGRATE" = "true"
|
||||
"flyway_baselineVersionAsString" = local.ohdsi_api_flyway_baseline_version
|
||||
"FLYWAY_DATASOURCE_DRIVERCLASSNAME" = "org.postgresql.Driver"
|
||||
"FLYWAY_DATASOURCE_USERNAME" = local.postgres_webapi_admin_username
|
||||
"FLYWAY_DATASOURCE_PASSWORD" = "@Microsoft.KeyVault(VaultName=${data.azurerm_key_vault.ws.name};SecretName=${azurerm_key_vault_secret.postgres_webapi_admin_password.name})"
|
||||
"FLYWAY_DATASOURCE_URL" = "@Microsoft.KeyVault(VaultName=${data.azurerm_key_vault.ws.name};SecretName=${azurerm_key_vault_secret.jdbc_connection_string_webapi_admin.name})"
|
||||
"FLYWAY_LOCATIONS" = "classpath:db/migration/postgresql"
|
||||
"FLYWAY_PLACEHOLDERS_OHDSISCHEMA" = local.postgres_schema_name
|
||||
"FLYWAY_SCHEMAS" = local.postgres_schema_name
|
||||
"FLYWAY_TABLE" = "schema_history"
|
||||
"MANAGED_IDENTITY_CLIENT_ID" = azurerm_user_assigned_identity.ohdsi_webapi_id.id
|
||||
"SECURITY_SSL_ENABLED" = "false"
|
||||
"SECURITY_CORS_ENABLED" = "true"
|
||||
"SECURITY_DB_DATASOURCE_AUTHENTICATIONQUERY" = "select password from webapi_security.security where email = ?"
|
||||
"SECURITY_DB_DATASOURCE_PASSWORD" = "@Microsoft.KeyVault(VaultName=${data.azurerm_key_vault.ws.name};SecretName=${azurerm_key_vault_secret.postgres_webapi_admin_password.name})"
|
||||
"SECURITY_DB_DATASOURCE_SCHEMA" = "webapi_security"
|
||||
"SECURITY_DB_DATASOURCE_URL" = "@Microsoft.KeyVault(VaultName=${data.azurerm_key_vault.ws.name};SecretName=${azurerm_key_vault_secret.jdbc_connection_string_webapi_admin.name})"
|
||||
"SECURITY_DB_DATASOURCE_USERNAME" = local.postgres_webapi_admin_username
|
||||
"SECURITY_DURATION_INCREMENT" = "10"
|
||||
"SECURITY_DURATION_INITIAL" = "10"
|
||||
"SECURITY_MAXLOGINATTEMPTS" = "3"
|
||||
"SECURITY_ORIGIN" = "*"
|
||||
"SECURITY_PROVIDER" = "AtlasRegularSecurity"
|
||||
"SPRING_BATCH_REPOSITORY_TABLEPREFIX" = "webapi.BATCH_"
|
||||
"SPRING_JPA_PROPERTIES_HIBERNATE_DEFAULT_SCHEMA" = local.postgres_schema_name
|
||||
"SPRING_JPA_PROPERTIES_HIBERNATE_DIALECT" = "org.hibernate.dialect.PostgreSQLDialect"
|
||||
"WEBSITES_CONTAINER_START_TIME_LIMIT" = "1800"
|
||||
"WEBSITES_ENABLE_APP_SERVICE_STORAGE" = false
|
||||
"WEBSITES_PORT" = "8080"
|
||||
"security.oid.clientId" = "@Microsoft.KeyVault(VaultName=${data.azurerm_key_vault.ws.name};SecretName=${data.azurerm_key_vault_secret.workspace_client_id.name})"
|
||||
"security.oid.apiSecret" = "@Microsoft.KeyVault(VaultName=${data.azurerm_key_vault.ws.name};SecretName=${data.azurerm_key_vault_secret.workspace_client_secret.name})"
|
||||
"security.oid.url" = "${module.terraform_azurerm_environment_configuration.active_directory_endpoint}/${data.azurerm_key_vault_secret.aad_tenant_id.value}/v2.0/.well-known/openid-configuration"
|
||||
"security.oauth.callback.api" = local.ohdsi_webapi_url_auth_callback
|
||||
"security.oauth.callback.ui" = local.atlas_ui_url_welcome
|
||||
"security.oid.redirectUrl" = local.atlas_ui_url_welcome
|
||||
"security.oid.logoutUrl" = local.atlas_ui_url_welcome
|
||||
}
|
||||
|
||||
logs {
|
||||
application_logs {
|
||||
file_system_level = "Information"
|
||||
}
|
||||
|
||||
http_logs {
|
||||
file_system {
|
||||
retention_in_days = 7
|
||||
retention_in_mb = 100
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tags = local.tre_workspace_service_tags
|
||||
|
||||
depends_on = [
|
||||
terraform_data.deployment_ohdsi_webapi_init
|
||||
]
|
||||
}
|
||||
|
||||
resource "azurerm_private_endpoint" "webapi_private_endpoint" {
|
||||
name = "pe-${azurerm_linux_web_app.ohdsi_webapi.name}"
|
||||
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.tre_workspace_service_tags
|
||||
|
||||
private_service_connection {
|
||||
private_connection_resource_id = azurerm_linux_web_app.ohdsi_webapi.id
|
||||
name = "psc-${azurerm_linux_web_app.ohdsi_webapi.name}"
|
||||
subresource_names = ["sites"]
|
||||
is_manual_connection = false
|
||||
}
|
||||
|
||||
private_dns_zone_group {
|
||||
name = module.terraform_azurerm_environment_configuration.private_links["privatelink.azurewebsites.net"]
|
||||
private_dns_zone_ids = [data.azurerm_private_dns_zone.azurewebsites.id]
|
||||
}
|
||||
}
|
||||
|
||||
resource "azurerm_monitor_diagnostic_setting" "ohdsi_webapi" {
|
||||
name = azurerm_linux_web_app.ohdsi_webapi.name
|
||||
target_resource_id = azurerm_linux_web_app.ohdsi_webapi.id
|
||||
log_analytics_workspace_id = data.azurerm_log_analytics_workspace.workspace.id
|
||||
|
||||
dynamic "enabled_log" {
|
||||
for_each = local.ohdsi_api_log_analytics_categories
|
||||
content {
|
||||
category = enabled_log.value
|
||||
retention_policy {
|
||||
enabled = true
|
||||
days = 30
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
metric {
|
||||
category = "AllMetrics"
|
||||
enabled = true
|
||||
|
||||
retention_policy {
|
||||
enabled = true
|
||||
days = 365
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
output "connection_uri" {
|
||||
value = local.atlas_ui_url
|
||||
description = "Atlas Endpoint"
|
||||
|
||||
precondition {
|
||||
condition = local.atlas_ui_fqdn == azurerm_linux_web_app.atlas_ui.default_hostname
|
||||
error_message = "Computed FQDN is different than actual one."
|
||||
}
|
||||
}
|
||||
|
||||
output "webapi_uri" {
|
||||
value = local.ohdsi_webapi_url
|
||||
description = "WebAPI Endpoint"
|
||||
|
||||
precondition {
|
||||
condition = local.ohdsi_webapi_fqdn == azurerm_linux_web_app.ohdsi_webapi.default_hostname
|
||||
error_message = "Computed FQDN is different than actual one."
|
||||
}
|
||||
}
|
||||
|
||||
output "authentication_callback_uri" {
|
||||
value = "${local.ohdsi_webapi_url_auth_callback}?client_name=OidcClient"
|
||||
}
|
||||
|
||||
output "is_exposed_externally" {
|
||||
value = false
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
terraform {
|
||||
required_providers {
|
||||
azurerm = {
|
||||
source = "hashicorp/azurerm"
|
||||
version = "=3.58.0"
|
||||
}
|
||||
local = {
|
||||
source = "hashicorp/local"
|
||||
version = "=2.4.0"
|
||||
}
|
||||
random = {
|
||||
source = "hashicorp/random"
|
||||
version = "=3.5.1"
|
||||
}
|
||||
}
|
||||
backend "azurerm" {
|
||||
}
|
||||
}
|
||||
|
||||
provider "azurerm" {
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module "terraform_azurerm_environment_configuration" {
|
||||
source = "git::https://github.com/microsoft/terraform-azurerm-environment-configuration.git?ref=0.3.0"
|
||||
arm_environment = var.arm_environment
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
variable "workspace_id" {}
|
||||
variable "tre_id" {}
|
||||
variable "tre_resource_id" {}
|
||||
variable "arm_environment" {}
|
||||
variable "address_space" {
|
||||
type = string
|
||||
description = "Address space for PostgreSQL's subnet"
|
||||
}
|
||||
|
||||
# ATLAS Database
|
||||
variable "postgres_sku" {
|
||||
type = string
|
||||
default = "B_Standard_B1ms"
|
||||
description = "The SKU of the PostgreSQL database"
|
||||
}
|
||||
|
||||
variable "postgres_storage_size_in_mb" {
|
||||
type = number
|
||||
default = 32768
|
||||
description = "The storage size of the PostgreSQL database in MB"
|
||||
}
|
||||
|
||||
# Data Source Configuration
|
||||
variable "configure_data_source" {
|
||||
type = bool
|
||||
}
|
||||
|
||||
variable "data_source_config" {
|
||||
type = string
|
||||
default = null
|
||||
}
|
||||
|
||||
variable "data_source_daimons" {
|
||||
type = string
|
||||
default = null
|
||||
}
|
Загрузка…
Ссылка в новой задаче