From 44858ea18d97f4aeae50fa60119109d943292ef4 Mon Sep 17 00:00:00 2001
From: "p.delpy@dkfz-heidelberg.de"
Date: Mon, 9 Sep 2024 10:01:56 +0200
Subject: [PATCH] fix: add idmanagement and obds2fhir to dhki
---
dhki/modules/id-management-compose.yml | 96 +++++++++++++++++++++++++
dhki/modules/id-management-setup.sh | 53 ++++++++++++++
dhki/modules/id-management.md | 66 +++++++++++++++++
dhki/modules/obds2fhir-rest-compose.yml | 20 ++++++
dhki/modules/obds2fhir-rest-setup.sh | 13 ++++
5 files changed, 248 insertions(+)
create mode 100644 dhki/modules/id-management-compose.yml
create mode 100644 dhki/modules/id-management-setup.sh
create mode 100644 dhki/modules/id-management.md
create mode 100644 dhki/modules/obds2fhir-rest-compose.yml
create mode 100644 dhki/modules/obds2fhir-rest-setup.sh
diff --git a/dhki/modules/id-management-compose.yml b/dhki/modules/id-management-compose.yml
new file mode 100644
index 0000000..f9156cf
--- /dev/null
+++ b/dhki/modules/id-management-compose.yml
@@ -0,0 +1,96 @@
+version: "3.7"
+
+services:
+ id-manager:
+ image: docker.verbis.dkfz.de/bridgehead/magicpl
+ container_name: bridgehead-id-manager
+ environment:
+ TOMCAT_REVERSEPROXY_FQDN: ${HOST}
+ TOMCAT_REVERSEPROXY_SSL: "true"
+ MAGICPL_SITE: ${IDMANAGEMENT_FRIENDLY_ID}
+ MAGICPL_ALLOWED_ORIGINS: https://${HOST}
+ MAGICPL_LOCAL_PATIENTLIST_APIKEY: ${IDMANAGER_LOCAL_PATIENTLIST_APIKEY}
+ MAGICPL_CENTRAXX_APIKEY: ${IDMANAGER_UPLOAD_APIKEY}
+ MAGICPL_CONNECTOR_APIKEY: ${IDMANAGER_READ_APIKEY}
+ MAGICPL_CENTRAL_PATIENTLIST_APIKEY: ${IDMANAGER_CENTRAL_PATIENTLIST_APIKEY}
+ MAGICPL_CONTROLNUMBERGENERATOR_APIKEY: ${IDMANAGER_CONTROLNUMBERGENERATOR_APIKEY}
+ depends_on:
+ - patientlist
+ - traefik-forward-auth
+ labels:
+ - "traefik.enable=true"
+ - "traefik.http.routers.id-manager.rule=PathPrefix(`/id-manager`)"
+ - "traefik.http.services.id-manager.loadbalancer.server.port=8080"
+ - "traefik.http.routers.id-manager.tls=true"
+ - "traefik.http.routers.id-manager.middlewares=traefik-forward-auth-idm"
+
+ patientlist:
+ image: docker.verbis.dkfz.de/bridgehead/mainzelliste
+ container_name: bridgehead-patientlist
+ environment:
+ - TOMCAT_REVERSEPROXY_FQDN=${HOST}
+ - TOMCAT_REVERSEPROXY_SSL=true
+ - ML_SITE=${IDMANAGEMENT_FRIENDLY_ID}
+ - ML_DB_PASS=${PATIENTLIST_POSTGRES_PASSWORD}
+ - ML_API_KEY=${IDMANAGER_LOCAL_PATIENTLIST_APIKEY}
+ - ML_UPLOAD_API_KEY=${IDMANAGER_UPLOAD_APIKEY}
+ # Add Variables from /etc/patientlist-id-generators.env
+ - PATIENTLIST_SEEDS_TRANSFORMED
+ labels:
+ - "traefik.enable=true"
+ - "traefik.http.routers.patientlist.rule=PathPrefix(`/patientlist`)"
+ - "traefik.http.services.patientlist.loadbalancer.server.port=8080"
+ - "traefik.http.routers.patientlist.tls=true"
+ depends_on:
+ - patientlist-db
+
+ patientlist-db:
+ image: docker.verbis.dkfz.de/cache/postgres:${POSTGRES_TAG}
+ container_name: bridgehead-patientlist-db
+ environment:
+ POSTGRES_USER: "mainzelliste"
+ POSTGRES_DB: "mainzelliste"
+ POSTGRES_PASSWORD: ${PATIENTLIST_POSTGRES_PASSWORD}
+ volumes:
+ - "patientlist-db-data:/var/lib/postgresql/data"
+ # NOTE: Add backups here. This is only imported if /var/lib/bridgehead/data/patientlist/ is empty!!!
+ - "/tmp/bridgehead/patientlist/:/docker-entrypoint-initdb.d/"
+
+ traefik-forward-auth:
+ image: docker.verbis.dkfz.de/cache/oauth2-proxy/oauth2-proxy:v7.6.0
+ environment:
+ - http_proxy=http://forward_proxy:3128
+ - https_proxy=http://forward_proxy:3128
+ - OAUTH2_PROXY_PROVIDER=oidc
+ - OAUTH2_PROXY_SKIP_PROVIDER_BUTTON=true
+ - OAUTH2_PROXY_OIDC_ISSUER_URL=https://login.verbis.dkfz.de/realms/master
+ - OAUTH2_PROXY_CLIENT_ID=bridgehead-${SITE_ID}
+ - OAUTH2_PROXY_CLIENT_SECRET=${IDMANAGER_AUTH_CLIENT_SECRET}
+ - OAUTH2_PROXY_COOKIE_SECRET=${IDMANAGER_AUTH_COOKIE_SECRET}
+ - OAUTH2_PROXY_COOKIE_DOMAINS=.${HOST}
+ - OAUTH2_PROXY_HTTP_ADDRESS=:4180
+ - OAUTH2_PROXY_REVERSE_PROXY=true
+ - OAUTH2_PROXY_WHITELIST_DOMAINS=.${HOST}
+ - OAUTH2_PROXY_UPSTREAMS=static://202
+ - OAUTH2_PROXY_EMAIL_DOMAINS=*
+ - OAUTH2_PROXY_SCOPE=openid profile email
+ # Pass Authorization Header and some user information to backend services
+ - OAUTH2_PROXY_SET_AUTHORIZATION_HEADER=true
+ - OAUTH2_PROXY_SET_XAUTHREQUEST=true
+ # Keycloak has an expiration time of 60s therefore oauth2-proxy needs to refresh after that
+ - OAUTH2_PROXY_COOKIE_REFRESH=60s
+ - OAUTH2_PROXY_ALLOWED_GROUPS=DKTK-CCP-PPSN
+ - OAUTH2_PROXY_PROXY_PREFIX=/oauth2-idm
+ labels:
+ - "traefik.enable=true"
+ - "traefik.http.services.traefik-forward-auth.loadbalancer.server.port=4180"
+ - "traefik.http.routers.traefik-forward-auth.rule=Host(`${HOST}`) && PathPrefix(`/oauth2-idm`)"
+ - "traefik.http.routers.traefik-forward-auth.tls=true"
+ - "traefik.http.middlewares.traefik-forward-auth-idm.forwardauth.address=http://traefik-forward-auth:4180"
+ - "traefik.http.middlewares.traefik-forward-auth-idm.forwardauth.authResponseHeaders=Authorization"
+ depends_on:
+ forward_proxy:
+ condition: service_healthy
+
+volumes:
+ patientlist-db-data:
diff --git a/dhki/modules/id-management-setup.sh b/dhki/modules/id-management-setup.sh
new file mode 100644
index 0000000..3165956
--- /dev/null
+++ b/dhki/modules/id-management-setup.sh
@@ -0,0 +1,53 @@
+#!/bin/bash -e
+
+function idManagementSetup() {
+ if [ -n "$IDMANAGER_UPLOAD_APIKEY" ]; then
+ log INFO "id-management setup detected -- will start id-management (mainzelliste & magicpl)."
+ OVERRIDE+=" -f ./$PROJECT/modules/id-management-compose.yml"
+
+ # Auto Generate local Passwords
+ PATIENTLIST_POSTGRES_PASSWORD="$(echo \"id-management-module-db-password-salt\" | openssl pkeyutl -sign -inkey /etc/bridgehead/pki/${SITE_ID}.priv.pem | base64 | head -c 30)"
+ IDMANAGER_LOCAL_PATIENTLIST_APIKEY="$(cat /proc/sys/kernel/random/uuid | sed 's/[-]//g' | head -c 20)"
+
+ # Transform Seeds Configuration to pass it to the Mainzelliste Container
+ PATIENTLIST_SEEDS_TRANSFORMED="$(declare -p PATIENTLIST_SEEDS | tr -d '\"' | sed 's/\[/\[\"/g' | sed 's/\]/\"\]/g')"
+
+ # Ensure old ids are working !!!
+ export IDMANAGEMENT_FRIENDLY_ID=$(legacyIdMapping "$SITE_ID")
+ fi
+}
+
+# Transform into single string array, e.g. 'dktk-test' to 'dktk test'
+# Usage: transformToSingleStringArray 'dktk-test' -> 'dktk test'
+function transformToSingleStringArray() {
+ echo "${1//-/ }";
+}
+
+# Ensure all Words are Uppercase
+# Usage: transformToUppercase 'dktk test' -> 'Dktk Test'
+function transformToUppercase() {
+ result="";
+ for word in $1; do
+ result+=" ${word^}";
+ done
+ echo "$result";
+}
+
+# Handle all execeptions from the norm (e.g LMU, TUM)
+# Usage: applySpecialCases 'Muenchen Lmu Test' -> 'Muenchen LMU Test'
+function applySpecialCases() {
+ result="$1";
+ result="${result/Lmu/LMU}";
+ result="${result/Tum/TUM}";
+ result="${result/Dktk Test/Teststandort}";
+ echo "$result";
+}
+
+# Transform current siteids to legacy version
+# Usage: legacyIdMapping "dktk-test" -> "DktkTest"
+function legacyIdMapping() {
+ single_string_array=$(transformToSingleStringArray "$1");
+ uppercase_string=$(transformToUppercase "$single_string_array");
+ normalized_string=$(applySpecialCases "$uppercase_string");
+ echo "$normalized_string" | tr -d ' '
+}
diff --git a/dhki/modules/id-management.md b/dhki/modules/id-management.md
new file mode 100644
index 0000000..66f9f71
--- /dev/null
+++ b/dhki/modules/id-management.md
@@ -0,0 +1,66 @@
+# Module: Id-Management
+This module provides integration with the CCP-Pseudonymiziation Service. To learn more on the backgrounds of this service, you can refer to the [CCP Data Protection Concept](https://dktk.dkfz.de/klinische-plattformen/documents-download).
+
+## Getting Started
+The following configuration variables are added to your sites-configuration repository:
+
+```
+IDMANAGER_UPLOAD_APIKEY=""
+IDMANAGER_READ_APIKEY=""
+IDMANAGER_CENTRAL_PATIENTLIST_APIKEY=""
+IDMANAGER_CONTROLNUMBERGENERATOR_APIKEY=""
+IDMANAGER_AUTH_CLIENT_ID=""
+IDMANAGER_AUTH_CLIENT_SECRET=""
+
+IDMANAGER_SEEDS_BK=""
+IDMANAGER_SEEDS_MDS=""
+IDMANAGER_SEEDS_DKTK000001985=""
+```
+> NOTE: Additionally, the CCP-IT adds lines declaring the `PATIENTLIST_SEEDS` array in your site configuration. This will contain the seeds for the different id-generators used in all projects.
+
+Once your Bridgehead is updated and restarted, you're all set!
+
+## Additional information you may want to know
+
+### Services
+
+Upon configuration, the Bridgehead will spawn the following services:
+
+- The `bridgehead-id-manager` at https://bridgehead.local/id-manager, provides a common interface for creating pseudonyms in the bridgehead.
+- The `bridgehead-patientlist` at https://bridgehead.local/patientlist is a local instance of the open-source software [Mainzelliste](https://mainzelliste.de). This service's primary task is to map patients IDAT to pseudonyms identifying them along the different CCP projects.
+- The `bridgehead-patientlist-db` is only accessible within the Bridgehead itself. This is a local postgresql instance storing the database for `bridgehead-patientlist`. The data is persisted as a named volume `patientlist-db-data`.
+
+### How to import an existing database (e.g from Legacy Windows or from Backups)
+First you must shutdown your local bridgehead instance:
+```
+systemctl stop bridgehead@ccp
+```
+
+Next you need to remove the current patientlist database:
+```
+docker volume rm patientlist-db-data;
+```
+
+Third, you need to place your postgres dump in the import directory `/tmp/bridgehead/patientlist/some-dump.sql`. This will only be imported, then the volume `patientlist-db-data` was removed previously.
+> NOTE: Please create the postgres dump with the options "--no-owner" and "--no-privileges". Additionally ensure the dump is created in the plain format (SQL).
+
+After this, you can restart your bridgehead and the dump will be imported:
+```
+systemctl start bridgehead@ccp
+```
+
+### How to connect your local data-management
+Typically, the sites connect their local data-management for the pseudonym creation with the id-management in the bridgehead. In the following two sections, you can read where you can change the configuration:
+#### Sites using CentraXX
+On your CentraXX Server, you need to change following settings in the "centraxx-dev.properties" file.
+```
+dktk.idmanagement.url=https:///id-manager/translator/getId
+dktk.idmanagement.apiKey=
+```
+They typically already exist, but need to be changed to the new values!
+#### Sites using ADT2FHIR
+@Pierre
+
+
+### How to connect the legacy windows bridgehead
+You need to change the configuration file "..." of your Windows Bridgehead. TODO...
diff --git a/dhki/modules/obds2fhir-rest-compose.yml b/dhki/modules/obds2fhir-rest-compose.yml
new file mode 100644
index 0000000..f201e23
--- /dev/null
+++ b/dhki/modules/obds2fhir-rest-compose.yml
@@ -0,0 +1,20 @@
+version: "3.7"
+
+services:
+ obds2fhir-rest:
+ container_name: bridgehead-obds2fhir-rest
+ image: docker.verbis.dkfz.de/ccp/obds2fhir-rest:main
+ environment:
+ IDTYPE: BK_${IDMANAGEMENT_FRIENDLY_ID}_L-ID
+ MAINZELLISTE_APIKEY: ${IDMANAGER_LOCAL_PATIENTLIST_APIKEY}
+ SALT: ${LOCAL_SALT}
+ KEEP_INTERNAL_ID: ${KEEP_INTERNAL_ID:-false}
+ MAINZELLISTE_URL: ${PATIENTLIST_URL:-http://patientlist:8080/patientlist}
+ restart: always
+ labels:
+ - "traefik.enable=true"
+ - "traefik.http.routers.obds2fhir-rest.rule=PathPrefix(`/obds2fhir-rest`) || PathPrefix(`/adt2fhir-rest`)"
+ - "traefik.http.middlewares.obds2fhir-rest_strip.stripprefix.prefixes=/obds2fhir-rest,/adt2fhir-rest"
+ - "traefik.http.services.obds2fhir-rest.loadbalancer.server.port=8080"
+ - "traefik.http.routers.obds2fhir-rest.tls=true"
+ - "traefik.http.routers.obds2fhir-rest.middlewares=obds2fhir-rest_strip,auth"
diff --git a/dhki/modules/obds2fhir-rest-setup.sh b/dhki/modules/obds2fhir-rest-setup.sh
new file mode 100644
index 0000000..677ea63
--- /dev/null
+++ b/dhki/modules/obds2fhir-rest-setup.sh
@@ -0,0 +1,13 @@
+#!/bin/bash
+
+function obds2fhirRestSetup() {
+ if [ -n "$ENABLE_OBDS2FHIR_REST" ]; then
+ log INFO "oBDS2FHIR-REST setup detected -- will start obds2fhir-rest module."
+ if [ ! -n "$IDMANAGER_UPLOAD_APIKEY" ]; then
+ log ERROR "Missing ID-Management Module! Fix this by setting up ID Management:"
+ PATIENTLIST_URL=" "
+ fi
+ OVERRIDE+=" -f ./$PROJECT/modules/obds2fhir-rest-compose.yml"
+ LOCAL_SALT="$(echo \"local-random-salt\" | openssl pkeyutl -sign -inkey /etc/bridgehead/pki/${SITE_ID}.priv.pem | base64 | head -c 30)"
+ fi
+}