diff --git a/.github/workflows/build-orthanc-share.yml b/.github/workflows/build-orthanc-share.yml index 7157dfa..b035c1e 100644 --- a/.github/workflows/build-orthanc-share.yml +++ b/.github/workflows/build-orthanc-share.yml @@ -43,6 +43,15 @@ jobs: org.opencontainers.image.title=orthanc-nginx org.opencontainers.image.vendor=Orthanc Team SRL + - name: Extract metadata (tags, labels) for Docker (orthanc-nginx-certbot) + id: meta-orthanc-nginx-certbot + uses: docker/metadata-action@v4 + with: + images: orthancteam/orthanc-nginx-certbot + labels: | + org.opencontainers.image.title=orthanc-nginx-certbot + org.opencontainers.image.vendor=Orthanc Team SRL + - name: Extract metadata (tags, labels) for Docker (orthanc-auth-service) id: meta-orthanc-auth-service uses: docker/metadata-action@v5 @@ -97,6 +106,15 @@ jobs: tags: ${{ steps.meta-orthanc-nginx.outputs.tags }} labels: ${{ steps.meta-orthanc-nginx.outputs.labels }} + - name: Build and push orthanc-nginx-certbot Docker image + uses: docker/build-push-action@v4 + with: + context: sources/ + file: sources/nginx/Dockerfile.orthanc-nginx-certbot + push: true + tags: ${{ steps.meta-orthanc-nginx-certbot.outputs.tags }} + labels: ${{ steps.meta-orthanc-nginx-certbot.outputs.labels }} + - name: Build and push orthanc-auth-service Docker image uses: docker/build-push-action@v5 with: @@ -151,6 +169,15 @@ jobs: short-description: Web service to run in front of Orthanc to handle sharing of studies & admin access readme-filepath: sources/README-dockerhub-orthanc-nginx.md + - name: Docker Hub Description (orthanc-nginx-certbot) + uses: peter-evans/dockerhub-description@v3 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} + repository: orthancteam/orthanc-nginx-certbot + short-description: Web service to run in front of Orthanc to handle sharing of studies & admin access (including certbot) + readme-filepath: sources/README-dockerhub-orthanc-nginx-certbot.md + - name: Docker Hub Description (orthanc-auth-service) uses: peter-evans/dockerhub-description@v3 with: diff --git a/README.md b/README.md index 5e97195..8e1079c 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ Features: - Handles user authentication & permissions together with Keycloak - Generates publication links for: - [Stone Viewer](https://www.orthanc-server.com/static.php?page=stone-web-viewer) - - [Osimis Viewer](https://book.orthanc-server.com/plugins/osimis-webviewer.html) + - [OHIF Viewer](https://ohif.org/) - [MedDream Viewer](https://www.softneta.com/online-dicom-viewer/) (commercial - CE approved) - 3 Boilerplates `docker-compose` setups to bootstrap a setup: - One with [basic authentication](minimal-setup/basic-auth) only to demonstrate study sharing. diff --git a/minimal-setup/basic-auth/docker-compose.yml b/minimal-setup/basic-auth/docker-compose.yml index 51604d3..1c0f708 100644 --- a/minimal-setup/basic-auth/docker-compose.yml +++ b/minimal-setup/basic-auth/docker-compose.yml @@ -23,7 +23,7 @@ services: ENABLE_OHIF: "true" orthanc: - image: orthancteam/orthanc:24.5.1 + image: orthancteam/orthanc:24.6.2 volumes: - orthanc-storage:/var/lib/orthanc/db depends_on: [orthanc-db] @@ -64,7 +64,7 @@ services: } orthanc-for-shares: - image: orthancteam/orthanc:24.5.1 + image: orthancteam/orthanc:24.6.2 volumes: - orthanc-storage:/var/lib/orthanc/db depends_on: [orthanc-db] diff --git a/minimal-setup/keycloak-meddream-full/docker-compose.yml b/minimal-setup/keycloak-meddream-full/docker-compose.yml index db4cd26..393c5ac 100644 --- a/minimal-setup/keycloak-meddream-full/docker-compose.yml +++ b/minimal-setup/keycloak-meddream-full/docker-compose.yml @@ -24,7 +24,7 @@ services: ENABLE_ORTHANC_FOR_API: "true" orthanc: - image: orthancteam/orthanc:24.5.1 + image: orthancteam/orthanc:24.6.2 volumes: - orthanc-storage:/var/lib/orthanc/db depends_on: [orthanc-db] @@ -151,7 +151,7 @@ services: # An orthanc dedicated for API accesses and also used by MedDream orthanc-for-api: - image: orthancteam/orthanc:24.5.1 + image: orthancteam/orthanc:24.6.2 volumes: - orthanc-storage:/var/lib/orthanc/db - ./meddream-plugin.py:/scripts/meddream-plugin.py diff --git a/minimal-setup/keycloak/docker-compose.yml b/minimal-setup/keycloak/docker-compose.yml index 99a46ce..2aea6ff 100644 --- a/minimal-setup/keycloak/docker-compose.yml +++ b/minimal-setup/keycloak/docker-compose.yml @@ -25,8 +25,7 @@ services: orthanc: # to use OHIF-plugin: use the master-unstable image - image: orthancteam/orthanc-pre-release:permissions-ui-unstable -# image: orthancteam/orthanc:24.5.1 + image: orthancteam/orthanc:24.6.2 volumes: - orthanc-storage:/var/lib/orthanc/db depends_on: [orthanc-db] diff --git a/release-notes.md b/release-notes.md index 00ee349..91761f9 100644 --- a/release-notes.md +++ b/release-notes.md @@ -5,6 +5,7 @@ SPDX-License-Identifier: GPL-3.0-or-later --> - Upgraded OHIF from v3.7.0 to 6c9a4d9758a72f0aca7c941dc676df0ec12b973f to fix PDF +- Remove "Bearer " prefix from token when decoding user profile if present. v 24.5.1 diff --git a/sources/README-dockerhub-orthanc-nginx-certbot.md b/sources/README-dockerhub-orthanc-nginx-certbot.md new file mode 100644 index 0000000..ecaa8c3 --- /dev/null +++ b/sources/README-dockerhub-orthanc-nginx-certbot.md @@ -0,0 +1,19 @@ + + +# Orthanc-nginx-cerbot + +Same as [orthancteam/orthanc-nginx](https://hub.docker.com/r/orthancteam/orthanc-nginx) with certbot included to handle tls thanks to let'encrypt. + +On top of [orthancteam/orthanc-nginx](https://hub.docker.com/r/orthancteam/orthanc-nginx) env var, these have to be defined: + + +| Environment variables | Default value | Description | +|----------------------------|:-------------------------------------------|:----------------------------------------------------------------------------------------------------------------| +| DOMAIN_NAME | - | FQNA redirecting to the public IP of the server running Nginx. | +| CERTBOT_EMAIL | - | Email adress provided to lets'encrypt, could be used to send warnings about certificates about to expire. | + +NB: `ENABLE_HTTPS` env var decribed in [orthancteam/orthanc-nginx](https://hub.docker.com/r/orthancteam/orthanc-nginx) is not applicable in this version of the orthanc-nginx. \ No newline at end of file diff --git a/sources/nginx/Dockerfile.orthanc-nginx b/sources/nginx/Dockerfile.orthanc-nginx index 90915d0..57d6f3d 100644 --- a/sources/nginx/Dockerfile.orthanc-nginx +++ b/sources/nginx/Dockerfile.orthanc-nginx @@ -6,12 +6,14 @@ FROM nginx:1.23 RUN mkdir /etc/nginx/enabled-reverse-proxies RUN mkdir /scripts +ADD nginx/nginx-common.conf /etc/nginx/includes/ ADD nginx/reverse-proxy.* /etc/nginx/disabled-reverse-proxies/ -ADD nginx/orthanc-nginx-*.conf /etc/nginx/disabled-conf/ +ADD nginx/orthanc-nginx-http*.conf /etc/nginx/disabled-conf/ COPY nginx/docker-entrypoint.sh /scripts/ +COPY nginx/copy-conf-files.sh /scripts/ RUN ls -al /etc/nginx/disabled-reverse-proxies/ diff --git a/sources/nginx/Dockerfile.orthanc-nginx-certbot b/sources/nginx/Dockerfile.orthanc-nginx-certbot new file mode 100644 index 0000000..8621b62 --- /dev/null +++ b/sources/nginx/Dockerfile.orthanc-nginx-certbot @@ -0,0 +1,21 @@ +# SPDX-FileCopyrightText: 2022 - 2024 Orthanc Team SRL +# +# SPDX-License-Identifier: CC0-1.0 + +FROM jonasal/nginx-certbot + +RUN mkdir /etc/nginx/enabled-reverse-proxies +RUN mkdir /scripts-ot +ADD nginx/nginx-common.conf /etc/nginx/includes/ + +ADD nginx/reverse-proxy.* /etc/nginx/disabled-reverse-proxies/ + +ADD nginx/orthanc-nginx-certbot.conf /etc/nginx/user_conf.d/ + +COPY nginx/docker-entrypoint-certbot.sh /scripts-ot/ +COPY nginx/copy-conf-files.sh /scripts-ot/ + +RUN ls -al /etc/nginx/disabled-reverse-proxies/ + +ENTRYPOINT ["./scripts-ot/docker-entrypoint-certbot.sh"] + diff --git a/sources/nginx/copy-conf-files.sh b/sources/nginx/copy-conf-files.sh new file mode 100755 index 0000000..8e864d3 --- /dev/null +++ b/sources/nginx/copy-conf-files.sh @@ -0,0 +1,70 @@ +#!/bin/bash + +# SPDX-FileCopyrightText: 2022 - 2024 Orthanc Team SRL +# +# SPDX-License-Identifier: CC0-1.0 + +## configuration files management + +# first (and only) arg should be a boolean: +# 'true' --> https +# 'false'--> http + +set -o errexit + +# get https +if [ "$1" == true ]; then + https=true +else + https=false +fi + +enableOrthanc="${ENABLE_ORTHANC:-false}" +enableOrthancForApi="${ENABLE_ORTHANC_FOR_API:-false}" +enableOrthancForShares="${ENABLE_ORTHANC_FOR_SHARES:-false}" +enableKeycloak="${ENABLE_KEYCLOAK:-false}" +enableOrthancTokenService="${ENABLE_ORTHANC_TOKEN_SERVICE:-false}" +enableOhif="${ENABLE_OHIF:-false}" +enableMedDream="${ENABLE_MEDDREAM:-false}" + +ls -al /etc/nginx/disabled-reverse-proxies/ + +if [[ $enableOrthanc == "true" ]]; then + echo "ENABLE_ORTHANC is true -> enable /orthanc/ reverse proxy" + cp -f /etc/nginx/disabled-reverse-proxies/reverse-proxy.orthanc.conf /etc/nginx/enabled-reverse-proxies/ +fi + +if [[ $enableOrthancForApi == "true" ]]; then + echo "ENABLE_ORTHANC_FOR_API is true -> enable /orthanc-api/ reverse proxy" + cp -f /etc/nginx/disabled-reverse-proxies/reverse-proxy.orthanc-api.conf /etc/nginx/enabled-reverse-proxies/ +fi + +if [[ $enableOrthancForShares == "true" ]]; then + echo "ENABLE_ORTHANC_FOR_SHARES is true -> enable /shares/ reverse proxy" + cp -f /etc/nginx/disabled-reverse-proxies/reverse-proxy.shares.conf /etc/nginx/enabled-reverse-proxies/ +fi + +if [[ $enableKeycloak == "true" ]]; then + if [[ $https == "true" ]]; then + echo "ENABLE_KEYCLOAK is true and ENABLE_HTTPS is true -> enable /keycloak/ reverse proxy in https version" + cp -f /etc/nginx/disabled-reverse-proxies/reverse-proxy.keycloak-https.conf /etc/nginx/enabled-reverse-proxies/ + else + echo "ENABLE_KEYCLOAK is true and ENABLE_HTTPS is false -> enable /keycloak/ reverse proxy in http version" + cp -f /etc/nginx/disabled-reverse-proxies/reverse-proxy.keycloak-http.conf /etc/nginx/enabled-reverse-proxies/ + fi +fi + +if [[ $enableOrthancTokenService == "true" ]]; then + echo "ENABLE_ORTHANC_TOKEN_SERVICE is true -> enable /token-service/ reverse proxy" + cp -f /etc/nginx/disabled-reverse-proxies/reverse-proxy.token-service.conf /etc/nginx/enabled-reverse-proxies/ +fi + +if [[ $enableMedDream == "true" ]]; then + echo "ENABLE_MEDDREAM is true -> enable /meddream/ reverse proxy" + cp -f /etc/nginx/disabled-reverse-proxies/reverse-proxy.meddream.conf /etc/nginx/enabled-reverse-proxies/ +fi + +if [[ $enableOhif == "true" ]]; then + echo "ENABLE_OHIF is true -> enable /ohif/ reverse proxy" + cp -f /etc/nginx/disabled-reverse-proxies/reverse-proxy.ohif.conf /etc/nginx/enabled-reverse-proxies/ +fi diff --git a/sources/nginx/docker-entrypoint-certbot.sh b/sources/nginx/docker-entrypoint-certbot.sh new file mode 100755 index 0000000..dd8948a --- /dev/null +++ b/sources/nginx/docker-entrypoint-certbot.sh @@ -0,0 +1,25 @@ +#!/bin/bash + +# SPDX-FileCopyrightText: 2022 - 2024 Orthanc Team SRL +# +# SPDX-License-Identifier: CC0-1.0 + +# set -o xtrace +set -o errexit + +# configuration files management (true for https) + +./scripts-ot/copy-conf-files.sh true + +# domain name management + +if [ -z "${DOMAIN_NAME}" ]; then + echo "Error: DOMAIN_NAME is not set or is empty." + exit 1 +fi +domainName="${DOMAIN_NAME}" + +sed -i "s/domain-name-placeholder/${domainName}/g" /etc/nginx/user_conf.d/orthanc-nginx-certbot.conf + +# run ngix-certbot original entrypoint +./scripts/start_nginx_certbot.sh \ No newline at end of file diff --git a/sources/nginx/docker-entrypoint.sh b/sources/nginx/docker-entrypoint.sh index fceb1da..28de6f7 100755 --- a/sources/nginx/docker-entrypoint.sh +++ b/sources/nginx/docker-entrypoint.sh @@ -7,14 +7,7 @@ # set -o xtrace set -o errexit -enableOrthanc="${ENABLE_ORTHANC:-false}" -enableOrthancForApi="${ENABLE_ORTHANC_FOR_API:-false}" -enableOrthancForShares="${ENABLE_ORTHANC_FOR_SHARES:-false}" -enableKeycloak="${ENABLE_KEYCLOAK:-false}" -enableOrthancTokenService="${ENABLE_ORTHANC_TOKEN_SERVICE:-false}" -enableOhif="${ENABLE_OHIF:-false}" enableHttps="${ENABLE_HTTPS:-false}" -enableMedDream="${ENABLE_MEDDREAM:-false}" ls -al /etc/nginx/disabled-conf/ @@ -26,47 +19,7 @@ else cp -f /etc/nginx/disabled-conf/orthanc-nginx-http.conf /etc/nginx/conf.d/default.conf fi -ls -al /etc/nginx/disabled-reverse-proxies/ - -if [[ $enableOrthanc == "true" ]]; then - echo "ENABLE_ORTHANC is true -> enable /orthanc/ reverse proxy" - cp -f /etc/nginx/disabled-reverse-proxies/reverse-proxy.orthanc.conf /etc/nginx/enabled-reverse-proxies/ -fi - -if [[ $enableOrthancForApi == "true" ]]; then - echo "ENABLE_ORTHANC_FOR_API is true -> enable /orthanc-api/ reverse proxy" - cp -f /etc/nginx/disabled-reverse-proxies/reverse-proxy.orthanc-api.conf /etc/nginx/enabled-reverse-proxies/ -fi - -if [[ $enableOrthancForShares == "true" ]]; then - echo "ENABLE_ORTHANC_FOR_SHARES is true -> enable /shares/ reverse proxy" - cp -f /etc/nginx/disabled-reverse-proxies/reverse-proxy.shares.conf /etc/nginx/enabled-reverse-proxies/ -fi - -if [[ $enableKeycloak == "true" ]]; then - if [[ $enableHttps == "true" ]]; then - echo "ENABLE_KEYCLOAK is true and ENABLE_HTTPS is true -> enable /keycloak/ reverse proxy in https version" - cp -f /etc/nginx/disabled-reverse-proxies/reverse-proxy.keycloak-https.conf /etc/nginx/enabled-reverse-proxies/ - else - echo "ENABLE_KEYCLOAK is true and ENABLE_HTTPS is false -> enable /keycloak/ reverse proxy in http version" - cp -f /etc/nginx/disabled-reverse-proxies/reverse-proxy.keycloak-http.conf /etc/nginx/enabled-reverse-proxies/ - fi -fi - -if [[ $enableOrthancTokenService == "true" ]]; then - echo "ENABLE_ORTHANC_TOKEN_SERVICE is true -> enable /token-service/ reverse proxy" - cp -f /etc/nginx/disabled-reverse-proxies/reverse-proxy.token-service.conf /etc/nginx/enabled-reverse-proxies/ -fi - -if [[ $enableMedDream == "true" ]]; then - echo "ENABLE_MEDDREAM is true -> enable /meddream/ reverse proxy" - cp -f /etc/nginx/disabled-reverse-proxies/reverse-proxy.meddream.conf /etc/nginx/enabled-reverse-proxies/ -fi - -if [[ $enableOhif == "true" ]]; then - echo "ENABLE_OHIF is true -> enable /ohif/ reverse proxy" - cp -f /etc/nginx/disabled-reverse-proxies/reverse-proxy.ohif.conf /etc/nginx/enabled-reverse-proxies/ -fi +./scripts/copy-conf-files.sh $enableHttps # call the default nginx entrypoint /docker-entrypoint.sh "$@" diff --git a/sources/nginx/nginx-common.conf b/sources/nginx/nginx-common.conf new file mode 100644 index 0000000..0b4d2e0 --- /dev/null +++ b/sources/nginx/nginx-common.conf @@ -0,0 +1,14 @@ +# SPDX-FileCopyrightText: 2022 - 2024 Orthanc Team SRL +# +# SPDX-License-Identifier: CC0-1.0 + +# To avoid 504 error +proxy_read_timeout 240s; + +# To avoid "too big header... / 502 Bad Gateway" error (inspired from https://www.getpagespeed.com/server-setup/nginx/tuning-proxy_buffer_size-in-nginx) +proxy_buffer_size 32k; +proxy_buffers 64 8k; +proxy_busy_buffers_size 48k; + +# To avoid "414 Request-URI Too Large" whant opening 15(!) studies in OHIF +large_client_header_buffers 8 16k; \ No newline at end of file diff --git a/sources/nginx/orthanc-nginx-certbot.conf b/sources/nginx/orthanc-nginx-certbot.conf new file mode 100644 index 0000000..308c691 --- /dev/null +++ b/sources/nginx/orthanc-nginx-certbot.conf @@ -0,0 +1,21 @@ +# SPDX-FileCopyrightText: 2022 - 2024 Orthanc Team SRL +# +# SPDX-License-Identifier: CC0-1.0 + +server { + + listen 443 ssl; + + server_name domain-name-placeholder; + + # Load the certificate files. + ssl_certificate /etc/letsencrypt/live/domain-name-placeholder/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/domain-name-placeholder/privkey.pem; + ssl_trusted_certificate /etc/letsencrypt/live/domain-name-placeholder/chain.pem; + + # include buffers/timeout parameters + include /etc/nginx/includes/nginx-common.conf; + + # include all reverse proxies that have been enabled through env var (check docker-entrypoint.sh) + include /etc/nginx/enabled-reverse-proxies/*.conf; +} \ No newline at end of file diff --git a/sources/nginx/orthanc-nginx-http.conf b/sources/nginx/orthanc-nginx-http.conf index 249b1e4..5f12c19 100644 --- a/sources/nginx/orthanc-nginx-http.conf +++ b/sources/nginx/orthanc-nginx-http.conf @@ -5,16 +5,8 @@ server { listen 80; - # To avoid 504 error - proxy_read_timeout 120s; - - # To avoid "too big header... / 502 Bad Gateway" error (inspired from https://www.getpagespeed.com/server-setup/nginx/tuning-proxy_buffer_size-in-nginx) - proxy_buffer_size 32k; - proxy_buffers 64 8k; - proxy_busy_buffers_size 48k; - - # To avoid "414 Request-URI Too Large" whant opening 15(!) studies in OHIF - large_client_header_buffers 8 16k; + # include buffers/timeout parameters + include /etc/nginx/includes/nginx-common.conf; # include all reverse proxies that have been enabled through env var (check docker-entrypoint.sh) include /etc/nginx/enabled-reverse-proxies/*.conf; diff --git a/sources/nginx/orthanc-nginx-https.conf b/sources/nginx/orthanc-nginx-https.conf index 256bcd0..60256e9 100644 --- a/sources/nginx/orthanc-nginx-https.conf +++ b/sources/nginx/orthanc-nginx-https.conf @@ -9,16 +9,8 @@ server { listen 443 ssl; - # To avoid 504 error - proxy_read_timeout 120s; - - # To avoid "too big header... / 502 Bad Gateway" error (inspired from https://www.getpagespeed.com/server-setup/nginx/tuning-proxy_buffer_size-in-nginx) - proxy_buffer_size 32k; - proxy_buffers 64 8k; - proxy_busy_buffers_size 48k; - - # To avoid "414 Request-URI Too Large" whant opening 15(!) studies in OHIF - large_client_header_buffers 8 16k; + # include buffers/timeout parameters + include /etc/nginx/includes/nginx-common.conf; # include all reverse proxies that have been enabled through env var (check docker-entrypoint.sh) include /etc/nginx/enabled-reverse-proxies/*.conf; diff --git a/sources/orthanc_auth_service/app.py b/sources/orthanc_auth_service/app.py index 7dc6e52..8bd0bba 100644 --- a/sources/orthanc_auth_service/app.py +++ b/sources/orthanc_auth_service/app.py @@ -214,8 +214,10 @@ def get_user_profile(user_profile_request: UserProfileRequest): if user_profile_request.token_key == "api-key" and keycloak_admin_client is not None: response = keycloak_admin_client.get_user_profile_from_api_key(api_key=user_profile_request.token_value) else: - response = keycloak_std_client.get_user_profile_from_token(user_profile_request.token_value) - + token = user_profile_request.token_value + if token.startswith("Bearer "): + token = token.replace("Bearer ", "") + response = keycloak_std_client.get_user_profile_from_token(token) else: return anonymous_profile