From 458870898fc5ae5db9f8747b566cebb2b6555410 Mon Sep 17 00:00:00 2001 From: Hauke Hund Date: Wed, 29 Jul 2026 12:10:15 +0200 Subject: [PATCH 01/11] version to 2.1.1-SNAPSHOT --- CITATION.cff | 4 ++-- dsf-bpe/dsf-bpe-process-api-v1-base/pom.xml | 2 +- dsf-bpe/dsf-bpe-process-api-v1-impl/pom.xml | 2 +- dsf-bpe/dsf-bpe-process-api-v1-operaton/pom.xml | 2 +- dsf-bpe/dsf-bpe-process-api-v1/pom.xml | 2 +- dsf-bpe/dsf-bpe-process-api-v2-impl/pom.xml | 2 +- dsf-bpe/dsf-bpe-process-api-v2/pom.xml | 2 +- dsf-bpe/dsf-bpe-process-api/pom.xml | 2 +- dsf-bpe/dsf-bpe-server-jetty/pom.xml | 2 +- dsf-bpe/dsf-bpe-server/pom.xml | 2 +- dsf-bpe/dsf-bpe-test-plugin-v1/pom.xml | 2 +- dsf-bpe/dsf-bpe-test-plugin-v2/pom.xml | 2 +- dsf-bpe/dsf-bpe-test-plugin/pom.xml | 2 +- dsf-bpe/pom.xml | 2 +- dsf-common/dsf-common-auth/pom.xml | 2 +- dsf-common/dsf-common-build-info-reader/pom.xml | 2 +- dsf-common/dsf-common-config/pom.xml | 2 +- dsf-common/dsf-common-db/pom.xml | 2 +- dsf-common/dsf-common-docker-secrets-reader/pom.xml | 2 +- dsf-common/dsf-common-documentation/pom.xml | 2 +- dsf-common/dsf-common-jetty/pom.xml | 2 +- dsf-common/dsf-common-oidc/pom.xml | 2 +- dsf-common/dsf-common-status/pom.xml | 2 +- dsf-common/dsf-common-ui/pom.xml | 2 +- dsf-common/pom.xml | 2 +- dsf-fhir/dsf-fhir-rest-adapter/pom.xml | 2 +- dsf-fhir/dsf-fhir-server-jetty/pom.xml | 2 +- dsf-fhir/dsf-fhir-server/pom.xml | 2 +- dsf-fhir/dsf-fhir-validation/pom.xml | 2 +- dsf-fhir/dsf-fhir-webservice-client/pom.xml | 2 +- dsf-fhir/dsf-fhir-websocket-client/pom.xml | 2 +- dsf-fhir/pom.xml | 2 +- dsf-maven/dsf-maven-plugin/pom.xml | 2 +- dsf-maven/pom.xml | 2 +- pom.xml | 2 +- 35 files changed, 36 insertions(+), 36 deletions(-) diff --git a/CITATION.cff b/CITATION.cff index 4ecc275eb..00d750be0 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -24,8 +24,8 @@ preferred-citation: doi: 10.3233/SHTI210060 type: proceedings title: "Data Sharing Framework (DSF)" -version: 2.1.0 -date-released: 2026-04-14 +version: 2.1.1 +date-released: 2026-08-04 url: https://dsf.dev repository-code: https://github.com/datasharingframework/dsf repository-artifact: https://github.com/datasharingframework/dsf/releases diff --git a/dsf-bpe/dsf-bpe-process-api-v1-base/pom.xml b/dsf-bpe/dsf-bpe-process-api-v1-base/pom.xml index eb44c20f9..a6b2dd82d 100644 --- a/dsf-bpe/dsf-bpe-process-api-v1-base/pom.xml +++ b/dsf-bpe/dsf-bpe-process-api-v1-base/pom.xml @@ -23,7 +23,7 @@ dev.dsf dsf-bpe-pom - 2.1.0 + 2.1.1-SNAPSHOT diff --git a/dsf-bpe/dsf-bpe-process-api-v1-impl/pom.xml b/dsf-bpe/dsf-bpe-process-api-v1-impl/pom.xml index 1323ee3b1..c5d2d4fcb 100644 --- a/dsf-bpe/dsf-bpe-process-api-v1-impl/pom.xml +++ b/dsf-bpe/dsf-bpe-process-api-v1-impl/pom.xml @@ -23,7 +23,7 @@ dev.dsf dsf-bpe-pom - 2.1.0 + 2.1.1-SNAPSHOT diff --git a/dsf-bpe/dsf-bpe-process-api-v1-operaton/pom.xml b/dsf-bpe/dsf-bpe-process-api-v1-operaton/pom.xml index 3e3bae16c..95816cf97 100644 --- a/dsf-bpe/dsf-bpe-process-api-v1-operaton/pom.xml +++ b/dsf-bpe/dsf-bpe-process-api-v1-operaton/pom.xml @@ -23,7 +23,7 @@ dev.dsf dsf-bpe-pom - 2.1.0 + 2.1.1-SNAPSHOT diff --git a/dsf-bpe/dsf-bpe-process-api-v1/pom.xml b/dsf-bpe/dsf-bpe-process-api-v1/pom.xml index cb46d8890..328e41ef5 100644 --- a/dsf-bpe/dsf-bpe-process-api-v1/pom.xml +++ b/dsf-bpe/dsf-bpe-process-api-v1/pom.xml @@ -23,7 +23,7 @@ dev.dsf dsf-bpe-pom - 2.1.0 + 2.1.1-SNAPSHOT diff --git a/dsf-bpe/dsf-bpe-process-api-v2-impl/pom.xml b/dsf-bpe/dsf-bpe-process-api-v2-impl/pom.xml index d5e52227a..cd1ea1a2e 100644 --- a/dsf-bpe/dsf-bpe-process-api-v2-impl/pom.xml +++ b/dsf-bpe/dsf-bpe-process-api-v2-impl/pom.xml @@ -23,7 +23,7 @@ dev.dsf dsf-bpe-pom - 2.1.0 + 2.1.1-SNAPSHOT diff --git a/dsf-bpe/dsf-bpe-process-api-v2/pom.xml b/dsf-bpe/dsf-bpe-process-api-v2/pom.xml index ddc147bc6..0fc973937 100644 --- a/dsf-bpe/dsf-bpe-process-api-v2/pom.xml +++ b/dsf-bpe/dsf-bpe-process-api-v2/pom.xml @@ -23,7 +23,7 @@ dev.dsf dsf-bpe-pom - 2.1.0 + 2.1.1-SNAPSHOT diff --git a/dsf-bpe/dsf-bpe-process-api/pom.xml b/dsf-bpe/dsf-bpe-process-api/pom.xml index ba27d7158..0205d2748 100644 --- a/dsf-bpe/dsf-bpe-process-api/pom.xml +++ b/dsf-bpe/dsf-bpe-process-api/pom.xml @@ -25,7 +25,7 @@ dev.dsf dsf-bpe-pom - 2.1.0 + 2.1.1-SNAPSHOT diff --git a/dsf-bpe/dsf-bpe-server-jetty/pom.xml b/dsf-bpe/dsf-bpe-server-jetty/pom.xml index 94a6b1839..608b48094 100755 --- a/dsf-bpe/dsf-bpe-server-jetty/pom.xml +++ b/dsf-bpe/dsf-bpe-server-jetty/pom.xml @@ -23,7 +23,7 @@ dev.dsf dsf-bpe-pom - 2.1.0 + 2.1.1-SNAPSHOT diff --git a/dsf-bpe/dsf-bpe-server/pom.xml b/dsf-bpe/dsf-bpe-server/pom.xml index 9ba226efb..30c57b695 100755 --- a/dsf-bpe/dsf-bpe-server/pom.xml +++ b/dsf-bpe/dsf-bpe-server/pom.xml @@ -23,7 +23,7 @@ dev.dsf dsf-bpe-pom - 2.1.0 + 2.1.1-SNAPSHOT diff --git a/dsf-bpe/dsf-bpe-test-plugin-v1/pom.xml b/dsf-bpe/dsf-bpe-test-plugin-v1/pom.xml index 512dd8b7b..8192f0a65 100644 --- a/dsf-bpe/dsf-bpe-test-plugin-v1/pom.xml +++ b/dsf-bpe/dsf-bpe-test-plugin-v1/pom.xml @@ -23,7 +23,7 @@ dev.dsf dsf-bpe-pom - 2.1.0 + 2.1.1-SNAPSHOT diff --git a/dsf-bpe/dsf-bpe-test-plugin-v2/pom.xml b/dsf-bpe/dsf-bpe-test-plugin-v2/pom.xml index cddcddb30..7dfcb7880 100644 --- a/dsf-bpe/dsf-bpe-test-plugin-v2/pom.xml +++ b/dsf-bpe/dsf-bpe-test-plugin-v2/pom.xml @@ -23,7 +23,7 @@ dev.dsf dsf-bpe-pom - 2.1.0 + 2.1.1-SNAPSHOT diff --git a/dsf-bpe/dsf-bpe-test-plugin/pom.xml b/dsf-bpe/dsf-bpe-test-plugin/pom.xml index 83fe44e36..61bea458f 100644 --- a/dsf-bpe/dsf-bpe-test-plugin/pom.xml +++ b/dsf-bpe/dsf-bpe-test-plugin/pom.xml @@ -23,7 +23,7 @@ dev.dsf dsf-bpe-pom - 2.1.0 + 2.1.1-SNAPSHOT diff --git a/dsf-bpe/pom.xml b/dsf-bpe/pom.xml index 5d9a7aa0e..08fef2cbb 100755 --- a/dsf-bpe/pom.xml +++ b/dsf-bpe/pom.xml @@ -24,7 +24,7 @@ dev.dsf dsf-pom - 2.1.0 + 2.1.1-SNAPSHOT diff --git a/dsf-common/dsf-common-auth/pom.xml b/dsf-common/dsf-common-auth/pom.xml index a0b85b5db..a7b809b77 100644 --- a/dsf-common/dsf-common-auth/pom.xml +++ b/dsf-common/dsf-common-auth/pom.xml @@ -23,7 +23,7 @@ dev.dsf dsf-common-pom - 2.1.0 + 2.1.1-SNAPSHOT diff --git a/dsf-common/dsf-common-build-info-reader/pom.xml b/dsf-common/dsf-common-build-info-reader/pom.xml index c9df2445a..fade0b103 100644 --- a/dsf-common/dsf-common-build-info-reader/pom.xml +++ b/dsf-common/dsf-common-build-info-reader/pom.xml @@ -23,7 +23,7 @@ dev.dsf dsf-common-pom - 2.1.0 + 2.1.1-SNAPSHOT diff --git a/dsf-common/dsf-common-config/pom.xml b/dsf-common/dsf-common-config/pom.xml index ea99ec487..5f5f2b5b4 100644 --- a/dsf-common/dsf-common-config/pom.xml +++ b/dsf-common/dsf-common-config/pom.xml @@ -23,7 +23,7 @@ dev.dsf dsf-common-pom - 2.1.0 + 2.1.1-SNAPSHOT diff --git a/dsf-common/dsf-common-db/pom.xml b/dsf-common/dsf-common-db/pom.xml index e4ebab9a5..d2d8c3414 100644 --- a/dsf-common/dsf-common-db/pom.xml +++ b/dsf-common/dsf-common-db/pom.xml @@ -23,7 +23,7 @@ dev.dsf dsf-common-pom - 2.1.0 + 2.1.1-SNAPSHOT diff --git a/dsf-common/dsf-common-docker-secrets-reader/pom.xml b/dsf-common/dsf-common-docker-secrets-reader/pom.xml index 53738b0cf..87ac31219 100644 --- a/dsf-common/dsf-common-docker-secrets-reader/pom.xml +++ b/dsf-common/dsf-common-docker-secrets-reader/pom.xml @@ -23,7 +23,7 @@ dev.dsf dsf-common-pom - 2.1.0 + 2.1.1-SNAPSHOT diff --git a/dsf-common/dsf-common-documentation/pom.xml b/dsf-common/dsf-common-documentation/pom.xml index ce16e5f65..1dd75fa0f 100644 --- a/dsf-common/dsf-common-documentation/pom.xml +++ b/dsf-common/dsf-common-documentation/pom.xml @@ -23,7 +23,7 @@ dev.dsf dsf-common-pom - 2.1.0 + 2.1.1-SNAPSHOT diff --git a/dsf-common/dsf-common-jetty/pom.xml b/dsf-common/dsf-common-jetty/pom.xml index a2f4612f7..34f905682 100644 --- a/dsf-common/dsf-common-jetty/pom.xml +++ b/dsf-common/dsf-common-jetty/pom.xml @@ -23,7 +23,7 @@ dev.dsf dsf-common-pom - 2.1.0 + 2.1.1-SNAPSHOT diff --git a/dsf-common/dsf-common-oidc/pom.xml b/dsf-common/dsf-common-oidc/pom.xml index 4113ca264..b42aa9a2a 100644 --- a/dsf-common/dsf-common-oidc/pom.xml +++ b/dsf-common/dsf-common-oidc/pom.xml @@ -25,7 +25,7 @@ dev.dsf dsf-common-pom - 2.1.0 + 2.1.1-SNAPSHOT diff --git a/dsf-common/dsf-common-status/pom.xml b/dsf-common/dsf-common-status/pom.xml index 59f9c67b1..b8a03f6e1 100644 --- a/dsf-common/dsf-common-status/pom.xml +++ b/dsf-common/dsf-common-status/pom.xml @@ -23,7 +23,7 @@ dev.dsf dsf-common-pom - 2.1.0 + 2.1.1-SNAPSHOT diff --git a/dsf-common/dsf-common-ui/pom.xml b/dsf-common/dsf-common-ui/pom.xml index 32f6c8f27..3adb67d79 100644 --- a/dsf-common/dsf-common-ui/pom.xml +++ b/dsf-common/dsf-common-ui/pom.xml @@ -23,7 +23,7 @@ dev.dsf dsf-common-pom - 2.1.0 + 2.1.1-SNAPSHOT diff --git a/dsf-common/pom.xml b/dsf-common/pom.xml index 85108968c..c2fd7997f 100644 --- a/dsf-common/pom.xml +++ b/dsf-common/pom.xml @@ -24,7 +24,7 @@ dev.dsf dsf-pom - 2.1.0 + 2.1.1-SNAPSHOT diff --git a/dsf-fhir/dsf-fhir-rest-adapter/pom.xml b/dsf-fhir/dsf-fhir-rest-adapter/pom.xml index 70f5bb7f9..6f2a8869d 100755 --- a/dsf-fhir/dsf-fhir-rest-adapter/pom.xml +++ b/dsf-fhir/dsf-fhir-rest-adapter/pom.xml @@ -23,7 +23,7 @@ dev.dsf dsf-fhir-pom - 2.1.0 + 2.1.1-SNAPSHOT diff --git a/dsf-fhir/dsf-fhir-server-jetty/pom.xml b/dsf-fhir/dsf-fhir-server-jetty/pom.xml index fb873c6bd..ac31c551b 100755 --- a/dsf-fhir/dsf-fhir-server-jetty/pom.xml +++ b/dsf-fhir/dsf-fhir-server-jetty/pom.xml @@ -23,7 +23,7 @@ dev.dsf dsf-fhir-pom - 2.1.0 + 2.1.1-SNAPSHOT diff --git a/dsf-fhir/dsf-fhir-server/pom.xml b/dsf-fhir/dsf-fhir-server/pom.xml index d269e7be3..5ab54be76 100755 --- a/dsf-fhir/dsf-fhir-server/pom.xml +++ b/dsf-fhir/dsf-fhir-server/pom.xml @@ -23,7 +23,7 @@ dev.dsf dsf-fhir-pom - 2.1.0 + 2.1.1-SNAPSHOT diff --git a/dsf-fhir/dsf-fhir-validation/pom.xml b/dsf-fhir/dsf-fhir-validation/pom.xml index 5abbd43de..f6d6bca09 100644 --- a/dsf-fhir/dsf-fhir-validation/pom.xml +++ b/dsf-fhir/dsf-fhir-validation/pom.xml @@ -23,7 +23,7 @@ dev.dsf dsf-fhir-pom - 2.1.0 + 2.1.1-SNAPSHOT diff --git a/dsf-fhir/dsf-fhir-webservice-client/pom.xml b/dsf-fhir/dsf-fhir-webservice-client/pom.xml index 89031ffa8..0a3dc99eb 100755 --- a/dsf-fhir/dsf-fhir-webservice-client/pom.xml +++ b/dsf-fhir/dsf-fhir-webservice-client/pom.xml @@ -23,7 +23,7 @@ dev.dsf dsf-fhir-pom - 2.1.0 + 2.1.1-SNAPSHOT diff --git a/dsf-fhir/dsf-fhir-websocket-client/pom.xml b/dsf-fhir/dsf-fhir-websocket-client/pom.xml index 71d83c108..f3ab0962d 100755 --- a/dsf-fhir/dsf-fhir-websocket-client/pom.xml +++ b/dsf-fhir/dsf-fhir-websocket-client/pom.xml @@ -23,7 +23,7 @@ dev.dsf dsf-fhir-pom - 2.1.0 + 2.1.1-SNAPSHOT diff --git a/dsf-fhir/pom.xml b/dsf-fhir/pom.xml index 648ff250a..29fc49467 100755 --- a/dsf-fhir/pom.xml +++ b/dsf-fhir/pom.xml @@ -24,7 +24,7 @@ dev.dsf dsf-pom - 2.1.0 + 2.1.1-SNAPSHOT diff --git a/dsf-maven/dsf-maven-plugin/pom.xml b/dsf-maven/dsf-maven-plugin/pom.xml index f8b6a5da5..fa6486a2f 100644 --- a/dsf-maven/dsf-maven-plugin/pom.xml +++ b/dsf-maven/dsf-maven-plugin/pom.xml @@ -26,7 +26,7 @@ dev.dsf dsf-maven-pom - 2.1.0 + 2.1.1-SNAPSHOT diff --git a/dsf-maven/pom.xml b/dsf-maven/pom.xml index d25a615d1..79adadeee 100644 --- a/dsf-maven/pom.xml +++ b/dsf-maven/pom.xml @@ -26,7 +26,7 @@ dev.dsf dsf-pom - 2.1.0 + 2.1.1-SNAPSHOT diff --git a/pom.xml b/pom.xml index 60d592342..192534769 100755 --- a/pom.xml +++ b/pom.xml @@ -20,7 +20,7 @@ dev.dsf dsf-pom - 2.1.0 + 2.1.1-SNAPSHOT pom From c918b95dcd206f24891ccc003d0c9e51a3d3c10f Mon Sep 17 00:00:00 2001 From: Hauke Hund Date: Wed, 29 Jul 2026 12:19:26 +0200 Subject: [PATCH 02/11] backport from develop * java, maven plugin, docker, docker-compose, github actions version upgrades * dev setup network and nginx config * missing license header --- .github/workflows/build.yml | 44 ++++---- .trivyignore | 16 +++ .../dsf-bpe-server-jetty/docker/Dockerfile | 4 +- .../docker-compose.yml | 100 ++++++++++++++---- .../proxy/conf.d/dic1.conf | 2 +- .../proxy/conf.d/dic2.conf | 4 +- .../proxy/conf.d/dic3.conf | 4 +- .../proxy/conf.d/localhost.conf | 28 +++++ .../proxy/conf.d/ttp.conf | 4 +- .../proxy/index.html | 91 ++++++++++++++++ .../proxy/nginx.conf | 4 +- dsf-docker/bpe_proxy/Dockerfile | 2 +- dsf-docker/fhir_proxy/Dockerfile | 2 +- .../dsf-fhir-server-jetty/docker/Dockerfile | 4 +- pom.xml | 33 +++--- 15 files changed, 265 insertions(+), 77 deletions(-) create mode 100644 dsf-docker-dev-setup-3dic-ttp/proxy/conf.d/localhost.conf create mode 100644 dsf-docker-dev-setup-3dic-ttp/proxy/index.html diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 91958b916..39fa386f5 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -42,16 +42,16 @@ jobs: name: 'codeql: ${{ matrix.language }}' steps: - name: Checkout repository - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Set up JDK 25 if: ${{ matrix.language == 'java-kotlin' }} - uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0 + uses: actions/setup-java@03ad4de0992f5dab5e18fcb136590ce7c4a0ac95 # v5.6.0 with: distribution: 'zulu' java-version: 25 cache: 'maven' - name: Initialize CodeQL - uses: github/codeql-action/init@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4.35.2 + uses: github/codeql-action/init@e4fba868fa4b1b91e1fdab776edc8cfbe6e9fb81 # v4.37.3 with: languages: ${{ matrix.language }} build-mode: ${{ matrix.build-mode }} @@ -60,7 +60,7 @@ jobs: if: ${{ matrix.language == 'java-kotlin' }} run: mvn package $MVN_BATCH_MODE_FAIL_AT_END $MVN_SKIP_MOST -DskipTests - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4.35.2 + uses: github/codeql-action/analyze@e4fba868fa4b1b91e1fdab776edc8cfbe6e9fb81 # v4.37.3 with: category: "/language:${{matrix.language}}" @@ -73,9 +73,9 @@ jobs: main: ${{ steps.main.outputs.main }} steps: - name: Checkout repository - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Set up JDK 25 - uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0 + uses: actions/setup-java@03ad4de0992f5dab5e18fcb136590ce7c4a0ac95 # v5.6.0 with: distribution: 'zulu' java-version: 25 @@ -106,7 +106,7 @@ jobs: id: version run: echo "version=$(mvn -q -Dexec.executable=echo -Dexec.args='${project.version}' --non-recursive org.codehaus.mojo:exec-maven-plugin:3.6.3:exec)" >> $GITHUB_OUTPUT - name: Checkout main branch - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: ref: main - name: Check if ref is main HEAD @@ -142,14 +142,14 @@ jobs: timeout-minutes: 8 steps: - name: Checkout repository - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Download quick-build results uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: name: quick_build path: ./ - name: Set up JDK 25 - uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0 + uses: actions/setup-java@03ad4de0992f5dab5e18fcb136590ce7c4a0ac95 # v5.6.0 with: distribution: 'zulu' java-version: 25 @@ -178,25 +178,25 @@ jobs: name: 'trivy: ${{ matrix.image.name }}' steps: - name: Checkout repository - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Download quick-build results uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: name: quick_build path: ./ - name: Set up Buildx - uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0 + uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0 - name: Build Docker image run: docker build -t ghcr.io/${{ github.repository_owner }}/${{ matrix.image.name }}:${{ github.sha }} ${{ matrix.image.context }} - name: Scan Docker image with Trivy - uses: aquasecurity/trivy-action@57a97c7e7821a5776cebc9bb87c984fa69cba8f1 # v0.35.0 + uses: aquasecurity/trivy-action@ed142fd0673e97e23eac54620cfb913e5ce36c25 # v0.36.0 with: image-ref: ghcr.io/${{ github.repository_owner }}/${{ matrix.image.name }}:${{ github.sha }} format: 'sarif' output: 'trivy-results-${{ matrix.image.name }}.sarif' trivyignores: './.trivyignore' - name: Upload Trivy scan results to GitHub Security tab - uses: github/codeql-action/upload-sarif@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4.35.2 + uses: github/codeql-action/upload-sarif@e4fba868fa4b1b91e1fdab776edc8cfbe6e9fb81 # v4.37.3 if: always() with: sarif_file: 'trivy-results-${{ matrix.image.name }}.sarif' @@ -225,24 +225,24 @@ jobs: name: 'docker-deploy: ${{ matrix.image.name }}' steps: - name: Checkout repository - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Download quick-build results uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: name: quick_build path: ./ - name: Set up QEMU - uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a # v4.0.0 + uses: docker/setup-qemu-action@96fe6ef7f33517b61c61be40b68a1882f3264fb8 # v4.2.0 - name: Set up Buildx - uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0 + uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0 - name: Login to GitHub Container Registry - uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0 + uses: docker/login-action@371161bbe7024a29a25c5e19bfcbc0804fe9ad2c # v4.5.2 with: registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Docker metadata - uses: docker/metadata-action@030e881283bb7a6894de51c315a6bfe6a94e05cf # v6.0.0 + uses: docker/metadata-action@dc802804100637a589fabce1cb79ff13a1411302 # v6.2.0 id: meta with: images: ghcr.io/${{ github.repository_owner }}/${{ matrix.image.name }} @@ -257,7 +257,7 @@ jobs: # latest only for stable releases # develop builds - name: Build and Push - uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f # v7.1.0 + uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7.3.0 id: push with: push: true @@ -273,7 +273,7 @@ jobs: - name: Generate SBOM run: syft ghcr.io/${{ github.repository_owner }}/${{ matrix.image.name }}@${DIGEST} -o cyclonedx-json > sbom.json - name: Set up cosign - uses: sigstore/cosign-installer@cad07c2e89fa2edd6e2d7bab4c1aa38e53f76003 # v4.1.1 + uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6 # v4.1.2 - name: Attach SBOM run: cosign attest --yes --predicate sbom.json --type cyclonedx ghcr.io/${{ github.repository_owner }}/${{ matrix.image.name }}@${DIGEST} - name: Sign image @@ -287,14 +287,14 @@ jobs: contents: read steps: - name: Checkout repository - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Download quick-build results uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: name: quick_build path: ./ - name: Set up JDK 25 - uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0 + uses: actions/setup-java@03ad4de0992f5dab5e18fcb136590ce7c4a0ac95 # v5.6.0 with: distribution: 'zulu' java-version: 25 diff --git a/.trivyignore b/.trivyignore index 1e04d74d0..0cd739a94 100644 --- a/.trivyignore +++ b/.trivyignore @@ -1,3 +1,19 @@ +# +# Copyright 2018-2025 Heilbronn University of Applied Sciences +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + # Ignore reason: Vulnerable code not used in DSF # CVE title: FHIR Validator HTTP service has SSRF via /loadIG Chains with startsWith() Credential Leak for Authentication Token Theft CVE-2026-34361 diff --git a/dsf-bpe/dsf-bpe-server-jetty/docker/Dockerfile b/dsf-bpe/dsf-bpe-server-jetty/docker/Dockerfile index 725bfa58f..fc0d51a23 100755 --- a/dsf-bpe/dsf-bpe-server-jetty/docker/Dockerfile +++ b/dsf-bpe/dsf-bpe-server-jetty/docker/Dockerfile @@ -14,7 +14,7 @@ # limitations under the License. # -FROM debian:trixie-slim@sha256:4ffb3a1511099754cddc70eb1b12e50ffdb67619aa0ab6c13fcd800a78ef7c7a AS builder +FROM docker.io/library/debian:trixie-slim@sha256:020c0d20b9880058cbe785a9db107156c3c75c2ac944a6aa7ab59f2add76a7bd AS builder WORKDIR /opt/bpe COPY --chown=root:2202 ./ ./ RUN chown root:2202 ./ && \ @@ -23,7 +23,7 @@ RUN chown root:2202 ./ && \ chmod 1775 ./log -FROM azul/zulu-openjdk:25-jre-headless@sha256:9a30f9ac9b51aba2f0ee76daf6440c03d59a7690b4fd6070e85fba1da9fd32ff +FROM docker.io/azul/zulu-openjdk:25-jre-headless@sha256:44df5eb4a2055e85fff47cb5c6bd4edca4045210a1b05beecd8114822e2f2cdd LABEL org.opencontainers.image.source=https://github.com/datasharingframework/dsf LABEL org.opencontainers.image.description="DSF BPE Server" LABEL org.opencontainers.image.licenses="Apache License, Version 2.0" diff --git a/dsf-docker-dev-setup-3dic-ttp/docker-compose.yml b/dsf-docker-dev-setup-3dic-ttp/docker-compose.yml index 3cd1ac2b8..6f53d56dd 100644 --- a/dsf-docker-dev-setup-3dic-ttp/docker-compose.yml +++ b/dsf-docker-dev-setup-3dic-ttp/docker-compose.yml @@ -16,7 +16,7 @@ services: proxy: - image: nginx:1.29 + image: nginx:1.31 restart: "no" ports: - 127.0.0.1:443:443 @@ -34,23 +34,27 @@ services: source: ./proxy/nginx.conf target: /etc/nginx/nginx.conf read_only: true + - type: bind + source: ./proxy/index.html + target: /usr/share/nginx/html/index.html + read_only: true networks: dic1-fhir-frontend: ipv4_address: 172.20.0.2 dic2-fhir-frontend: - ipv4_address: 172.20.0.10 - dic3-fhir-frontend: ipv4_address: 172.20.0.18 + dic3-fhir-frontend: + ipv4_address: 172.20.0.34 ttp-fhir-frontend: - ipv4_address: 172.20.0.26 + ipv4_address: 172.20.0.50 dic1-bpe-frontend: - ipv4_address: 172.20.0.34 + ipv4_address: 172.20.0.66 dic2-bpe-frontend: - ipv4_address: 172.20.0.42 + ipv4_address: 172.20.0.82 dic3-bpe-frontend: - ipv4_address: 172.20.0.50 + ipv4_address: 172.20.0.98 ttp-bpe-frontend: - ipv4_address: 172.20.0.58 + ipv4_address: 172.20.0.114 internet: aliases: - dic1 @@ -94,7 +98,7 @@ services: read_only: true keycloak: - image: quay.io/keycloak/keycloak:26.3 + image: quay.io/keycloak/keycloak:26.7 restart: "no" ports: - 127.0.0.1:8443:8443 @@ -290,7 +294,7 @@ services: DEV_DSF_SERVER_AUTH_OIDC_CLIENT_SECRET_FILE: /run/secrets/oidc_client_dic2_fhir.secret networks: dic2-fhir-frontend: - ipv4_address: 172.20.0.11 + ipv4_address: 172.20.0.19 dic2-fhir-backend: internet: depends_on: @@ -369,7 +373,7 @@ services: DEV_DSF_SERVER_AUTH_OIDC_CLIENT_SECRET_FILE: /run/secrets/oidc_client_dic3_fhir.secret networks: dic3-fhir-frontend: - ipv4_address: 172.20.0.19 + ipv4_address: 172.20.0.35 dic3-fhir-backend: internet: depends_on: @@ -456,7 +460,7 @@ services: DEV_DSF_SERVER_AUTH_OIDC_CLIENT_SECRET_FILE: /run/secrets/oidc_client_ttp_fhir.secret networks: ttp-fhir-frontend: - ipv4_address: 172.20.0.27 + ipv4_address: 172.20.0.51 ttp-fhir-backend: internet: depends_on: @@ -573,7 +577,7 @@ services: DEV_DSF_BPE_FHIR_CLIENT_CONNECTIONS_CONFIG_DEFAULT_TRUST_SERVER_CERTIFICATE_CAS: /run/secrets/root_ca.crt networks: dic1-bpe-frontend: - ipv4_address: 172.20.0.35 + ipv4_address: 172.20.0.67 dic1-bpe-backend: internet: forward-proxy: @@ -664,7 +668,7 @@ services: DEV_DSF_SERVER_AUTH_OIDC_CLIENT_SECRET_FILE: /run/secrets/oidc_client_dic2_bpe.secret networks: dic2-bpe-frontend: - ipv4_address: 172.20.0.43 + ipv4_address: 172.20.0.83 dic2-bpe-backend: internet: depends_on: @@ -753,7 +757,7 @@ services: DEV_DSF_SERVER_AUTH_OIDC_CLIENT_SECRET_FILE: /run/secrets/oidc_client_dic3_bpe.secret networks: dic3-bpe-frontend: - ipv4_address: 172.20.0.51 + ipv4_address: 172.20.0.99 dic3-bpe-backend: internet: depends_on: @@ -843,7 +847,7 @@ services: DEV_DSF_SERVER_AUTH_OIDC_CLIENT_SECRET_FILE: /run/secrets/oidc_client_ttp_bpe.secret networks: ttp-bpe-frontend: - ipv4_address: 172.20.0.59 + ipv4_address: 172.20.0.115 ttp-bpe-backend: internet: depends_on: @@ -964,57 +968,107 @@ networks: config: - subnet: 172.20.0.0/29 dic1-fhir-backend: - dic2-fhir-frontend: driver: bridge ipam: driver: default config: - subnet: 172.20.0.8/29 + dic2-fhir-frontend: + driver: bridge + ipam: + driver: default + config: + - subnet: 172.20.0.16/29 dic2-fhir-backend: + driver: bridge + ipam: + driver: default + config: + - subnet: 172.20.0.24/29 dic3-fhir-frontend: driver: bridge ipam: driver: default config: - - subnet: 172.20.0.16/29 + - subnet: 172.20.0.32/29 dic3-fhir-backend: + driver: bridge + ipam: + driver: default + config: + - subnet: 172.20.0.40/29 ttp-fhir-frontend: driver: bridge ipam: driver: default config: - - subnet: 172.20.0.24/29 + - subnet: 172.20.0.48/29 ttp-fhir-backend: + driver: bridge + ipam: + driver: default + config: + - subnet: 172.20.0.56/29 dic1-bpe-frontend: driver: bridge ipam: driver: default config: - - subnet: 172.20.0.32/29 + - subnet: 172.20.0.64/29 dic1-bpe-backend: + driver: bridge + ipam: + driver: default + config: + - subnet: 172.20.0.72/29 dic2-bpe-frontend: driver: bridge ipam: driver: default config: - - subnet: 172.20.0.40/29 + - subnet: 172.20.0.80/29 dic2-bpe-backend: + driver: bridge + ipam: + driver: default + config: + - subnet: 172.20.0.88/29 dic3-bpe-frontend: driver: bridge ipam: driver: default config: - - subnet: 172.20.0.48/29 + - subnet: 172.20.0.96/29 dic3-bpe-backend: + driver: bridge + ipam: + driver: default + config: + - subnet: 172.20.0.104/29 ttp-bpe-frontend: driver: bridge ipam: driver: default config: - - subnet: 172.20.0.56/29 + - subnet: 172.20.0.112/29 ttp-bpe-backend: + driver: bridge + ipam: + driver: default + config: + - subnet: 172.20.0.120/29 internet: + driver: bridge + ipam: + driver: default + config: + - subnet: 172.20.0.128/28 forward-proxy: + driver: bridge + ipam: + driver: default + config: + - subnet: 172.20.0.144/29 volumes: postgresql: diff --git a/dsf-docker-dev-setup-3dic-ttp/proxy/conf.d/dic1.conf b/dsf-docker-dev-setup-3dic-ttp/proxy/conf.d/dic1.conf index 0580cae33..e7e86ae66 100644 --- a/dsf-docker-dev-setup-3dic-ttp/proxy/conf.d/dic1.conf +++ b/dsf-docker-dev-setup-3dic-ttp/proxy/conf.d/dic1.conf @@ -38,7 +38,7 @@ server { location /bpe { proxy_set_header X-ClientCert $ssl_client_escaped_cert; - proxy_pass http://172.20.0.35:8080/bpe; + proxy_pass http://172.20.0.67:8080/bpe; proxy_http_version 1.1; proxy_set_header Host $http_host; diff --git a/dsf-docker-dev-setup-3dic-ttp/proxy/conf.d/dic2.conf b/dsf-docker-dev-setup-3dic-ttp/proxy/conf.d/dic2.conf index e7cffb32d..7246c61e8 100644 --- a/dsf-docker-dev-setup-3dic-ttp/proxy/conf.d/dic2.conf +++ b/dsf-docker-dev-setup-3dic-ttp/proxy/conf.d/dic2.conf @@ -22,7 +22,7 @@ server { location /fhir { proxy_set_header X-ClientCert $ssl_client_escaped_cert; - proxy_pass http://172.20.0.11:8080/fhir; + proxy_pass http://172.20.0.19:8080/fhir; proxy_http_version 1.1; proxy_set_header Host $http_host; @@ -38,7 +38,7 @@ server { location /bpe { proxy_set_header X-ClientCert $ssl_client_escaped_cert; - proxy_pass http://172.20.0.43:8080/bpe; + proxy_pass http://172.20.0.83:8080/bpe; proxy_http_version 1.1; proxy_set_header Host $http_host; diff --git a/dsf-docker-dev-setup-3dic-ttp/proxy/conf.d/dic3.conf b/dsf-docker-dev-setup-3dic-ttp/proxy/conf.d/dic3.conf index 2b5668b8a..3b9856925 100644 --- a/dsf-docker-dev-setup-3dic-ttp/proxy/conf.d/dic3.conf +++ b/dsf-docker-dev-setup-3dic-ttp/proxy/conf.d/dic3.conf @@ -22,7 +22,7 @@ server { location /fhir { proxy_set_header X-ClientCert $ssl_client_escaped_cert; - proxy_pass http://172.20.0.19:8080/fhir; + proxy_pass http://172.20.0.35:8080/fhir; proxy_http_version 1.1; proxy_set_header Host $http_host; @@ -38,7 +38,7 @@ server { location /bpe { proxy_set_header X-ClientCert $ssl_client_escaped_cert; - proxy_pass http://172.20.0.51:8080/bpe; + proxy_pass http://172.20.0.99:8080/bpe; proxy_http_version 1.1; proxy_set_header Host $http_host; diff --git a/dsf-docker-dev-setup-3dic-ttp/proxy/conf.d/localhost.conf b/dsf-docker-dev-setup-3dic-ttp/proxy/conf.d/localhost.conf new file mode 100644 index 000000000..0ef58e453 --- /dev/null +++ b/dsf-docker-dev-setup-3dic-ttp/proxy/conf.d/localhost.conf @@ -0,0 +1,28 @@ +# +# Copyright 2018-2025 Heilbronn University of Applied Sciences +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +server { + listen 443 ssl; + listen [::]:443 ssl; + + server_name localhost; + + root /usr/share/nginx/html; + + location / { + try_files /index.html =404; + } +} \ No newline at end of file diff --git a/dsf-docker-dev-setup-3dic-ttp/proxy/conf.d/ttp.conf b/dsf-docker-dev-setup-3dic-ttp/proxy/conf.d/ttp.conf index da3d7d9fc..7fd6b7c49 100644 --- a/dsf-docker-dev-setup-3dic-ttp/proxy/conf.d/ttp.conf +++ b/dsf-docker-dev-setup-3dic-ttp/proxy/conf.d/ttp.conf @@ -22,7 +22,7 @@ server { location /fhir { proxy_set_header X-ClientCert $ssl_client_escaped_cert; - proxy_pass http://172.20.0.27:8080/fhir; + proxy_pass http://172.20.0.51:8080/fhir; proxy_http_version 1.1; proxy_set_header Host $http_host; @@ -38,7 +38,7 @@ server { location /bpe { proxy_set_header X-ClientCert $ssl_client_escaped_cert; - proxy_pass http://172.20.0.59:8080/bpe; + proxy_pass http://172.20.0.115:8080/bpe; proxy_http_version 1.1; proxy_set_header Host $http_host; diff --git a/dsf-docker-dev-setup-3dic-ttp/proxy/index.html b/dsf-docker-dev-setup-3dic-ttp/proxy/index.html new file mode 100644 index 000000000..7676a16f5 --- /dev/null +++ b/dsf-docker-dev-setup-3dic-ttp/proxy/index.html @@ -0,0 +1,91 @@ + + + +localhost + + + +
+image/svg+xml +

3 DIC / TTP Dev Setup

+
+ + + \ No newline at end of file diff --git a/dsf-docker-dev-setup-3dic-ttp/proxy/nginx.conf b/dsf-docker-dev-setup-3dic-ttp/proxy/nginx.conf index 6885c87a0..04fa214ef 100644 --- a/dsf-docker-dev-setup-3dic-ttp/proxy/nginx.conf +++ b/dsf-docker-dev-setup-3dic-ttp/proxy/nginx.conf @@ -28,9 +28,7 @@ http { ssl_certificate /run/secrets/localhost.chain.crt; ssl_certificate_key /run/secrets/localhost.key.plain; - ssl_protocols TLSv1.2 TLSv1.3; - ssl_ciphers TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256; - ssl_prefer_server_ciphers on; + ssl_protocols TLSv1.3; add_header Strict-Transport-Security "max-age=63072000" always; ssl_client_certificate /run/secrets/issuing_ca.crt; diff --git a/dsf-docker/bpe_proxy/Dockerfile b/dsf-docker/bpe_proxy/Dockerfile index 3a2c06070..557f326f8 100644 --- a/dsf-docker/bpe_proxy/Dockerfile +++ b/dsf-docker/bpe_proxy/Dockerfile @@ -14,7 +14,7 @@ # limitations under the License. # -FROM httpd:2.4-alpine@sha256:8f26f33a7002658050e9ab2cd6b77502619dfc89d0a6ba2e9e4a202e0ef04596 +FROM docker.io/library/httpd:2.4-alpine@sha256:1b766f17b84026429b7cb243317b142921b24432336e798bc881c43f45ed9567 LABEL org.opencontainers.image.source=https://github.com/datasharingframework/dsf LABEL org.opencontainers.image.description="DSF BPE Reverse Proxy" LABEL org.opencontainers.image.licenses="Apache License, Version 2.0" diff --git a/dsf-docker/fhir_proxy/Dockerfile b/dsf-docker/fhir_proxy/Dockerfile index 168144f25..750e9f816 100755 --- a/dsf-docker/fhir_proxy/Dockerfile +++ b/dsf-docker/fhir_proxy/Dockerfile @@ -14,7 +14,7 @@ # limitations under the License. # -FROM httpd:2.4-alpine@sha256:8f26f33a7002658050e9ab2cd6b77502619dfc89d0a6ba2e9e4a202e0ef04596 +FROM docker.io/library/httpd:2.4-alpine@sha256:1b766f17b84026429b7cb243317b142921b24432336e798bc881c43f45ed9567 LABEL org.opencontainers.image.source=https://github.com/datasharingframework/dsf LABEL org.opencontainers.image.description="DSF FHIR Reverse Proxy" LABEL org.opencontainers.image.licenses="Apache License, Version 2.0" diff --git a/dsf-fhir/dsf-fhir-server-jetty/docker/Dockerfile b/dsf-fhir/dsf-fhir-server-jetty/docker/Dockerfile index 22d148838..576b73e4d 100755 --- a/dsf-fhir/dsf-fhir-server-jetty/docker/Dockerfile +++ b/dsf-fhir/dsf-fhir-server-jetty/docker/Dockerfile @@ -14,7 +14,7 @@ # limitations under the License. # -FROM debian:trixie-slim@sha256:4ffb3a1511099754cddc70eb1b12e50ffdb67619aa0ab6c13fcd800a78ef7c7a AS builder +FROM docker.io/library/debian:trixie-slim@sha256:020c0d20b9880058cbe785a9db107156c3c75c2ac944a6aa7ab59f2add76a7bd AS builder WORKDIR /opt/fhir COPY --chown=root:2101 ./ ./ RUN chown root:2101 ./ && \ @@ -23,7 +23,7 @@ RUN chown root:2101 ./ && \ chmod 1775 ./log -FROM azul/zulu-openjdk:25-jre-headless@sha256:9a30f9ac9b51aba2f0ee76daf6440c03d59a7690b4fd6070e85fba1da9fd32ff +FROM docker.io/azul/zulu-openjdk:25-jre-headless@sha256:44df5eb4a2055e85fff47cb5c6bd4edca4045210a1b05beecd8114822e2f2cdd LABEL org.opencontainers.image.source=https://github.com/datasharingframework/dsf LABEL org.opencontainers.image.description="DSF FHIR Server" LABEL org.opencontainers.image.licenses="Apache License, Version 2.0" diff --git a/pom.xml b/pom.xml index 192534769..f98d59295 100755 --- a/pom.xml +++ b/pom.xml @@ -39,18 +39,18 @@ ${project.basedir} 2.0.17 - 2.25.4 - 12.1.8 + 2.25.5 + 12.1.10 3.1.11 2.2.2 - 6.2.17 - 2.21.2 + 6.2.19 + 2.21.5 1.1.1 5.1.0 8.4.2 6.5.27 8.4.2 - 1.83 + 1.84 3.8.0 5.2.1 5.2.1 @@ -183,7 +183,7 @@ org.postgresql postgresql - 42.7.10 + 42.7.13 org.checkerframework @@ -453,7 +453,7 @@ org.thymeleaf thymeleaf - 3.1.3.RELEASE + 3.1.5.RELEASE com.nimbusds @@ -542,7 +542,7 @@ org.apache.maven.plugins maven-jar-plugin - 3.5.0 + 3.5.1 @@ -569,12 +569,12 @@ org.apache.maven.plugins maven-surefire-plugin - 3.5.5 + 3.5.6 org.apache.maven.plugins maven-failsafe-plugin - 3.5.5 + 3.5.6 org.apache.maven.plugins @@ -604,7 +604,7 @@ org.apache.maven.plugins maven-dependency-plugin - 3.10.0 + 3.11.0 org.codehaus.mojo @@ -619,17 +619,17 @@ org.apache.maven.plugins maven-enforcer-plugin - 3.6.2 + 3.6.3 org.apache.maven.plugins maven-site-plugin - 3.21.0 + 3.22.0 com.github.spotbugs spotbugs-maven-plugin - 4.9.8.3 + 4.10.3.0 org.apache.maven.plugins @@ -644,7 +644,7 @@ org.sonatype.central central-publishing-maven-plugin - 0.10.0 + 0.11.0 org.apache.maven.plugins @@ -654,7 +654,7 @@ com.mycila license-maven-plugin - 5.0.0 + 5.1.1 org.apache.maven.plugins @@ -1092,6 +1092,7 @@ SCRIPT_STYLE SCRIPT_STYLE SCRIPT_STYLE + SCRIPT_STYLE From 1812d9590e6bce261ee2d7dd99553bdbc4e95a56 Mon Sep 17 00:00:00 2001 From: Reto Wettstein Date: Fri, 29 May 2026 17:28:54 +0200 Subject: [PATCH 03/11] throw bpmn error if translater is applied --- .../v2/activity/MessageSendTaskDelegate.java | 25 +- .../integration/PluginV2IntegrationTest.java | 6 + .../SendTaskErrorBoundaryEventTestThrow.java | 42 ++ .../dsf/bpe/test/spring/config/Config.java | 15 +- .../src/main/resources/bpe/test.bpmn | 510 ++++++++++-------- 5 files changed, 359 insertions(+), 239 deletions(-) create mode 100644 dsf-bpe/dsf-bpe-test-plugin-v2/src/main/java/dev/dsf/bpe/test/message/SendTaskErrorBoundaryEventTestThrow.java diff --git a/dsf-bpe/dsf-bpe-process-api-v2-impl/src/main/java/dev/dsf/bpe/v2/activity/MessageSendTaskDelegate.java b/dsf-bpe/dsf-bpe-process-api-v2-impl/src/main/java/dev/dsf/bpe/v2/activity/MessageSendTaskDelegate.java index 7ac1d3470..fa1e2ed14 100644 --- a/dsf-bpe/dsf-bpe-process-api-v2-impl/src/main/java/dev/dsf/bpe/v2/activity/MessageSendTaskDelegate.java +++ b/dsf-bpe/dsf-bpe-process-api-v2-impl/src/main/java/dev/dsf/bpe/v2/activity/MessageSendTaskDelegate.java @@ -47,13 +47,7 @@ public void execute(DelegateExecution execution) throws Exception // do not stop process execution catch (ErrorBoundaryEvent event) { - MessageSendTaskErrorHandler handler = delegate.getErrorHandler(); - if (handler != null) - event = handler.handleErrorBoundaryEvent(api, variables, event); - - if (event != null) - throw new BpmnError(event.getErrorCode(), event.getErrorMessage(), event); - // else, do nothing if event was absorbed by error handler + handleErrorBoundaryEvent(variables, event); } // stop process execution if exception not absorbed by error handler catch (Exception exception) @@ -62,10 +56,25 @@ public void execute(DelegateExecution execution) throws Exception if (handler != null) exception = handler.handleException(api, variables, sendTaskValues, exception); - if (exception != null) + // do not stop process execution if exception translated to error boundary event + if (exception instanceof ErrorBoundaryEvent event) + handleErrorBoundaryEvent(variables, event); + + else if (exception != null) execution.getProcessEngine().getRuntimeService().deleteProcessInstance(execution.getProcessInstanceId(), exception.getMessage()); // else, do nothing if exception was absorbed by error handler } } + + private void handleErrorBoundaryEvent(Variables variables, ErrorBoundaryEvent event) + { + MessageSendTaskErrorHandler handler = delegate.getErrorHandler(); + if (handler != null) + event = handler.handleErrorBoundaryEvent(api, variables, event); + + // do nothing if event was absorbed by error handler + if (event != null) + throw new BpmnError(event.getErrorCode(), event.getErrorMessage(), event); + } } diff --git a/dsf-bpe/dsf-bpe-server/src/test/java/dev/dsf/bpe/integration/PluginV2IntegrationTest.java b/dsf-bpe/dsf-bpe-server/src/test/java/dev/dsf/bpe/integration/PluginV2IntegrationTest.java index 74751a493..3ce5d2dce 100644 --- a/dsf-bpe/dsf-bpe-server/src/test/java/dev/dsf/bpe/integration/PluginV2IntegrationTest.java +++ b/dsf-bpe/dsf-bpe-server/src/test/java/dev/dsf/bpe/integration/PluginV2IntegrationTest.java @@ -111,6 +111,12 @@ public void startSendTaskTest() throws Exception executePluginTest(createTestTask("SendTaskTest")); } + @Test + public void startSendTaskErrorBoundaryEventTestThrow() throws Exception + { + executePluginTest(createTestTask("SendTaskErrorBoundaryEventTestThrow")); + } + @Test public void startFieldInjectionTest() throws Exception { diff --git a/dsf-bpe/dsf-bpe-test-plugin-v2/src/main/java/dev/dsf/bpe/test/message/SendTaskErrorBoundaryEventTestThrow.java b/dsf-bpe/dsf-bpe-test-plugin-v2/src/main/java/dev/dsf/bpe/test/message/SendTaskErrorBoundaryEventTestThrow.java new file mode 100644 index 000000000..51ef77640 --- /dev/null +++ b/dsf-bpe/dsf-bpe-test-plugin-v2/src/main/java/dev/dsf/bpe/test/message/SendTaskErrorBoundaryEventTestThrow.java @@ -0,0 +1,42 @@ +/* + * Copyright 2018-2025 Heilbronn University of Applied Sciences + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package dev.dsf.bpe.test.message; + +import dev.dsf.bpe.test.AbstractTest; +import dev.dsf.bpe.v2.ProcessPluginApi; +import dev.dsf.bpe.v2.activity.MessageSendTask; +import dev.dsf.bpe.v2.activity.values.SendTaskValues; +import dev.dsf.bpe.v2.error.MessageSendTaskErrorHandler; +import dev.dsf.bpe.v2.error.impl.ExceptionToErrorBoundaryEventTranslationErrorHandler; +import dev.dsf.bpe.v2.variables.Variables; + +public class SendTaskErrorBoundaryEventTestThrow extends AbstractTest implements MessageSendTask +{ + public static final String TEST_ERROR_CODE = "testErrorCode"; + public static final String TEST_ERROR_MESSAGE = "testErrorMessage"; + + @Override + public void execute(ProcessPluginApi api, Variables variables, SendTaskValues sendTask) throws Exception + { + throw new RuntimeException(TEST_ERROR_MESSAGE); + } + + @Override + public MessageSendTaskErrorHandler getErrorHandler() + { + return new ExceptionToErrorBoundaryEventTranslationErrorHandler(_ -> TEST_ERROR_CODE); + } +} diff --git a/dsf-bpe/dsf-bpe-test-plugin-v2/src/main/java/dev/dsf/bpe/test/spring/config/Config.java b/dsf-bpe/dsf-bpe-test-plugin-v2/src/main/java/dev/dsf/bpe/test/spring/config/Config.java index e1577c881..19eb319ac 100644 --- a/dsf-bpe/dsf-bpe-test-plugin-v2/src/main/java/dev/dsf/bpe/test/spring/config/Config.java +++ b/dsf-bpe/dsf-bpe-test-plugin-v2/src/main/java/dev/dsf/bpe/test/spring/config/Config.java @@ -30,6 +30,7 @@ import dev.dsf.bpe.test.listener.StartFieldInjectionTestListener; import dev.dsf.bpe.test.listener.StartSendTaskTestListener; import dev.dsf.bpe.test.message.ContinueSendTestSend; +import dev.dsf.bpe.test.message.SendTaskErrorBoundaryEventTestThrow; import dev.dsf.bpe.test.message.SendTaskTest; import dev.dsf.bpe.test.service.ApiTest; import dev.dsf.bpe.test.service.AutowireTest; @@ -90,13 +91,13 @@ public static ActivityPrototypeBeanCreator activityPrototypeBeanCreator() return new ActivityPrototypeBeanCreator(TestActivitySelector.class, ProxyTest.class, ApiTest.class, OrganizationProviderTest.class, EndpointProviderTest.class, FhirClientProviderTest.class, FhirClientConfigProviderTest.class, StartSendTaskTestListener.class, SendTaskTest.class, - StartFieldInjectionTestListener.class, FieldInjectionTest.class, ErrorBoundaryEventTestThrow.class, - ErrorBoundaryEventTestVerify.class, ExceptionTest.class, CompressionServiceTest.class, - ContinueSendTest.class, ContinueSendTestSend.class, ContinueSendTestEvaluate.class, - JsonVariableTestSet.class, JsonVariableTestGet.class, CryptoServiceTest.class, - MimeTypeServiceTest.class, FhirBinaryVariableTestSet.class, FhirBinaryVariableTestGet.class, - DsfClientTest.class, TargetProviderTest.class, DataLoggerTest.class, AutowireTest.class, - QuestionnaireTestAnswer.class, QuestionnaireTestAnswerCheck.class, + SendTaskErrorBoundaryEventTestThrow.class, StartFieldInjectionTestListener.class, + FieldInjectionTest.class, ErrorBoundaryEventTestThrow.class, ErrorBoundaryEventTestVerify.class, + ExceptionTest.class, CompressionServiceTest.class, ContinueSendTest.class, ContinueSendTestSend.class, + ContinueSendTestEvaluate.class, JsonVariableTestSet.class, JsonVariableTestGet.class, + CryptoServiceTest.class, MimeTypeServiceTest.class, FhirBinaryVariableTestSet.class, + FhirBinaryVariableTestGet.class, DsfClientTest.class, TargetProviderTest.class, DataLoggerTest.class, + AutowireTest.class, QuestionnaireTestAnswer.class, QuestionnaireTestAnswerCheck.class, QuestionnaireTestSetIdentifies.class); } diff --git a/dsf-bpe/dsf-bpe-test-plugin-v2/src/main/resources/bpe/test.bpmn b/dsf-bpe/dsf-bpe-test-plugin-v2/src/main/resources/bpe/test.bpmn index 31e3ceee0..038232d5c 100644 --- a/dsf-bpe/dsf-bpe-test-plugin-v2/src/main/resources/bpe/test.bpmn +++ b/dsf-bpe/dsf-bpe-test-plugin-v2/src/main/resources/bpe/test.bpmn @@ -16,7 +16,7 @@ limitations under the License. --> - + Flow_112zq99 @@ -64,6 +64,7 @@ Flow_0paqotx Flow_1wpvvjm Flow_1ih8var + Flow_1gt50du @@ -99,6 +100,7 @@ Flow_1xuklwp Flow_1u24rv8 Flow_0civp0p + Flow_10cr72e Flow_0a1kwg9 @@ -578,6 +580,35 @@ Flow_1ih8var Flow_1mo1h7u + + + + instantiatesCanonicalValue + + + messageNameValue + + + ${testVariable} + + + + Flow_1gt50du + Flow_063u1ol + + + + Flow_1upv70e + Flow_063u1ol + Flow_10cr72e + + + Flow_1upv70e + + + + + @@ -626,92 +657,92 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -719,110 +750,121 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - + - + - + - + + + + - + - - + + + - - + + + - - + + + + + - + - - + + + + + + + + @@ -896,180 +938,180 @@ - - + + - - + + - - + + - - - - + + + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - - + + + - - + + - - - + + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + @@ -1083,162 +1125,182 @@ - - + + - - + + - - - + + + - - + + - - + + - - - + + + - - + + - - + + - - + + - - + + - - + + - - - + + + - - - + + + - - + + - - + + - - + + - - - + + + - - - + + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - - - - - - - - - - - + + - - + + - - - + + + - - + + - - - + + + - - + + - - + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + From 9b260578d1e93c5e5f33c2caed9e9aecbd908091 Mon Sep 17 00:00:00 2001 From: Hauke Hund Date: Wed, 3 Jun 2026 12:08:30 +0200 Subject: [PATCH 04/11] fixed class and constructor visibility Consumers of the TestAssertException should be able to perform instanceof checks, thus the class needs to be public. Only functions in the PluginTestExecutor need to instantiate TestAssertException. --- .../src/main/java/dev/dsf/bpe/test/PluginTestExecutor.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dsf-bpe/dsf-bpe-test-plugin/src/main/java/dev/dsf/bpe/test/PluginTestExecutor.java b/dsf-bpe/dsf-bpe-test-plugin/src/main/java/dev/dsf/bpe/test/PluginTestExecutor.java index 627ce5714..0b4e690c3 100644 --- a/dsf-bpe/dsf-bpe-test-plugin/src/main/java/dev/dsf/bpe/test/PluginTestExecutor.java +++ b/dsf-bpe/dsf-bpe-test-plugin/src/main/java/dev/dsf/bpe/test/PluginTestExecutor.java @@ -31,11 +31,11 @@ public final class PluginTestExecutor { private static final Logger logger = LoggerFactory.getLogger(PluginTestExecutor.class); - private static final class TestAssertException extends RuntimeException + public static final class TestAssertException extends RuntimeException { private static final long serialVersionUID = 1L; - public TestAssertException(String message) + private TestAssertException(String message) { super(message); } From db2f39c3f46974c505e015b0515c285e549abcf7 Mon Sep 17 00:00:00 2001 From: Hauke Hund Date: Wed, 3 Jun 2026 12:22:34 +0200 Subject: [PATCH 05/11] Simplified SendTaskErrorBoundaryEventTestThrow, added missing condition - Set ID of SendTaskErrorBoundaryEventTestThrow send task for easier debugging. - Removed not needed execution listener from SendTaskErrorBoundaryEventTestThrow send task, mandatory profile field now set via constant. - Added missing condition expression to the flow from the exclusive gateway to the SendTaskErrorBoundaryEventTestThrow send task. - Added default flows to the exclusive gateways of the v1 and v2 test BPMNs to catch missing condition expression errors in the future. --- .../src/main/resources/bpe/test.bpmn | 105 ++- .../src/main/resources/bpe/test.bpmn | 825 +++++++++--------- 2 files changed, 479 insertions(+), 451 deletions(-) diff --git a/dsf-bpe/dsf-bpe-test-plugin-v1/src/main/resources/bpe/test.bpmn b/dsf-bpe/dsf-bpe-test-plugin-v1/src/main/resources/bpe/test.bpmn index c506ff46b..e3b6edbff 100644 --- a/dsf-bpe/dsf-bpe-test-plugin-v1/src/main/resources/bpe/test.bpmn +++ b/dsf-bpe/dsf-bpe-test-plugin-v1/src/main/resources/bpe/test.bpmn @@ -16,7 +16,7 @@ limitations under the License. --> - + Flow_112zq99 @@ -37,13 +37,14 @@ Flow_112zq99 Flow_1bqddk1 - + Flow_1bqddk1 Flow_14rzc0j Flow_0iy74da Flow_1h0pa8u Flow_1hhwby8 Flow_0u49lp5 + Flow_04yuv8k @@ -88,106 +89,118 @@ ${testActivity == 'EnvironmentVariableTest'} + + Flow_04yuv8k + + - + - + - + - + - + - + - + - + - + - + + + + - - + + - - - + + + - - + + - - + + - - - + + + - - + + - - + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + + + + + + diff --git a/dsf-bpe/dsf-bpe-test-plugin-v2/src/main/resources/bpe/test.bpmn b/dsf-bpe/dsf-bpe-test-plugin-v2/src/main/resources/bpe/test.bpmn index 038232d5c..5b5cf6346 100644 --- a/dsf-bpe/dsf-bpe-test-plugin-v2/src/main/resources/bpe/test.bpmn +++ b/dsf-bpe/dsf-bpe-test-plugin-v2/src/main/resources/bpe/test.bpmn @@ -16,7 +16,7 @@ limitations under the License. --> - + Flow_112zq99 @@ -37,7 +37,7 @@ Flow_112zq99 Flow_1bqddk1 - + Flow_1bqddk1 Flow_14rzc0j Flow_0iy74da @@ -65,6 +65,7 @@ Flow_1wpvvjm Flow_1ih8var Flow_1gt50du + Flow_1phdcxi @@ -580,7 +581,7 @@ Flow_1ih8var Flow_1mo1h7u - + instantiatesCanonicalValue @@ -589,718 +590,732 @@ messageNameValue - ${testVariable} + profileValue - Flow_1gt50du Flow_063u1ol - + + ${testActivity == 'SendTaskErrorBoundaryEventTestThrow'} + Flow_1upv70e Flow_063u1ol Flow_10cr72e - + Flow_1upv70e - + + + + Flow_1phdcxi + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + + + + - + - + - + - + - + - + - - - - - - - - - - - + + - - - - - - - + + - - + + + + + + + + + + + + - - + + - - - - + + + - - - - + + + + - - - - - - - - + + + - - - - - - - - + + + - - - - - - - - + + + - - - + + + - - - - + + + + - - - + + + + - - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - + + + + - - - + + + + - - - + + + + - - - - + + + + - - - + + + + - - - - + + + + - - - - + + + + - - - + + + + - - - - + + + + - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + + + + + + - - - + + + - - - - - - - - + + + - - - + + + - - - - + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - + + + + + + + - - - + + + - - - - - - - - - - - - + + - - + + - - + + - - - + + + - - - + + + - - + + - - + + - - + + - - - + + + - - - + + + - - - - - - - - - - - - - - - - - - - - - - + + - - + + - - + + - - + + + + + + - - + + - - - + + + - - + + - - - + + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - + + - - - - + + + + + From ac28656ef53fd560451632c68107d7dca51ac237 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mathias=20R=C3=BChle?= Date: Thu, 2 Jul 2026 15:18:54 +0200 Subject: [PATCH 06/11] Fix check for unsupported JWKS algorithm --- .../src/main/java/dev/dsf/bpe/client/oidc/OidcClientJersey.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dsf-bpe/dsf-bpe-server/src/main/java/dev/dsf/bpe/client/oidc/OidcClientJersey.java b/dsf-bpe/dsf-bpe-server/src/main/java/dev/dsf/bpe/client/oidc/OidcClientJersey.java index 513d8597e..999eb82d5 100644 --- a/dsf-bpe/dsf-bpe-server/src/main/java/dev/dsf/bpe/client/oidc/OidcClientJersey.java +++ b/dsf-bpe/dsf-bpe-server/src/main/java/dev/dsf/bpe/client/oidc/OidcClientJersey.java @@ -184,7 +184,7 @@ private DecodedJWT verifyAndDecodeAccessToken(String accessToken, Jwks jwks) thr throw new OidcClientException("Access token key with kid '" + keyId + "' and use 'sig' not in JWKS"); Optional algorithm = key.flatMap(JwksKey::toAlgorithm); - if (key.isEmpty()) + if (algorithm.isEmpty()) { throw new OidcClientException("Access token key with kid '" + keyId + "' has unsupported type (kty) / algorithm (alg) / key-size in JWKS"); From 760c595848bf895ae84305324e693cd9f72e3a42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mathias=20R=C3=BChle?= Date: Fri, 3 Jul 2026 00:09:39 +0200 Subject: [PATCH 07/11] URL-encode client id and client secret for Basic Auth RFC 6749 requires the client id and client secret to be url encoded first when using HTTP Basic authentication scheme. see https://datatracker.ietf.org/doc/html/rfc6749#section-2.3.1 --- .../dsf/bpe/client/oidc/OidcClientJersey.java | 8 +- .../bpe/client/oidc/OidcClientJerseyTest.java | 127 +++++++++++++++++- 2 files changed, 129 insertions(+), 6 deletions(-) diff --git a/dsf-bpe/dsf-bpe-server/src/main/java/dev/dsf/bpe/client/oidc/OidcClientJersey.java b/dsf-bpe/dsf-bpe-server/src/main/java/dev/dsf/bpe/client/oidc/OidcClientJersey.java index 999eb82d5..67cf802d8 100644 --- a/dsf-bpe/dsf-bpe-server/src/main/java/dev/dsf/bpe/client/oidc/OidcClientJersey.java +++ b/dsf-bpe/dsf-bpe-server/src/main/java/dev/dsf/bpe/client/oidc/OidcClientJersey.java @@ -15,6 +15,7 @@ */ package dev.dsf.bpe.client.oidc; +import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import java.security.KeyStore; import java.time.Duration; @@ -151,9 +152,10 @@ public DecodedJWT getAccessTokenDecoded(OidcConfiguration configuration, Jwks jw Response response = client.target(tokenEndpoint).request(MediaType.APPLICATION_JSON_TYPE) .header(HttpHeaders.AUTHORIZATION, - "Basic " + Base64.getEncoder() - .encodeToString(new StringBuilder().append(clientId).append(':').append(clientSecret) - .toString().getBytes(StandardCharsets.US_ASCII))) + "Basic " + Base64.getEncoder().encodeToString(new StringBuilder() + .append(URLEncoder.encode(clientId, StandardCharsets.US_ASCII)).append(':') + .append(URLEncoder.encode(String.valueOf(clientSecret), StandardCharsets.US_ASCII)) + .toString().getBytes(StandardCharsets.US_ASCII))) .post(Entity.form(new Form().param("grant_type", "client_credentials"))); if (response.getStatus() == Status.OK.getStatusCode()) diff --git a/dsf-bpe/dsf-bpe-server/src/test/java/dev/dsf/bpe/client/oidc/OidcClientJerseyTest.java b/dsf-bpe/dsf-bpe-server/src/test/java/dev/dsf/bpe/client/oidc/OidcClientJerseyTest.java index e9f6360bf..34954bada 100644 --- a/dsf-bpe/dsf-bpe-server/src/test/java/dev/dsf/bpe/client/oidc/OidcClientJerseyTest.java +++ b/dsf-bpe/dsf-bpe-server/src/test/java/dev/dsf/bpe/client/oidc/OidcClientJerseyTest.java @@ -15,22 +15,51 @@ */ package dev.dsf.bpe.client.oidc; +import static java.nio.charset.StandardCharsets.US_ASCII; + +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertThrows; +import java.io.IOException; +import java.io.OutputStream; +import java.net.InetSocketAddress; +import java.net.URLEncoder; import java.nio.file.Paths; import java.security.KeyStore; import java.time.Duration; +import java.util.Base64; +import java.util.List; +import java.util.Set; import org.junit.Ignore; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExternalResource; + +import com.sun.net.httpserver.HttpsConfigurator; +import com.sun.net.httpserver.HttpsServer; +import de.hsheilbronn.mi.utils.crypto.context.SSLContextFactory; import de.hsheilbronn.mi.utils.crypto.io.PemReader; import de.hsheilbronn.mi.utils.crypto.keystore.KeyStoreCreator; +import dev.dsf.bpe.api.client.oidc.OidcClientException; +import dev.dsf.bpe.integration.X509Certificates; +import dev.dsf.common.oidc.Jwks; +import dev.dsf.common.oidc.OidcConfiguration; +import jakarta.ws.rs.core.HttpHeaders; -@Ignore -// Needs keycloak service from 3dic-ttp dev setup, "Service accounts roles" needs to be activated for dic1-fhir client public class OidcClientJerseyTest { + @Rule + public final X509Certificates certificates = new X509Certificates(); + + @Rule + public final TokenEndpointServerResource tokenEndpointServerResource = new TokenEndpointServerResource(); + + // Needs keycloak service from 3dic-ttp dev setup, "Service accounts roles" needs to be activated for dic1-fhir + // client + @Ignore @Test public void getAccessToken() throws Exception { @@ -45,4 +74,96 @@ public void getAccessToken() throws Exception char[] accessToken = client.asOidcClientWithDecodedJwt().getAccessToken(); assertNotNull(accessToken); } -} \ No newline at end of file + + @Test + public void basicAuthorizationClientIdAndSecretShouldBeUrlEncoded() throws Exception + { + var clientId = "client/id:+"; + var clientSecret = "client/secret:+"; + var expectedAuthorizationHeaderValue = "Basic ".concat(clientId.transform(id -> URLEncoder.encode(id, US_ASCII)) + .concat(":").concat(clientSecret.transform(secret -> URLEncoder.encode(secret, US_ASCII))) + .transform(s -> Base64.getEncoder().encodeToString(s.getBytes(US_ASCII)))); + var client = new OidcClientJersey("https://localhost:" + tokenEndpointServerResource.getPort(), + "/.well-known/openid-configuration", clientId, clientSecret.toCharArray(), + certificates.getFhirServerCertificate().trustStore(), null, null, null, null, null, "Test Client", + Duration.ofSeconds(10), Duration.ofSeconds(5), true, Duration.ofSeconds(10), null, false); + var config = new OidcConfiguration("https://localhost:" + tokenEndpointServerResource.getPort(), + "https://localhost:" + tokenEndpointServerResource.getPort() + "/token", "https://localhost/jwks", + Set.of("client_credentials")); + + // token is intentionally invalid as it is not the focus of this test + // and to simplify test code + assertThrows(OidcClientException.class, () -> client.getAccessTokenDecoded(config, new Jwks(List.of()))); + + assertEquals(expectedAuthorizationHeaderValue, tokenEndpointServerResource.getAuthorizationHeaderValue()); + } + + private class TokenEndpointServerResource extends ExternalResource + { + private HttpsServer server; + private String authorizationHeaderValue; + + @Override + protected void before() throws Throwable + { + // Server will be created lazily when getPort() is first called + } + + @Override + protected void after() + { + if (server != null) + { + server.stop(0); + } + } + + int getPort() throws Exception + { + if (server == null) + { + server = createServer(); + server.start(); + } + return server.getAddress().getPort(); + } + + String getAuthorizationHeaderValue() + { + return authorizationHeaderValue; + } + + private HttpsServer createServer() throws Exception + { + var newServer = HttpsServer.create(new InetSocketAddress("localhost", 0), 0); + var serverCertificate = certificates.getFhirServerCertificate(); + + var keyStorePassword = "server-password".toCharArray(); + KeyStore keyStore = KeyStoreCreator.jksForPrivateKeyAndCertificateChain(serverCertificate.privateKey(), + keyStorePassword, serverCertificate.certificate(), serverCertificate.caCertificate()); + + newServer.setHttpsConfigurator( + new HttpsConfigurator(SSLContextFactory.createSSLContext(null, keyStore, keyStorePassword, "TLS"))); + + newServer.createContext("/token", exchange -> + { + authorizationHeaderValue = exchange.getRequestHeaders().getFirst(HttpHeaders.AUTHORIZATION); + + byte[] response = "{\"access_token\":\"invalid\",\"expires_in\":300}".getBytes(US_ASCII); + exchange.getResponseHeaders().set(HttpHeaders.CONTENT_TYPE, "application/json"); + exchange.sendResponseHeaders(200, response.length); + try (OutputStream out = exchange.getResponseBody()) + { + out.write(response); + } + catch (IOException e) + { + throw new RuntimeException(e); + } + exchange.close(); + }); + + return newServer; + } + } +} From b62f60bda30e407d3af2bf23dddfa4a7b0f7e175 Mon Sep 17 00:00:00 2001 From: Hauke Hund Date: Sat, 4 Jul 2026 16:03:43 +0200 Subject: [PATCH 08/11] Fixed encoding as defined in RFC 6749 - Appendix B -> UTF-8 --- .../dsf/bpe/client/oidc/OidcClientJersey.java | 9 ++-- .../bpe/client/oidc/OidcClientJerseyTest.java | 47 +++++++++++++++---- 2 files changed, 42 insertions(+), 14 deletions(-) diff --git a/dsf-bpe/dsf-bpe-server/src/main/java/dev/dsf/bpe/client/oidc/OidcClientJersey.java b/dsf-bpe/dsf-bpe-server/src/main/java/dev/dsf/bpe/client/oidc/OidcClientJersey.java index 67cf802d8..7f96d9c16 100644 --- a/dsf-bpe/dsf-bpe-server/src/main/java/dev/dsf/bpe/client/oidc/OidcClientJersey.java +++ b/dsf-bpe/dsf-bpe-server/src/main/java/dev/dsf/bpe/client/oidc/OidcClientJersey.java @@ -152,10 +152,11 @@ public DecodedJWT getAccessTokenDecoded(OidcConfiguration configuration, Jwks jw Response response = client.target(tokenEndpoint).request(MediaType.APPLICATION_JSON_TYPE) .header(HttpHeaders.AUTHORIZATION, - "Basic " + Base64.getEncoder().encodeToString(new StringBuilder() - .append(URLEncoder.encode(clientId, StandardCharsets.US_ASCII)).append(':') - .append(URLEncoder.encode(String.valueOf(clientSecret), StandardCharsets.US_ASCII)) - .toString().getBytes(StandardCharsets.US_ASCII))) + "Basic " + Base64.getEncoder() + .encodeToString(new StringBuilder() + .append(URLEncoder.encode(clientId, StandardCharsets.UTF_8)).append(':') + .append(URLEncoder.encode(String.valueOf(clientSecret), StandardCharsets.UTF_8)) + .toString().getBytes(StandardCharsets.UTF_8))) .post(Entity.form(new Form().param("grant_type", "client_credentials"))); if (response.getStatus() == Status.OK.getStatusCode()) diff --git a/dsf-bpe/dsf-bpe-server/src/test/java/dev/dsf/bpe/client/oidc/OidcClientJerseyTest.java b/dsf-bpe/dsf-bpe-server/src/test/java/dev/dsf/bpe/client/oidc/OidcClientJerseyTest.java index 34954bada..573879205 100644 --- a/dsf-bpe/dsf-bpe-server/src/test/java/dev/dsf/bpe/client/oidc/OidcClientJerseyTest.java +++ b/dsf-bpe/dsf-bpe-server/src/test/java/dev/dsf/bpe/client/oidc/OidcClientJerseyTest.java @@ -15,16 +15,13 @@ */ package dev.dsf.bpe.client.oidc; -import static java.nio.charset.StandardCharsets.US_ASCII; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertThrows; +import static org.junit.Assert.*; import java.io.IOException; import java.io.OutputStream; import java.net.InetSocketAddress; import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; import java.nio.file.Paths; import java.security.KeyStore; import java.time.Duration; @@ -79,10 +76,11 @@ public void getAccessToken() throws Exception public void basicAuthorizationClientIdAndSecretShouldBeUrlEncoded() throws Exception { var clientId = "client/id:+"; - var clientSecret = "client/secret:+"; - var expectedAuthorizationHeaderValue = "Basic ".concat(clientId.transform(id -> URLEncoder.encode(id, US_ASCII)) - .concat(":").concat(clientSecret.transform(secret -> URLEncoder.encode(secret, US_ASCII))) - .transform(s -> Base64.getEncoder().encodeToString(s.getBytes(US_ASCII)))); + var clientSecret = "client/s€cr€t:+"; + var expectedAuthorizationHeaderValue = "Basic " + .concat(clientId.transform(id -> URLEncoder.encode(id, StandardCharsets.UTF_8)).concat(":") + .concat(clientSecret.transform(secret -> URLEncoder.encode(secret, StandardCharsets.UTF_8))) + .transform(s -> Base64.getEncoder().encodeToString(s.getBytes(StandardCharsets.UTF_8)))); var client = new OidcClientJersey("https://localhost:" + tokenEndpointServerResource.getPort(), "/.well-known/openid-configuration", clientId, clientSecret.toCharArray(), certificates.getFhirServerCertificate().trustStore(), null, null, null, null, null, "Test Client", @@ -149,7 +147,7 @@ private HttpsServer createServer() throws Exception { authorizationHeaderValue = exchange.getRequestHeaders().getFirst(HttpHeaders.AUTHORIZATION); - byte[] response = "{\"access_token\":\"invalid\",\"expires_in\":300}".getBytes(US_ASCII); + byte[] response = "{\"access_token\":\"invalid\",\"expires_in\":300}".getBytes(StandardCharsets.UTF_8); exchange.getResponseHeaders().set(HttpHeaders.CONTENT_TYPE, "application/json"); exchange.sendResponseHeaders(200, response.length); try (OutputStream out = exchange.getResponseBody()) @@ -166,4 +164,33 @@ private HttpsServer createServer() throws Exception return newServer; } } + + @Test + public void testEncoding() throws Exception + { + /* + * RFC 6749, Appendix B - https://datatracker.ietf.org/doc/html/rfc6749#appendix-B + * + * [...] + * + * When parsing data from a payload using this media type, the names and values resulting from reversing the + * name/value encoding consequently need to be treated as octet sequences, to be decoded using the UTF-8 + * character encoding scheme. + * + * For example, the value consisting of the six Unicode code points (1) U+0020 (SPACE), (2) U+0025 (PERCENT + * SIGN), (3) U+0026 (AMPERSAND), (4) U+002B (PLUS SIGN), (5) U+00A3 (POUND SIGN), and (6) U+20AC (EURO SIGN) + * would be encoded into the octet sequence below (using hexadecimal notation): + * + * 20 25 26 2B C2 A3 E2 82 AC + * + * and then represented in the payload as: + * + * +%25%26%2B%C2%A3%E2%82%AC + */ + + String example = "\u0020\u0025\u0026\u002B\u00A3\u20AC"; + String expected = "+%25%26%2B%C2%A3%E2%82%AC"; + + assertEquals(expected, URLEncoder.encode(example, StandardCharsets.UTF_8)); + } } From 6d802fa7421ea1751b72cd5d24cb22d00339b9da Mon Sep 17 00:00:00 2001 From: Hauke Hund Date: Tue, 7 Jul 2026 17:57:44 +0200 Subject: [PATCH 09/11] new test to reproduce issue #535 --- .../dev/dsf/bpe/test/service/JsonVariableTestGet.java | 9 +++++++++ .../dev/dsf/bpe/test/service/JsonVariableTestSet.java | 2 ++ 2 files changed, 11 insertions(+) diff --git a/dsf-bpe/dsf-bpe-test-plugin-v2/src/main/java/dev/dsf/bpe/test/service/JsonVariableTestGet.java b/dsf-bpe/dsf-bpe-test-plugin-v2/src/main/java/dev/dsf/bpe/test/service/JsonVariableTestGet.java index 638db9972..7514efebc 100644 --- a/dsf-bpe/dsf-bpe-test-plugin-v2/src/main/java/dev/dsf/bpe/test/service/JsonVariableTestGet.java +++ b/dsf-bpe/dsf-bpe-test-plugin-v2/src/main/java/dev/dsf/bpe/test/service/JsonVariableTestGet.java @@ -16,6 +16,7 @@ package dev.dsf.bpe.test.service; import static dev.dsf.bpe.test.PluginTestExecutor.expectNotNull; +import static dev.dsf.bpe.test.PluginTestExecutor.expectNull; import static dev.dsf.bpe.test.PluginTestExecutor.expectSame; import dev.dsf.bpe.test.AbstractTest; @@ -62,4 +63,12 @@ public void getIntegerVariable(Variables variables) throws Exception expectNotNull(variable); expectSame(JsonVariableTestSet.TEST_INTEGER, variable); } + + @PluginTest + public void getJsonNullVariable(Variables variables) throws Exception + { + JsonPojo variable = variables.getVariable(JsonVariableTestSet.JSON_NULL_VARIABLE); + + expectNull(variable); + } } diff --git a/dsf-bpe/dsf-bpe-test-plugin-v2/src/main/java/dev/dsf/bpe/test/service/JsonVariableTestSet.java b/dsf-bpe/dsf-bpe-test-plugin-v2/src/main/java/dev/dsf/bpe/test/service/JsonVariableTestSet.java index fe0564455..82d2668f6 100644 --- a/dsf-bpe/dsf-bpe-test-plugin-v2/src/main/java/dev/dsf/bpe/test/service/JsonVariableTestSet.java +++ b/dsf-bpe/dsf-bpe-test-plugin-v2/src/main/java/dev/dsf/bpe/test/service/JsonVariableTestSet.java @@ -26,6 +26,7 @@ public class JsonVariableTestSet implements ServiceTask { public static final String JSON_VARIABLE = "json-variable"; + public static final String JSON_NULL_VARIABLE = "json-null-variable"; public static final String STRING_VARIABLE = "string-variable"; public static final String INTEGER_VARIABLE = "integer-variable"; @@ -41,5 +42,6 @@ public void execute(ProcessPluginApi api, Variables variables) throws ErrorBound variables.setJsonVariable(JSON_VARIABLE, new JsonPojo(TEST_VALUE_1, TEST_VALUE_2, TEST_ZONED_DATE_TIME_VALUE)); variables.setString(STRING_VARIABLE, TEST_STRING); variables.setInteger(INTEGER_VARIABLE, TEST_INTEGER); + variables.setJsonVariable(JSON_NULL_VARIABLE, null); } } From 4985d700dbe8d741db20448047f6f4db586e15cf Mon Sep 17 00:00:00 2001 From: Hauke Hund Date: Tue, 7 Jul 2026 18:03:35 +0200 Subject: [PATCH 10/11] special cases for null json values to fix issue #535 --- .../dev/dsf/bpe/v2/variables/JsonHolder.java | 31 +++++++++++++++---- .../v2/variables/JsonHolderSerializer.java | 3 +- .../dsf/bpe/v2/variables/VariablesImpl.java | 11 +++++-- 3 files changed, 36 insertions(+), 9 deletions(-) diff --git a/dsf-bpe/dsf-bpe-process-api-v2-impl/src/main/java/dev/dsf/bpe/v2/variables/JsonHolder.java b/dsf-bpe/dsf-bpe-process-api-v2-impl/src/main/java/dev/dsf/bpe/v2/variables/JsonHolder.java index 92ea7188c..f747eda08 100644 --- a/dsf-bpe/dsf-bpe-process-api-v2-impl/src/main/java/dev/dsf/bpe/v2/variables/JsonHolder.java +++ b/dsf-bpe/dsf-bpe-process-api-v2-impl/src/main/java/dev/dsf/bpe/v2/variables/JsonHolder.java @@ -19,19 +19,33 @@ public class JsonHolder { - private final String dataClassName; - private final byte[] data; - /** * @param dataClassName * not null * @param data * not null + * @return */ - public JsonHolder(String dataClassName, byte[] data) + public static JsonHolder of(String dataClassName, byte[] data) + { + Objects.requireNonNull(dataClassName, "dataClassName"); + Objects.requireNonNull(data, "data"); + + return new JsonHolder(dataClassName, data); + } + + public static JsonHolder empty() + { + return new JsonHolder(null, null); + } + + private final String dataClassName; + private final byte[] data; + + private JsonHolder(String dataClassName, byte[] data) { - this.dataClassName = Objects.requireNonNull(dataClassName, "dataClassName"); - this.data = Objects.requireNonNull(data, "data"); + this.dataClassName = dataClassName; + this.data = data; } public String getDataClassName() @@ -43,4 +57,9 @@ public byte[] getData() { return data; } + + public boolean isEmpty() + { + return dataClassName == null || data == null; + } } diff --git a/dsf-bpe/dsf-bpe-process-api-v2-impl/src/main/java/dev/dsf/bpe/v2/variables/JsonHolderSerializer.java b/dsf-bpe/dsf-bpe-process-api-v2-impl/src/main/java/dev/dsf/bpe/v2/variables/JsonHolderSerializer.java index 12e55449f..45caed302 100644 --- a/dsf-bpe/dsf-bpe-process-api-v2-impl/src/main/java/dev/dsf/bpe/v2/variables/JsonHolderSerializer.java +++ b/dsf-bpe/dsf-bpe-process-api-v2-impl/src/main/java/dev/dsf/bpe/v2/variables/JsonHolderSerializer.java @@ -52,7 +52,8 @@ public JsonHolderValue readValue(ValueFields valueFields, boolean asTransientVal String dataClassName = valueFields.getTextValue(); byte[] data = valueFields.getByteArrayValue(); - return JsonHolderValues.create(new JsonHolder(dataClassName, data)); + return JsonHolderValues.create( + dataClassName == null || data == null ? JsonHolder.empty() : JsonHolder.of(dataClassName, data)); } @Override diff --git a/dsf-bpe/dsf-bpe-process-api-v2-impl/src/main/java/dev/dsf/bpe/v2/variables/VariablesImpl.java b/dsf-bpe/dsf-bpe-process-api-v2-impl/src/main/java/dev/dsf/bpe/v2/variables/VariablesImpl.java index 39b56d71c..f85f9dc65 100644 --- a/dsf-bpe/dsf-bpe-process-api-v2-impl/src/main/java/dev/dsf/bpe/v2/variables/VariablesImpl.java +++ b/dsf-bpe/dsf-bpe-process-api-v2-impl/src/main/java/dev/dsf/bpe/v2/variables/VariablesImpl.java @@ -107,12 +107,15 @@ public VariablesImpl(DelegateExecution execution, ObjectMapper objectMapper, Dsf private JsonHolder toJsonHolder(Object json) { + if (json == null) + return JsonHolder.empty(); + try { byte[] data = objectMapper.writeValueAsBytes(json); String dataClassName = json.getClass().getName(); - return new JsonHolder(dataClassName, data); + return JsonHolder.of(dataClassName, data); } catch (JsonProcessingException e) { @@ -123,11 +126,15 @@ private JsonHolder toJsonHolder(Object json) @SuppressWarnings("unchecked") private T fromJsonHolder(JsonHolder holder) { + if (holder.isEmpty()) + return null; + try { byte[] data = holder.getData(); - Class dataClass = getClassLoader().loadClass(holder.getDataClassName()); + String dataClassName = holder.getDataClassName(); + Class dataClass = getClassLoader().loadClass(dataClassName); return (T) objectMapper.readValue(data, dataClass); } catch (ClassNotFoundException | IOException e) From b6735d64bbf49e7c81b5692ed58454bca268e338 Mon Sep 17 00:00:00 2001 From: Hauke Hund Date: Wed, 22 Jul 2026 13:58:02 +0200 Subject: [PATCH 11/11] fixed bad handling of input values with index 0, some code cleanup --- .../src/main/resources/fhir/static/form.js | 24 +++++++++---------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/static/form.js b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/static/form.js index 0d96348e3..a598a329d 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/static/form.js +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/static/form.js @@ -1108,12 +1108,10 @@ function handlePendingTask() { const count = baseIdCount.get(baseId) || 0 baseIdCount.set(baseId, count + 1) - const suffix = count === 0 ? "" : `|${count}` - if (count > 0) - appendInputRowAfter(baseId) + appendInputRowAfter(`${baseId}|${count - 1}`) - const fullId = (id) => id + suffix + const fullId = (suffix) => `${baseId}|${count}${suffix != null ? `-${suffix}` : ""}` const primitiveValue = values.boolean ?? values.string ?? values.integer ?? @@ -1121,7 +1119,7 @@ function handlePendingTask() { values.dateTime ?? values.instant ?? values.uri if (primitiveValue != null) { - const id = fullId(baseId + (values.boolean !== undefined ? `-${values.boolean}` : "")) + const id = fullId(values.boolean) const input = getInputById(id) @@ -1138,14 +1136,14 @@ function handlePendingTask() { const { reference, identifier } = values.reference if (reference) { - const input = getInputById(fullId(baseId)) + const input = getInputById(fullId()) if (input) input.value = reference } else if (identifier) { const { system, value } = identifier - const inputSystem = getInputById(fullId(baseId + "-system")) - const inputValue = getInputById(fullId(baseId + "-value")) + const inputSystem = getInputById(fullId("system")) + const inputValue = getInputById(fullId("value")) if (inputSystem) inputSystem.value = system if (inputValue) inputValue.value = value @@ -1153,16 +1151,16 @@ function handlePendingTask() { } else if (values.identifier) { const { system, value } = values.identifier - const inputSystem = getInputById(fullId(baseId + "-system")) - const inputValue = getInputById(fullId(baseId + "-value")) + const inputSystem = getInputById(fullId("system")) + const inputValue = getInputById(fullId("value")) if (inputSystem) inputSystem.value = system if (inputValue) inputValue.value = value } else if (values.coding) { const { system, code } = values.coding - const inputSystem = getInputById(fullId(baseId + "-system")) - const inputCode = getInputById(fullId(baseId + "-code")) + const inputSystem = getInputById(fullId("system")) + const inputCode = getInputById(fullId("code")) if (inputSystem) inputSystem.value = system if (inputCode) inputCode.value = code @@ -1173,7 +1171,7 @@ function handlePendingTask() { Object.entries(fields).forEach(([key, val]) => { if (val == null) return - const input = getInputById(fullId(`${baseId}-${key}`)) + const input = getInputById(fullId(key)) if (input) input.value = val }) }