From b7e4936aa53003a02cff08903f206050a109256d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 12 Feb 2024 01:28:21 +0000 Subject: [PATCH 001/100] chore(deps): bump mikefarah/yq from 4.40.5 to 4.40.7 Bumps [mikefarah/yq](https://github.com/mikefarah/yq) from 4.40.5 to 4.40.7. - [Release notes](https://github.com/mikefarah/yq/releases) - [Changelog](https://github.com/mikefarah/yq/blob/master/release_notes.txt) - [Commits](https://github.com/mikefarah/yq/compare/v4.40.5...v4.40.7) --- updated-dependencies: - dependency-name: mikefarah/yq dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/draft-new-release.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/draft-new-release.yaml b/.github/workflows/draft-new-release.yaml index 99e7468e7..20f24c938 100644 --- a/.github/workflows/draft-new-release.yaml +++ b/.github/workflows/draft-new-release.yaml @@ -54,7 +54,7 @@ jobs: GITHUB_PACKAGE_USERNAME: ${{ github.actor }} GITHUB_PACKAGE_PASSWORD: ${{ secrets.GITHUB_TOKEN }} - name: Bump version in /charts - uses: mikefarah/yq@v4.40.5 + uses: mikefarah/yq@v4.40.7 with: cmd: |- find charts -name Chart.yaml -maxdepth 3 | xargs -n1 yq -i '.appVersion = "${{ github.event.inputs.version }}" | .version = "${{ github.event.inputs.version }}"' From 748ba6416e952851c519c9e9686b7eac07394774 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 12 Feb 2024 01:28:25 +0000 Subject: [PATCH 002/100] chore(deps): bump helm/kind-action from 1.8.0 to 1.9.0 Bumps [helm/kind-action](https://github.com/helm/kind-action) from 1.8.0 to 1.9.0. - [Release notes](https://github.com/helm/kind-action/releases) - [Commits](https://github.com/helm/kind-action/compare/v1.8.0...v1.9.0) --- updated-dependencies: - dependency-name: helm/kind-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/upgradeability-test.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/upgradeability-test.yaml b/.github/workflows/upgradeability-test.yaml index ce2015790..003ae0f74 100644 --- a/.github/workflows/upgradeability-test.yaml +++ b/.github/workflows/upgradeability-test.yaml @@ -56,7 +56,7 @@ jobs: version: 'v1.28.2' - name: Create k8s Kind Cluster - uses: helm/kind-action@v1.8.0 + uses: helm/kind-action@v1.9.0 - name: "Update helm repo" run: | From 6f48dc36fea1eb9f7012366c2abf8ac2d9d1a386 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 13 Feb 2024 08:11:48 +0000 Subject: [PATCH 003/100] chore(deps): bump testcontainers from 1.19.4 to 1.19.5 Bumps `testcontainers` from 1.19.4 to 1.19.5. Updates `org.testcontainers:junit-jupiter` from 1.19.4 to 1.19.5 - [Release notes](https://github.com/testcontainers/testcontainers-java/releases) - [Changelog](https://github.com/testcontainers/testcontainers-java/blob/main/CHANGELOG.md) - [Commits](https://github.com/testcontainers/testcontainers-java/compare/1.19.4...1.19.5) Updates `org.testcontainers:postgresql` from 1.19.4 to 1.19.5 - [Release notes](https://github.com/testcontainers/testcontainers-java/releases) - [Changelog](https://github.com/testcontainers/testcontainers-java/blob/main/CHANGELOG.md) - [Commits](https://github.com/testcontainers/testcontainers-java/compare/1.19.4...1.19.5) Updates `org.testcontainers:vault` from 1.19.4 to 1.19.5 - [Release notes](https://github.com/testcontainers/testcontainers-java/releases) - [Changelog](https://github.com/testcontainers/testcontainers-java/blob/main/CHANGELOG.md) - [Commits](https://github.com/testcontainers/testcontainers-java/compare/1.19.4...1.19.5) --- updated-dependencies: - dependency-name: org.testcontainers:junit-jupiter dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.testcontainers:postgresql dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.testcontainers:vault dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index e47d813e2..5e4b58ff1 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -21,7 +21,7 @@ postgres = "42.7.1" restAssured = "5.4.0" rsApi = "3.1.0" slf4j = "2.0.12" -testcontainers = "1.19.4" +testcontainers = "1.19.5" tink = "1.12.0" titanium = "1.3.3" From 87f7807096797a54e08728609b63dde3867a1917 Mon Sep 17 00:00:00 2001 From: Enrico Risa Date: Tue, 13 Feb 2024 09:17:00 +0100 Subject: [PATCH 004/100] chore: dependencies file --- DEPENDENCIES | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/DEPENDENCIES b/DEPENDENCIES index 4ed963509..bc80fa949 100644 --- a/DEPENDENCIES +++ b/DEPENDENCIES @@ -1,4 +1,4 @@ -maven/mavencentral/com.apicatalog/carbon-did/0.0.2, Apache-2.0, approved, #9239 + maven/mavencentral/com.apicatalog/carbon-did/0.0.2, Apache-2.0, approved, #9239 maven/mavencentral/com.apicatalog/iron-ed25519-cryptosuite-2020/0.8.1, Apache-2.0, approved, #11157 maven/mavencentral/com.apicatalog/iron-verifiable-credentials/0.8.1, Apache-2.0, approved, #9234 maven/mavencentral/com.apicatalog/titanium-json-ld/1.0.0, Apache-2.0, approved, clearlydefined @@ -203,6 +203,7 @@ maven/mavencentral/net.minidev/json-smart/2.4.10, Apache-2.0, approved, #3288 maven/mavencentral/net.minidev/json-smart/2.5.0, Apache-2.0, approved, clearlydefined maven/mavencentral/net.sf.saxon/Saxon-HE/12.3, MPL-2.0-no-copyleft-exception AND (LicenseRef-scancode-proprietary-license AND MPL-2.0-no-copyleft-exception) AND (MPL-2.0-no-copyleft-exception AND X11) AND (MIT AND MPL-2.0-no-copyleft-exception) AND (MPL-1.0 AND MPL-2.0-no-copyleft-exception) AND (Apache-2.0 AND MPL-2.0-no-copyleft-exception) AND MPL-1.0, restricted, #13191 maven/mavencentral/org.antlr/antlr4-runtime/4.11.1, BSD-3-Clause, approved, clearlydefined +maven/mavencentral/org.apache.commons/commons-compress/1.24.0, Apache-2.0 AND BSD-3-Clause AND bzip2-1.0.6 AND LicenseRef-Public-Domain, approved, #10368 maven/mavencentral/org.apache.commons/commons-compress/1.25.0, Apache-2.0, approved, #11600 maven/mavencentral/org.apache.commons/commons-lang3/3.11, Apache-2.0, approved, CQ22642 maven/mavencentral/org.apache.commons/commons-lang3/3.12.0, Apache-2.0, approved, clearlydefined @@ -498,12 +499,17 @@ maven/mavencentral/org.slf4j/slf4j-api/1.7.7, MIT, approved, CQ9827 maven/mavencentral/org.slf4j/slf4j-api/2.0.12, MIT, approved, #5915 maven/mavencentral/org.slf4j/slf4j-api/2.0.9, MIT, approved, #5915 maven/mavencentral/org.testcontainers/database-commons/1.19.4, Apache-2.0, approved, #10345 +maven/mavencentral/org.testcontainers/database-commons/1.19.5, Apache-2.0, approved, #10345 maven/mavencentral/org.testcontainers/jdbc/1.19.4, Apache-2.0, approved, #10348 +maven/mavencentral/org.testcontainers/jdbc/1.19.5, Apache-2.0, approved, #10348 maven/mavencentral/org.testcontainers/junit-jupiter/1.19.3, MIT, approved, #10344 maven/mavencentral/org.testcontainers/junit-jupiter/1.19.4, MIT, approved, #10344 +maven/mavencentral/org.testcontainers/junit-jupiter/1.19.5, MIT, approved, #10344 maven/mavencentral/org.testcontainers/postgresql/1.19.4, MIT, approved, #10350 +maven/mavencentral/org.testcontainers/postgresql/1.19.5, MIT, approved, #10350 maven/mavencentral/org.testcontainers/testcontainers/1.19.4, Apache-2.0 AND MIT, approved, #10347 -maven/mavencentral/org.testcontainers/vault/1.19.4, MIT, approved, #10852 +maven/mavencentral/org.testcontainers/testcontainers/1.19.5, Apache-2.0 AND MIT, approved, #10347 +maven/mavencentral/org.testcontainers/vault/1.19.5, MIT, approved, #10852 maven/mavencentral/org.xmlresolver/xmlresolver/5.2.0, Apache-2.0, approved, clearlydefined maven/mavencentral/org.yaml/snakeyaml/2.0, Apache-2.0 AND (Apache-2.0 OR BSD-3-Clause OR EPL-1.0 OR GPL-2.0-or-later OR LGPL-2.1-or-later), approved, #7275 maven/mavencentral/org.yaml/snakeyaml/2.2, Apache-2.0 AND (Apache-2.0 OR BSD-3-Clause OR EPL-1.0 OR GPL-2.0-or-later OR LGPL-2.1-or-later), approved, #10232 From 16a45f5040645624483dad60694169d96d2e4c32 Mon Sep 17 00:00:00 2001 From: Enrico Risa Date: Tue, 13 Feb 2024 09:20:09 +0100 Subject: [PATCH 005/100] chore: dependencies file --- DEPENDENCIES | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DEPENDENCIES b/DEPENDENCIES index bc80fa949..0d02f935b 100644 --- a/DEPENDENCIES +++ b/DEPENDENCIES @@ -1,4 +1,4 @@ - maven/mavencentral/com.apicatalog/carbon-did/0.0.2, Apache-2.0, approved, #9239 +maven/mavencentral/com.apicatalog/carbon-did/0.0.2, Apache-2.0, approved, #9239 maven/mavencentral/com.apicatalog/iron-ed25519-cryptosuite-2020/0.8.1, Apache-2.0, approved, #11157 maven/mavencentral/com.apicatalog/iron-verifiable-credentials/0.8.1, Apache-2.0, approved, #9234 maven/mavencentral/com.apicatalog/titanium-json-ld/1.0.0, Apache-2.0, approved, clearlydefined From 960ff4bd6c904a1702cf2b2874b0fa780035c9a2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 13 Feb 2024 08:53:43 +0000 Subject: [PATCH 006/100] chore(deps): bump aws from 2.23.19 to 2.24.1 Bumps `aws` from 2.23.19 to 2.24.1. Updates `software.amazon.awssdk:s3` from 2.23.19 to 2.24.1 Updates `software.amazon.awssdk:s3-transfer-manager` from 2.23.19 to 2.24.1 --- updated-dependencies: - dependency-name: software.amazon.awssdk:s3 dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:s3-transfer-manager dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 5e4b58ff1..fd872a844 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -6,7 +6,7 @@ edc = "0.5.1" apache-sshd = "2.12.0" assertj = "3.25.3" awaitility = "4.2.0" -aws = "2.23.19" +aws = "2.24.1" azure-identity = "1.11.2" bouncyCastle-jdk18on = "1.77" flyway = "9.22.3" From fb9f3343793435760bf65b0ca4fa57f7b5f30629 Mon Sep 17 00:00:00 2001 From: Enrico Risa Date: Tue, 13 Feb 2024 13:53:35 +0100 Subject: [PATCH 007/100] chore: dependencies file --- DEPENDENCIES | 54 ++++++++++++++++++++++++++-------------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/DEPENDENCIES b/DEPENDENCIES index 0d02f935b..45ba48a97 100644 --- a/DEPENDENCIES +++ b/DEPENDENCIES @@ -514,58 +514,58 @@ maven/mavencentral/org.xmlresolver/xmlresolver/5.2.0, Apache-2.0, approved, clea maven/mavencentral/org.yaml/snakeyaml/2.0, Apache-2.0 AND (Apache-2.0 OR BSD-3-Clause OR EPL-1.0 OR GPL-2.0-or-later OR LGPL-2.1-or-later), approved, #7275 maven/mavencentral/org.yaml/snakeyaml/2.2, Apache-2.0 AND (Apache-2.0 OR BSD-3-Clause OR EPL-1.0 OR GPL-2.0-or-later OR LGPL-2.1-or-later), approved, #10232 maven/mavencentral/software.amazon.awssdk/annotations/2.22.9, Apache-2.0, approved, #12618 -maven/mavencentral/software.amazon.awssdk/annotations/2.23.19, Apache-2.0, approved, #13157 +maven/mavencentral/software.amazon.awssdk/annotations/2.24.1, , restricted, clearlydefined maven/mavencentral/software.amazon.awssdk/apache-client/2.22.9, Apache-2.0, approved, #12633 -maven/mavencentral/software.amazon.awssdk/apache-client/2.23.19, Apache-2.0, approved, #13142 +maven/mavencentral/software.amazon.awssdk/apache-client/2.24.1, , restricted, clearlydefined maven/mavencentral/software.amazon.awssdk/arns/2.22.9, Apache-2.0, approved, #12647 -maven/mavencentral/software.amazon.awssdk/arns/2.23.19, Apache-2.0, approved, #13135 +maven/mavencentral/software.amazon.awssdk/arns/2.24.1, , restricted, clearlydefined maven/mavencentral/software.amazon.awssdk/auth/2.22.9, Apache-2.0, approved, #12622 -maven/mavencentral/software.amazon.awssdk/auth/2.23.19, Apache-2.0, approved, #13141 +maven/mavencentral/software.amazon.awssdk/auth/2.24.1, , restricted, clearlydefined maven/mavencentral/software.amazon.awssdk/aws-core/2.22.9, Apache-2.0, approved, #12640 -maven/mavencentral/software.amazon.awssdk/aws-core/2.23.19, Apache-2.0, approved, #13148 +maven/mavencentral/software.amazon.awssdk/aws-core/2.24.1, , restricted, clearlydefined maven/mavencentral/software.amazon.awssdk/aws-query-protocol/2.22.9, Apache-2.0, approved, #12645 -maven/mavencentral/software.amazon.awssdk/aws-query-protocol/2.23.19, Apache-2.0, approved, #13150 +maven/mavencentral/software.amazon.awssdk/aws-query-protocol/2.24.1, , restricted, clearlydefined maven/mavencentral/software.amazon.awssdk/aws-xml-protocol/2.22.9, Apache-2.0, approved, #12628 -maven/mavencentral/software.amazon.awssdk/aws-xml-protocol/2.23.19, Apache-2.0, approved, #13146 +maven/mavencentral/software.amazon.awssdk/aws-xml-protocol/2.24.1, , restricted, clearlydefined maven/mavencentral/software.amazon.awssdk/checksums-spi/2.22.9, Apache-2.0, approved, #12642 -maven/mavencentral/software.amazon.awssdk/checksums-spi/2.23.19, Apache-2.0, approved, #13158 +maven/mavencentral/software.amazon.awssdk/checksums-spi/2.24.1, , restricted, clearlydefined maven/mavencentral/software.amazon.awssdk/checksums/2.22.9, Apache-2.0, approved, #12641 -maven/mavencentral/software.amazon.awssdk/checksums/2.23.19, Apache-2.0, approved, #13144 +maven/mavencentral/software.amazon.awssdk/checksums/2.24.1, , restricted, clearlydefined maven/mavencentral/software.amazon.awssdk/crt-core/2.22.9, Apache-2.0, approved, #12635 -maven/mavencentral/software.amazon.awssdk/crt-core/2.23.19, Apache-2.0, approved, #13136 +maven/mavencentral/software.amazon.awssdk/crt-core/2.24.1, , restricted, clearlydefined maven/mavencentral/software.amazon.awssdk/endpoints-spi/2.22.9, Apache-2.0, approved, #12624 -maven/mavencentral/software.amazon.awssdk/endpoints-spi/2.23.19, Apache-2.0, approved, #13151 +maven/mavencentral/software.amazon.awssdk/endpoints-spi/2.24.1, , restricted, clearlydefined maven/mavencentral/software.amazon.awssdk/http-auth-aws/2.22.9, Apache-2.0, approved, #12637 -maven/mavencentral/software.amazon.awssdk/http-auth-aws/2.23.19, Apache-2.0, approved, #13154 +maven/mavencentral/software.amazon.awssdk/http-auth-aws/2.24.1, , restricted, clearlydefined maven/mavencentral/software.amazon.awssdk/http-auth-spi/2.22.9, Apache-2.0, approved, #12638 -maven/mavencentral/software.amazon.awssdk/http-auth-spi/2.23.19, Apache-2.0, approved, #13147 +maven/mavencentral/software.amazon.awssdk/http-auth-spi/2.24.1, , restricted, clearlydefined maven/mavencentral/software.amazon.awssdk/http-auth/2.22.9, Apache-2.0, approved, #12626 -maven/mavencentral/software.amazon.awssdk/http-auth/2.23.19, Apache-2.0, approved, #13149 +maven/mavencentral/software.amazon.awssdk/http-auth/2.24.1, , restricted, clearlydefined maven/mavencentral/software.amazon.awssdk/http-client-spi/2.22.9, Apache-2.0, approved, #12627 -maven/mavencentral/software.amazon.awssdk/http-client-spi/2.23.19, Apache-2.0, approved, #13155 +maven/mavencentral/software.amazon.awssdk/http-client-spi/2.24.1, , restricted, clearlydefined maven/mavencentral/software.amazon.awssdk/iam/2.22.9, Apache-2.0, approved, clearlydefined maven/mavencentral/software.amazon.awssdk/identity-spi/2.22.9, Apache-2.0, approved, #12636 -maven/mavencentral/software.amazon.awssdk/identity-spi/2.23.19, Apache-2.0, approved, #13143 +maven/mavencentral/software.amazon.awssdk/identity-spi/2.24.1, , restricted, clearlydefined maven/mavencentral/software.amazon.awssdk/json-utils/2.22.9, Apache-2.0, approved, #12646 -maven/mavencentral/software.amazon.awssdk/json-utils/2.23.19, Apache-2.0, approved, #13139 +maven/mavencentral/software.amazon.awssdk/json-utils/2.24.1, , restricted, clearlydefined maven/mavencentral/software.amazon.awssdk/metrics-spi/2.22.9, Apache-2.0, approved, #12649 -maven/mavencentral/software.amazon.awssdk/metrics-spi/2.23.19, Apache-2.0, approved, #13153 +maven/mavencentral/software.amazon.awssdk/metrics-spi/2.24.1, , restricted, clearlydefined maven/mavencentral/software.amazon.awssdk/netty-nio-client/2.22.9, Apache-2.0, approved, #12644 -maven/mavencentral/software.amazon.awssdk/netty-nio-client/2.23.19, Apache-2.0, approved, #13134 +maven/mavencentral/software.amazon.awssdk/netty-nio-client/2.24.1, , restricted, clearlydefined maven/mavencentral/software.amazon.awssdk/profiles/2.22.9, Apache-2.0, approved, #12620 -maven/mavencentral/software.amazon.awssdk/profiles/2.23.19, Apache-2.0, approved, #13132 +maven/mavencentral/software.amazon.awssdk/profiles/2.24.1, , restricted, clearlydefined maven/mavencentral/software.amazon.awssdk/protocol-core/2.22.9, Apache-2.0, approved, #12648 -maven/mavencentral/software.amazon.awssdk/protocol-core/2.23.19, Apache-2.0, approved, #13133 +maven/mavencentral/software.amazon.awssdk/protocol-core/2.24.1, , restricted, clearlydefined maven/mavencentral/software.amazon.awssdk/regions/2.22.9, Apache-2.0, approved, #12643 -maven/mavencentral/software.amazon.awssdk/regions/2.23.19, Apache-2.0, approved, #13159 -maven/mavencentral/software.amazon.awssdk/s3-transfer-manager/2.23.19, Apache-2.0, approved, #13156 +maven/mavencentral/software.amazon.awssdk/regions/2.24.1, , restricted, clearlydefined +maven/mavencentral/software.amazon.awssdk/s3-transfer-manager/2.24.1, , restricted, clearlydefined maven/mavencentral/software.amazon.awssdk/s3/2.22.9, Apache-2.0, approved, #12630 -maven/mavencentral/software.amazon.awssdk/s3/2.23.19, Apache-2.0, approved, #13152 +maven/mavencentral/software.amazon.awssdk/s3/2.24.1, , restricted, clearlydefined maven/mavencentral/software.amazon.awssdk/sdk-core/2.22.9, Apache-2.0, approved, #12639 -maven/mavencentral/software.amazon.awssdk/sdk-core/2.23.19, Apache-2.0, approved, #13138 +maven/mavencentral/software.amazon.awssdk/sdk-core/2.24.1, , restricted, clearlydefined maven/mavencentral/software.amazon.awssdk/sts/2.22.9, Apache-2.0, approved, clearlydefined maven/mavencentral/software.amazon.awssdk/third-party-jackson-core/2.22.9, Apache-2.0, approved, #12629 -maven/mavencentral/software.amazon.awssdk/third-party-jackson-core/2.23.19, Apache-2.0, approved, #13140 +maven/mavencentral/software.amazon.awssdk/third-party-jackson-core/2.24.1, , restricted, clearlydefined maven/mavencentral/software.amazon.awssdk/utils/2.22.9, Apache-2.0, approved, #12631 -maven/mavencentral/software.amazon.awssdk/utils/2.23.19, Apache-2.0, approved, #13137 +maven/mavencentral/software.amazon.awssdk/utils/2.24.1, , restricted, clearlydefined maven/mavencentral/software.amazon.eventstream/eventstream/1.0.1, Apache-2.0, approved, clearlydefined From 7494d097a89df90ea8e11cf9c68b70b8867e78c3 Mon Sep 17 00:00:00 2001 From: Paul Latzelsperger <43503240+paullatzelsperger@users.noreply.github.com> Date: Tue, 13 Feb 2024 14:55:55 +0100 Subject: [PATCH 008/100] chore: make license header regex more permissive (#1052) --- resources/hashtag.header | 4 ++-- resources/java.header | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/resources/hashtag.header b/resources/hashtag.header index a6357d5b2..15b2ffccb 100644 --- a/resources/hashtag.header +++ b/resources/hashtag.header @@ -1,5 +1,5 @@ ^#! -^##{80}$ +^##+$ ^# Copyright \(c\) 20\d\d((,| -)20\d{2})? [A-Za-z].+\S$ ^#$ ^# See the NOTICE file\(s\) distributed with this work for additional$ @@ -16,5 +16,5 @@ ^# under the License\.$ ^#$ ^# SPDX-License-Identifier: Apache\-2\.0$ -^##{80}$ +^##+$ ^$ diff --git a/resources/java.header b/resources/java.header index aea312737..c099ca0e1 100644 --- a/resources/java.header +++ b/resources/java.header @@ -1,4 +1,4 @@ -^/\*{80}$ +^/\*+$ ^ \* Copyright \(c\) 20\d\d((,| -)20\d{2})? [A-Za-z].+\S$ ^ \*$ ^ \* See the NOTICE file\(s\) distributed with this work for additional$ @@ -15,6 +15,6 @@ ^ \* under the License\.$ ^ \*$ ^ \* SPDX-License-Identifier: Apache\-2\.0$ -^ \*{80}/$ +^ \*+/$ ^$ ^package From bf3244167e7e7f91a96fc146fd9c8adb5a4a209e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 14 Feb 2024 15:36:33 +0100 Subject: [PATCH 009/100] chore(deps): bump org.flywaydb:flyway-core from 9.22.3 to 10.7.2 (#1042) * chore(deps): bump org.flywaydb:flyway-core from 9.22.3 to 10.7.2 Bumps [org.flywaydb:flyway-core](https://github.com/flyway/flyway) from 9.22.3 to 10.7.2. - [Release notes](https://github.com/flyway/flyway/releases) - [Commits](https://github.com/flyway/flyway/compare/flyway-9.22.3...flyway-10.7.2) --- updated-dependencies: - dependency-name: org.flywaydb:flyway-core dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] * add explicit PG support to flyway * DEPENDENCIES --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Paul Latzelsperger --- DEPENDENCIES | 3 ++- edc-extensions/postgresql-migration/build.gradle.kts | 4 ++++ gradle/libs.versions.toml | 3 ++- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/DEPENDENCIES b/DEPENDENCIES index 45ba48a97..a94d1083e 100644 --- a/DEPENDENCIES +++ b/DEPENDENCIES @@ -418,7 +418,8 @@ maven/mavencentral/org.eclipse.jetty/jetty-servlet/11.0.20, EPL-2.0 OR Apache-2. maven/mavencentral/org.eclipse.jetty/jetty-util/11.0.20, EPL-2.0 OR Apache-2.0, approved, rt.jetty maven/mavencentral/org.eclipse.jetty/jetty-webapp/11.0.20, EPL-2.0 OR Apache-2.0, approved, rt.jetty maven/mavencentral/org.eclipse.jetty/jetty-xml/11.0.20, EPL-2.0 OR Apache-2.0, approved, rt.jetty -maven/mavencentral/org.flywaydb/flyway-core/9.22.3, Apache-2.0, approved, #10349 +maven/mavencentral/org.flywaydb/flyway-core/10.7.2, , restricted, clearlydefined +maven/mavencentral/org.flywaydb/flyway-database-postgresql/10.7.2, , restricted, clearlydefined maven/mavencentral/org.glassfish.hk2.external/aopalliance-repackaged/3.0.5, EPL-2.0 OR GPL-2.0-only with Classpath-exception-2.0, approved, ee4j.glassfish maven/mavencentral/org.glassfish.hk2/hk2-api/3.0.5, EPL-2.0 OR GPL-2.0-only with Classpath-exception-2.0, approved, ee4j.glassfish maven/mavencentral/org.glassfish.hk2/hk2-locator/3.0.5, EPL-2.0 OR GPL-2.0-only with Classpath-exception-2.0, approved, ee4j.glassfish diff --git a/edc-extensions/postgresql-migration/build.gradle.kts b/edc-extensions/postgresql-migration/build.gradle.kts index 22f26a7c2..ed6ad7469 100644 --- a/edc-extensions/postgresql-migration/build.gradle.kts +++ b/edc-extensions/postgresql-migration/build.gradle.kts @@ -31,6 +31,10 @@ dependencies { runtimeOnly(libs.postgres) implementation(libs.flyway.core) + // starting from flyway 10, they've moved to a more modular structure, + // so we need to add PG support explicitly + // https://documentation.red-gate.com/flyway/release-notes-and-older-versions/release-notes-for-flyway-engine + runtimeOnly(libs.flyway.database.postgres) testImplementation(testFixtures(libs.edc.sql.core)) } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index fd872a844..35a01b066 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -9,7 +9,7 @@ awaitility = "4.2.0" aws = "2.24.1" azure-identity = "1.11.2" bouncyCastle-jdk18on = "1.77" -flyway = "9.22.3" +flyway = "10.7.2" iron-vc = "0.8.1" jackson = "2.16.1" jakarta-json = "2.0.1" @@ -175,6 +175,7 @@ aws-s3 = { module = "software.amazon.awssdk:s3", version.ref = "aws" } aws-s3transfer = { module = "software.amazon.awssdk:s3-transfer-manager", version.ref = "aws" } bouncyCastle-bcpkixJdk18on = { module = "org.bouncycastle:bcpkix-jdk18on", version.ref = "bouncyCastle-jdk18on" } flyway-core = { module = "org.flywaydb:flyway-core", version.ref = "flyway" } +flyway-database-postgres = { module = "org.flywaydb:flyway-database-postgresql", version.ref = "flyway" } jackson-datatypeJsr310 = { module = "com.fasterxml.jackson.datatype:jackson-datatype-jsr310", version.ref = "jackson" } jacksonJsonP = { module = "com.fasterxml.jackson.datatype:jackson-datatype-jakarta-jsonp", version.ref = "jackson" } jakarta-rsApi = { module = "jakarta.ws.rs:jakarta.ws.rs-api", version.ref = "rsApi" } From d7dd82013939af876eb3654d077ee7cb13bc2951 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 15 Feb 2024 11:44:00 +0100 Subject: [PATCH 010/100] chore(deps): bump aquasecurity/trivy-action from 0.12.0 to 0.17.0 (#1044) Bumps [aquasecurity/trivy-action](https://github.com/aquasecurity/trivy-action) from 0.12.0 to 0.17.0. - [Release notes](https://github.com/aquasecurity/trivy-action/releases) - [Commits](https://github.com/aquasecurity/trivy-action/compare/0.12.0...0.17.0) --- updated-dependencies: - dependency-name: aquasecurity/trivy-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/trivy.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/trivy.yml b/.github/workflows/trivy.yml index e83831a5a..bd8f6db98 100644 --- a/.github/workflows/trivy.yml +++ b/.github/workflows/trivy.yml @@ -58,7 +58,7 @@ jobs: steps: - uses: actions/checkout@v4 - name: Run Trivy vulnerability scanner in repo mode - uses: aquasecurity/trivy-action@0.12.0 + uses: aquasecurity/trivy-action@0.17.0 with: scan-type: "config" # ignore-unfixed: true @@ -102,7 +102,7 @@ jobs: ## the next two steps will only execute if the image exists check was successful - name: Run Trivy vulnerability scanner if: success() && steps.imageCheck.outcome != 'failure' - uses: aquasecurity/trivy-action@0.12.0 + uses: aquasecurity/trivy-action@0.17.0 with: image-ref: "tractusx/${{ matrix.image }}:sha-${{ needs.git-sha7.outputs.value }}" format: "sarif" From a19de69689a84f2e145e8877ca8a85835e8ca6db Mon Sep 17 00:00:00 2001 From: Paul Latzelsperger <43503240+paullatzelsperger@users.noreply.github.com> Date: Thu, 15 Feb 2024 11:45:34 +0100 Subject: [PATCH 011/100] feat: implement new Policy eval fct for FrameworkAgreement (#1053) * add basic function impl * improved code structure, javadoc * track EDC snapshots * DEPENDENCIES --- DEPENDENCIES | 362 +++++++++--------- edc-extensions/cx-policy/build.gradle.kts | 1 + .../FrameworkAgreementConstraintFunction.java | 249 +++++++----- ...meworkAgreementConstraintFunctionTest.java | 327 ++++++++++++---- gradle/libs.versions.toml | 3 +- .../ssi/spi/jsonld/CredentialsNamespaces.java | 8 + 6 files changed, 583 insertions(+), 367 deletions(-) diff --git a/DEPENDENCIES b/DEPENDENCIES index a94d1083e..3f657bc59 100644 --- a/DEPENDENCIES +++ b/DEPENDENCIES @@ -6,12 +6,12 @@ maven/mavencentral/com.apicatalog/titanium-json-ld/1.3.1, Apache-2.0, approved, maven/mavencentral/com.apicatalog/titanium-json-ld/1.3.3, Apache-2.0, approved, #8912 maven/mavencentral/com.azure/azure-core-http-netty/1.13.11, MIT AND Apache-2.0, approved, #7948 maven/mavencentral/com.azure/azure-core-http-netty/1.13.9, MIT AND Apache-2.0, approved, #7948 -maven/mavencentral/com.azure/azure-core-http-netty/1.14.0, , restricted, clearlydefined +maven/mavencentral/com.azure/azure-core-http-netty/1.14.0, MIT AND Apache-2.0, approved, #13238 maven/mavencentral/com.azure/azure-core/1.44.1, MIT, approved, clearlydefined maven/mavencentral/com.azure/azure-core/1.45.1, MIT AND Apache-2.0, approved, #11845 -maven/mavencentral/com.azure/azure-core/1.46.0, , restricted, clearlydefined -maven/mavencentral/com.azure/azure-identity/1.11.1, MIT, approved, clearlydefined -maven/mavencentral/com.azure/azure-identity/1.11.2, , restricted, clearlydefined +maven/mavencentral/com.azure/azure-core/1.46.0, MIT AND Apache-2.0, approved, #13234 +maven/mavencentral/com.azure/azure-identity/1.11.1, MIT AND Apache-2.0, approved, #13237 +maven/mavencentral/com.azure/azure-identity/1.11.2, MIT AND Apache-2.0, approved, #13237 maven/mavencentral/com.azure/azure-json/1.1.0, MIT AND Apache-2.0, approved, #10547 maven/mavencentral/com.azure/azure-security-keyvault-secrets/4.7.3, MIT, approved, #10868 maven/mavencentral/com.azure/azure-storage-blob/12.24.1, MIT, approved, #10568 @@ -248,154 +248,154 @@ maven/mavencentral/org.codehaus.plexus/plexus-container-default/2.1.0, Apache-2. maven/mavencentral/org.codehaus.plexus/plexus-utils/3.1.1, , approved, CQ16492 maven/mavencentral/org.codehaus.plexus/plexus-utils/3.3.0, , approved, CQ21066 maven/mavencentral/org.codehaus.woodstox/stax2-api/4.2.1, BSD-2-Clause, approved, #2670 -maven/mavencentral/org.eclipse.edc/api-core/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/api-observability/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/asset-api/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/asset-index-sql/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/asset-spi/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/auth-spi/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/auth-tokenbased/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/autodoc-processor/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/aws-s3-core/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/aws-s3-test/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/azure-blob-core/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/azure-test/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/boot/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/callback-event-dispatcher/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/callback-http-dispatcher/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/catalog-api/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/catalog-core/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/catalog-spi/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/configuration-filesystem/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/connector-core/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/contract-agreement-api/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/contract-core/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/contract-definition-api/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/contract-definition-store-sql/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/contract-negotiation-api/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/contract-negotiation-store-sql/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/contract-spi/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/control-api-configuration/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/control-plane-aggregate-services/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/control-plane-api-client-spi/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/control-plane-api-client/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/control-plane-api/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/control-plane-core/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/control-plane-spi/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/core-spi/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/crypto-common/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-address-http-data-spi/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-plane-aws-s3/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-plane-azure-storage/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-plane-client/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-plane-control-api/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-plane-core/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-plane-http-oauth2-core/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-plane-http-oauth2/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-plane-http-spi/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-plane-http/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-plane-public-api/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-plane-selector-core/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-plane-selector-spi/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-plane-spi/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-plane-util/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-api-configuration/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-catalog-api/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-catalog-http-dispatcher/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-catalog-transform/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-catalog/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-http-core/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-http-spi/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-negotiation-api/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-negotiation-http-dispatcher/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-negotiation-transform/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-negotiation/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-spi/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-transfer-process-api/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-transfer-process-http-dispatcher/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-transfer-process-transform/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-transfer-process/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/http-spi/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/http/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/iam-mock/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-did-core/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-did-spi/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-hub-api/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-hub-credentials/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-hub-did-spi/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-hub-did/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-hub-keypairs/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-hub-participants/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-hub-spi/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-hub-store-spi/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-trust-core/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-trust-issuers-configuration/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-trust-service/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-trust-spi/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-trust-sts-api/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-trust-sts-client-configuration/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-trust-sts-core/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-trust-sts-embedded/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-trust-sts-remote-core/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-trust-sts-remote/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-trust-sts-spi/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-trust-transform/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/jersey-core/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/jersey-micrometer/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/jersey-providers/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/jetty-core/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/jetty-micrometer/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/json-ld-spi/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/json-ld/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/junit/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/jws2020/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/jwt-spi/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/jwt-verifiable-credentials/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/ldp-verifiable-credentials/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/management-api-configuration/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/management-api-test-fixtures/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/management-api/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/micrometer-core/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/oauth2-client/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/oauth2-spi/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/policy-definition-api/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/policy-definition-store-sql/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/policy-engine-spi/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/policy-engine/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/policy-evaluator/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/policy-model/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/policy-monitor-core/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/policy-monitor-spi/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/policy-monitor-store-sql/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/policy-spi/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/runtime-metamodel/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/security/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/sql-core/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/sql-lease/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/sql-pool-apache-commons/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/state-machine/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/token-core/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/token-spi/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/transaction-datasource-spi/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/transaction-local/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/transaction-spi/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/transfer-core/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/transfer-data-plane-spi/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/transfer-data-plane/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/transfer-process-api/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/transfer-process-store-sql/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/transfer-pull-http-dynamic-receiver/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/transfer-spi/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/transform-core/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/transform-spi/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/util/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/validator-core/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/validator-data-address-http-data/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/validator-spi/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/vault-azure/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/vault-hashicorp/0.5.1, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/web-spi/0.5.1, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/api-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/api-observability/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/asset-api/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/asset-index-sql/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/asset-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/auth-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/auth-tokenbased/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/autodoc-processor/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/aws-s3-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/aws-s3-test/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/azure-blob-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/azure-test/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/boot/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/callback-event-dispatcher/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/callback-http-dispatcher/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/catalog-api/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/catalog-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/catalog-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/configuration-filesystem/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/connector-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/contract-agreement-api/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/contract-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/contract-definition-api/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/contract-definition-store-sql/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/contract-negotiation-api/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/contract-negotiation-store-sql/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/contract-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/control-api-configuration/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/control-plane-aggregate-services/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/control-plane-api-client-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/control-plane-api-client/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/control-plane-api/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/control-plane-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/control-plane-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/core-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/crypto-common/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-address-http-data-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-aws-s3/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-azure-storage/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-client/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-control-api/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-http-oauth2-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-http-oauth2/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-http-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-http/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-public-api/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-selector-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-selector-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-util/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-api-configuration/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-catalog-api/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-catalog-http-dispatcher/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-catalog-transform/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-catalog/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-http-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-http-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-negotiation-api/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-negotiation-http-dispatcher/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-negotiation-transform/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-negotiation/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-transfer-process-api/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-transfer-process-http-dispatcher/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-transfer-process-transform/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-transfer-process/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/http-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/http/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/iam-mock/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-did-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-did-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-hub-api/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-hub-credentials/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-hub-did-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-hub-did/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-hub-keypairs/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-hub-participants/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-hub-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-hub-store-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-trust-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-trust-issuers-configuration/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-trust-service/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-trust-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-trust-sts-api/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-trust-sts-client-configuration/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-trust-sts-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-trust-sts-embedded/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-trust-sts-remote-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-trust-sts-remote/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-trust-sts-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-trust-transform/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/jersey-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/jersey-micrometer/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/jersey-providers/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/jetty-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/jetty-micrometer/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/json-ld-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/json-ld/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/junit/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/jws2020/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/jwt-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/jwt-verifiable-credentials/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/ldp-verifiable-credentials/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/management-api-configuration/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/management-api-test-fixtures/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/management-api/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/micrometer-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/oauth2-client/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/oauth2-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/policy-definition-api/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/policy-definition-store-sql/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/policy-engine-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/policy-engine/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/policy-evaluator/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/policy-model/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/policy-monitor-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/policy-monitor-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/policy-monitor-store-sql/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/policy-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/runtime-metamodel/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/security/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/sql-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/sql-lease/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/sql-pool-apache-commons/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/state-machine/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/token-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/token-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/transaction-datasource-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/transaction-local/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/transaction-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/transfer-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/transfer-data-plane-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/transfer-data-plane/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/transfer-process-api/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/transfer-process-store-sql/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/transfer-pull-http-dynamic-receiver/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/transfer-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/transform-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/transform-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/util/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/validator-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/validator-data-address-http-data/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/validator-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/vault-azure/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/vault-hashicorp/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/web-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.jetty.toolchain/jetty-jakarta-servlet-api/5.0.2, EPL-2.0 OR Apache-2.0, approved, rt.jetty maven/mavencentral/org.eclipse.jetty.toolchain/jetty-jakarta-websocket-api/2.0.0, EPL-2.0 OR Apache-2.0, approved, rt.jetty maven/mavencentral/org.eclipse.jetty.websocket/websocket-core-client/11.0.20, EPL-2.0 OR Apache-2.0, approved, rt.jetty @@ -418,8 +418,8 @@ maven/mavencentral/org.eclipse.jetty/jetty-servlet/11.0.20, EPL-2.0 OR Apache-2. maven/mavencentral/org.eclipse.jetty/jetty-util/11.0.20, EPL-2.0 OR Apache-2.0, approved, rt.jetty maven/mavencentral/org.eclipse.jetty/jetty-webapp/11.0.20, EPL-2.0 OR Apache-2.0, approved, rt.jetty maven/mavencentral/org.eclipse.jetty/jetty-xml/11.0.20, EPL-2.0 OR Apache-2.0, approved, rt.jetty -maven/mavencentral/org.flywaydb/flyway-core/10.7.2, , restricted, clearlydefined -maven/mavencentral/org.flywaydb/flyway-database-postgresql/10.7.2, , restricted, clearlydefined +maven/mavencentral/org.flywaydb/flyway-core/10.7.2, Apache-2.0, approved, #13235 +maven/mavencentral/org.flywaydb/flyway-database-postgresql/10.7.2, Apache-2.0, approved, #13236 maven/mavencentral/org.glassfish.hk2.external/aopalliance-repackaged/3.0.5, EPL-2.0 OR GPL-2.0-only with Classpath-exception-2.0, approved, ee4j.glassfish maven/mavencentral/org.glassfish.hk2/hk2-api/3.0.5, EPL-2.0 OR GPL-2.0-only with Classpath-exception-2.0, approved, ee4j.glassfish maven/mavencentral/org.glassfish.hk2/hk2-locator/3.0.5, EPL-2.0 OR GPL-2.0-only with Classpath-exception-2.0, approved, ee4j.glassfish @@ -515,58 +515,58 @@ maven/mavencentral/org.xmlresolver/xmlresolver/5.2.0, Apache-2.0, approved, clea maven/mavencentral/org.yaml/snakeyaml/2.0, Apache-2.0 AND (Apache-2.0 OR BSD-3-Clause OR EPL-1.0 OR GPL-2.0-or-later OR LGPL-2.1-or-later), approved, #7275 maven/mavencentral/org.yaml/snakeyaml/2.2, Apache-2.0 AND (Apache-2.0 OR BSD-3-Clause OR EPL-1.0 OR GPL-2.0-or-later OR LGPL-2.1-or-later), approved, #10232 maven/mavencentral/software.amazon.awssdk/annotations/2.22.9, Apache-2.0, approved, #12618 -maven/mavencentral/software.amazon.awssdk/annotations/2.24.1, , restricted, clearlydefined +maven/mavencentral/software.amazon.awssdk/annotations/2.24.1, Apache-2.0, approved, #13251 maven/mavencentral/software.amazon.awssdk/apache-client/2.22.9, Apache-2.0, approved, #12633 -maven/mavencentral/software.amazon.awssdk/apache-client/2.24.1, , restricted, clearlydefined +maven/mavencentral/software.amazon.awssdk/apache-client/2.24.1, Apache-2.0, approved, #13257 maven/mavencentral/software.amazon.awssdk/arns/2.22.9, Apache-2.0, approved, #12647 -maven/mavencentral/software.amazon.awssdk/arns/2.24.1, , restricted, clearlydefined +maven/mavencentral/software.amazon.awssdk/arns/2.24.1, Apache-2.0, approved, #13243 maven/mavencentral/software.amazon.awssdk/auth/2.22.9, Apache-2.0, approved, #12622 -maven/mavencentral/software.amazon.awssdk/auth/2.24.1, , restricted, clearlydefined +maven/mavencentral/software.amazon.awssdk/auth/2.24.1, Apache-2.0, approved, #13256 maven/mavencentral/software.amazon.awssdk/aws-core/2.22.9, Apache-2.0, approved, #12640 -maven/mavencentral/software.amazon.awssdk/aws-core/2.24.1, , restricted, clearlydefined +maven/mavencentral/software.amazon.awssdk/aws-core/2.24.1, Apache-2.0, approved, #13240 maven/mavencentral/software.amazon.awssdk/aws-query-protocol/2.22.9, Apache-2.0, approved, #12645 -maven/mavencentral/software.amazon.awssdk/aws-query-protocol/2.24.1, , restricted, clearlydefined +maven/mavencentral/software.amazon.awssdk/aws-query-protocol/2.24.1, Apache-2.0, approved, #13262 maven/mavencentral/software.amazon.awssdk/aws-xml-protocol/2.22.9, Apache-2.0, approved, #12628 -maven/mavencentral/software.amazon.awssdk/aws-xml-protocol/2.24.1, , restricted, clearlydefined +maven/mavencentral/software.amazon.awssdk/aws-xml-protocol/2.24.1, Apache-2.0, approved, #13247 maven/mavencentral/software.amazon.awssdk/checksums-spi/2.22.9, Apache-2.0, approved, #12642 -maven/mavencentral/software.amazon.awssdk/checksums-spi/2.24.1, , restricted, clearlydefined +maven/mavencentral/software.amazon.awssdk/checksums-spi/2.24.1, Apache-2.0, approved, #13245 maven/mavencentral/software.amazon.awssdk/checksums/2.22.9, Apache-2.0, approved, #12641 -maven/mavencentral/software.amazon.awssdk/checksums/2.24.1, , restricted, clearlydefined +maven/mavencentral/software.amazon.awssdk/checksums/2.24.1, Apache-2.0, approved, #13242 maven/mavencentral/software.amazon.awssdk/crt-core/2.22.9, Apache-2.0, approved, #12635 -maven/mavencentral/software.amazon.awssdk/crt-core/2.24.1, , restricted, clearlydefined +maven/mavencentral/software.amazon.awssdk/crt-core/2.24.1, Apache-2.0, approved, #13252 maven/mavencentral/software.amazon.awssdk/endpoints-spi/2.22.9, Apache-2.0, approved, #12624 -maven/mavencentral/software.amazon.awssdk/endpoints-spi/2.24.1, , restricted, clearlydefined +maven/mavencentral/software.amazon.awssdk/endpoints-spi/2.24.1, Apache-2.0, approved, #13246 maven/mavencentral/software.amazon.awssdk/http-auth-aws/2.22.9, Apache-2.0, approved, #12637 -maven/mavencentral/software.amazon.awssdk/http-auth-aws/2.24.1, , restricted, clearlydefined +maven/mavencentral/software.amazon.awssdk/http-auth-aws/2.24.1, Apache-2.0, approved, #13253 maven/mavencentral/software.amazon.awssdk/http-auth-spi/2.22.9, Apache-2.0, approved, #12638 -maven/mavencentral/software.amazon.awssdk/http-auth-spi/2.24.1, , restricted, clearlydefined +maven/mavencentral/software.amazon.awssdk/http-auth-spi/2.24.1, Apache-2.0, approved, #13264 maven/mavencentral/software.amazon.awssdk/http-auth/2.22.9, Apache-2.0, approved, #12626 -maven/mavencentral/software.amazon.awssdk/http-auth/2.24.1, , restricted, clearlydefined +maven/mavencentral/software.amazon.awssdk/http-auth/2.24.1, Apache-2.0, approved, #13248 maven/mavencentral/software.amazon.awssdk/http-client-spi/2.22.9, Apache-2.0, approved, #12627 -maven/mavencentral/software.amazon.awssdk/http-client-spi/2.24.1, , restricted, clearlydefined +maven/mavencentral/software.amazon.awssdk/http-client-spi/2.24.1, Apache-2.0, approved, #13259 maven/mavencentral/software.amazon.awssdk/iam/2.22.9, Apache-2.0, approved, clearlydefined maven/mavencentral/software.amazon.awssdk/identity-spi/2.22.9, Apache-2.0, approved, #12636 -maven/mavencentral/software.amazon.awssdk/identity-spi/2.24.1, , restricted, clearlydefined +maven/mavencentral/software.amazon.awssdk/identity-spi/2.24.1, Apache-2.0, approved, #13244 maven/mavencentral/software.amazon.awssdk/json-utils/2.22.9, Apache-2.0, approved, #12646 -maven/mavencentral/software.amazon.awssdk/json-utils/2.24.1, , restricted, clearlydefined +maven/mavencentral/software.amazon.awssdk/json-utils/2.24.1, Apache-2.0, approved, #13261 maven/mavencentral/software.amazon.awssdk/metrics-spi/2.22.9, Apache-2.0, approved, #12649 -maven/mavencentral/software.amazon.awssdk/metrics-spi/2.24.1, , restricted, clearlydefined +maven/mavencentral/software.amazon.awssdk/metrics-spi/2.24.1, Apache-2.0, approved, #13239 maven/mavencentral/software.amazon.awssdk/netty-nio-client/2.22.9, Apache-2.0, approved, #12644 -maven/mavencentral/software.amazon.awssdk/netty-nio-client/2.24.1, , restricted, clearlydefined +maven/mavencentral/software.amazon.awssdk/netty-nio-client/2.24.1, Apache-2.0, approved, #13260 maven/mavencentral/software.amazon.awssdk/profiles/2.22.9, Apache-2.0, approved, #12620 -maven/mavencentral/software.amazon.awssdk/profiles/2.24.1, , restricted, clearlydefined +maven/mavencentral/software.amazon.awssdk/profiles/2.24.1, Apache-2.0, approved, #13258 maven/mavencentral/software.amazon.awssdk/protocol-core/2.22.9, Apache-2.0, approved, #12648 -maven/mavencentral/software.amazon.awssdk/protocol-core/2.24.1, , restricted, clearlydefined +maven/mavencentral/software.amazon.awssdk/protocol-core/2.24.1, Apache-2.0, approved, #13241 maven/mavencentral/software.amazon.awssdk/regions/2.22.9, Apache-2.0, approved, #12643 -maven/mavencentral/software.amazon.awssdk/regions/2.24.1, , restricted, clearlydefined -maven/mavencentral/software.amazon.awssdk/s3-transfer-manager/2.24.1, , restricted, clearlydefined +maven/mavencentral/software.amazon.awssdk/regions/2.24.1, Apache-2.0, approved, #13255 +maven/mavencentral/software.amazon.awssdk/s3-transfer-manager/2.24.1, Apache-2.0, approved, #13263 maven/mavencentral/software.amazon.awssdk/s3/2.22.9, Apache-2.0, approved, #12630 -maven/mavencentral/software.amazon.awssdk/s3/2.24.1, , restricted, clearlydefined +maven/mavencentral/software.amazon.awssdk/s3/2.24.1, Apache-2.0, approved, #13254 maven/mavencentral/software.amazon.awssdk/sdk-core/2.22.9, Apache-2.0, approved, #12639 -maven/mavencentral/software.amazon.awssdk/sdk-core/2.24.1, , restricted, clearlydefined +maven/mavencentral/software.amazon.awssdk/sdk-core/2.24.1, Apache-2.0, approved, #13265 maven/mavencentral/software.amazon.awssdk/sts/2.22.9, Apache-2.0, approved, clearlydefined maven/mavencentral/software.amazon.awssdk/third-party-jackson-core/2.22.9, Apache-2.0, approved, #12629 -maven/mavencentral/software.amazon.awssdk/third-party-jackson-core/2.24.1, , restricted, clearlydefined +maven/mavencentral/software.amazon.awssdk/third-party-jackson-core/2.24.1, Apache-2.0, approved, #13249 maven/mavencentral/software.amazon.awssdk/utils/2.22.9, Apache-2.0, approved, #12631 -maven/mavencentral/software.amazon.awssdk/utils/2.24.1, , restricted, clearlydefined +maven/mavencentral/software.amazon.awssdk/utils/2.24.1, Apache-2.0, approved, #13250 maven/mavencentral/software.amazon.eventstream/eventstream/1.0.1, Apache-2.0, approved, clearlydefined diff --git a/edc-extensions/cx-policy/build.gradle.kts b/edc-extensions/cx-policy/build.gradle.kts index 4e26c94bd..def8283d6 100644 --- a/edc-extensions/cx-policy/build.gradle.kts +++ b/edc-extensions/cx-policy/build.gradle.kts @@ -26,6 +26,7 @@ dependencies { implementation(project(":spi:ssi-spi")) implementation(libs.edc.spi.policyengine) implementation(libs.jakartaJson) + implementation(libs.edc.spi.identitytrust) testImplementation(libs.jacksonJsonP) testImplementation(libs.titaniumJsonLd) testImplementation(testFixtures(project(":spi:ssi-spi"))) diff --git a/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/framework/FrameworkAgreementConstraintFunction.java b/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/framework/FrameworkAgreementConstraintFunction.java index 2914cc3d1..d7a13ee5b 100644 --- a/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/framework/FrameworkAgreementConstraintFunction.java +++ b/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/framework/FrameworkAgreementConstraintFunction.java @@ -19,163 +19,200 @@ package org.eclipse.tractusx.edc.policy.cx.framework; -import jakarta.json.JsonObject; +import org.eclipse.edc.identitytrust.model.VerifiableCredential; +import org.eclipse.edc.policy.engine.spi.DynamicAtomicConstraintFunction; import org.eclipse.edc.policy.engine.spi.PolicyContext; import org.eclipse.edc.policy.model.Operator; import org.eclipse.edc.policy.model.Permission; import org.eclipse.edc.spi.agent.ParticipantAgent; -import org.eclipse.tractusx.edc.policy.cx.common.AbstractVpConstraintFunction; +import org.eclipse.edc.spi.result.Result; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; -import java.util.Objects; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.function.Predicate; -import static java.lang.String.format; -import static java.util.Objects.requireNonNull; -import static org.eclipse.edc.policy.model.Operator.EQ; -import static org.eclipse.edc.policy.model.Operator.GEQ; -import static org.eclipse.edc.policy.model.Operator.GT; -import static org.eclipse.tractusx.edc.iam.ssi.spi.jsonld.CredentialsNamespaces.CX_USE_CASE_NS; -import static org.eclipse.tractusx.edc.iam.ssi.spi.jsonld.CredentialsNamespaces.VP_PROPERTY; -import static org.eclipse.tractusx.edc.iam.ssi.spi.jsonld.JsonLdTypeFunctions.extractObjectsOfType; -import static org.eclipse.tractusx.edc.iam.ssi.spi.jsonld.JsonLdValueFunctions.extractStringValue; +import static org.eclipse.tractusx.edc.iam.ssi.spi.jsonld.CredentialsNamespaces.CX_NS_1_0; /** * Enforces a Framework Agreement constraint. *

- * A policy constraints requiring a usecase framework credential take a left operand in the form: - *

FrameworkAgreement.[type]
- *

- * The following example requires a client to present a sustainability credential: + * This function can parse "FrameworkAgreement" constraints as defined in this documentation: *

- * "constraint": {
- *     "leftOperand": "FrameworkAgreement.sustainability",
- *     "operator": "eq",
- *     "rightOperand": "active"
- * }
+ *     FrameworkAgreement EQ subtype[:version]
  * 
- *

- * NB: This function will be enabled in the 3.2 release. + * In addition, it will support the "legacy" notation, where the subtype is encoded in the left-operand: + *

+ *     FrameworkAgreement.subtype EQ active[:version]
+ * 
+ * Either notation is converted into a set of predicates which are applied to the list of credentials. If the resulting filtered list is empty, the + * policy is considered not fulfilled. Note that if the {@code version} is specified, it must be satisfied by the same + * credential that satisfies the {@code subtype} requirement. */ -public class FrameworkAgreementConstraintFunction extends AbstractVpConstraintFunction { - public static final String CONTRACT_VERSION_PROPERTY = CX_USE_CASE_NS + "/contractVersion"; +public class FrameworkAgreementConstraintFunction implements DynamicAtomicConstraintFunction { + public static final String CONTRACT_VERSION_PROPERTY = CX_NS_1_0 + "contractVersion"; + private static final String VC_CLAIM = "vc"; private static final String ACTIVE = "active"; - private String agreementType; - private String agreementVersion; + private static final String FRAMEWORK_AGREEMENT_LITERAL = "FrameworkAgreement"; + private static final String CREDENTIAL_LITERAL = "Credential"; + private static final Collection ALLOWED_OPERATORS = List.of(Operator.EQ, Operator.NEQ); - private FrameworkAgreementConstraintFunction(String credentialType) { - super(credentialType); + public FrameworkAgreementConstraintFunction() { } + /** + * Evaluates the constraint's left-operand and right-operand against a list of {@link VerifiableCredential} objects. + * + * @param leftValue the left-side expression for the constraint. Must be either {@code FrameworkAgreement} or {@code FrameworkAgreement.subtype}. + * @param operator the operation Must be {@link Operator#EQ} or {@link Operator#NEQ} + * @param rightValue the right-side expression for the constraint. Must be a string that is either {@code "active":[version]} or {@code subtype[:version]}. + * @param rule the rule associated with the constraint. Ignored by this function. + * @param context the policy context. Must contain the {@link ParticipantAgent}, which in turn must contain a list of {@link VerifiableCredential} stored + * in its claims using the {@code "vc"} key. + * @return true if at least one credential satisfied the requirement imposed by the constraint. + */ @Override - public boolean evaluate(Operator operator, Object rightValue, Permission permission, PolicyContext context) { - if (!validateOperator(operator, context, EQ, GT, GEQ)) { + public boolean evaluate(Object leftValue, Operator operator, Object rightValue, Permission rule, PolicyContext context) { + + if (!ALLOWED_OPERATORS.contains(operator)) { + context.reportProblem("Invalid operator: allowed operators are %s, got '%s'.".formatted(ALLOWED_OPERATORS, operator)); return false; } - if (!validateRightOperand(ACTIVE, rightValue, context)) { + // we do not support list-type right-operands + if (!(leftValue instanceof String) || !(rightValue instanceof String)) { + context.reportProblem("Both the right- and left-operand must be of type String but were '%s' and '%s', respectively.".formatted(leftValue.getClass(), rightValue.getClass())); return false; } - var vp = (JsonObject) context.getContextData(ParticipantAgent.class).getClaims().get(VP_PROPERTY); - if (!validatePresentation(vp, context)) { + // make sure the ParticipantAgent is there + var participantAgent = context.getContextData(ParticipantAgent.class); + if (participantAgent == null) { + context.reportProblem("Required PolicyContext data not found: " + ParticipantAgent.class.getName()); return false; } - return extractObjectsOfType(credentialType, vp) - .map(credential -> extractCredentialSubject(credential, context)) - .filter(Objects::nonNull) - .anyMatch(credentialSubject -> validateUseCase(credentialSubject, operator, context)); - } + var leftOperand = leftValue.toString(); + var rightOperand = rightValue.toString(); + Result>> predicateResult; - private boolean validateUseCase(JsonObject credentialSubject, Operator operator, PolicyContext context) { - var usecaseAgreement = extractObjectsOfType(agreementType, credentialSubject).findFirst().orElse(null); - if (usecaseAgreement == null) { - context.reportProblem(format("%s is missing the usecase type: %s", credentialType, agreementType)); + if (leftOperand.startsWith(FRAMEWORK_AGREEMENT_LITERAL + ".")) { // legacy notation + predicateResult = getFilterPredicateLegacy(leftOperand, rightOperand); + + } else if (leftOperand.startsWith(FRAMEWORK_AGREEMENT_LITERAL)) { // new notation + predicateResult = getFilterPredicate(rightOperand); + } else { //invalid notation + context.reportProblem("Constraint left-operand must start with '%s' but was '%s'.".formatted(FRAMEWORK_AGREEMENT_LITERAL, leftValue)); return false; } - return validateVersion(context, operator, usecaseAgreement); - } - - private boolean validateVersion(PolicyContext context, Operator operator, JsonObject usecaseAgreement) { - if (agreementVersion == null) { - return true; + if (predicateResult.failed()) { // couldn't extract subtype/version predicate from constraint + context.reportProblem(predicateResult.getFailureDetail()); + return false; } - var version = extractStringValue(usecaseAgreement.get(CONTRACT_VERSION_PROPERTY)); - if (version == null || version.trim().length() == 0) { - context.reportProblem(format("%s is missing a %s property", credentialType, CONTRACT_VERSION_PROPERTY)); + + var vcListResult = getCredentialList(participantAgent); + if (vcListResult.failed()) { // couldn't extract credential list from agent + context.reportProblem(vcListResult.getFailureDetail()); return false; } + var rootPredicate = reducePredicates(predicateResult.getContent(), operator); + var credentials = vcListResult.getContent().stream().filter(rootPredicate).toList(); - switch (operator) { - case EQ -> { - if (!version.equals(agreementVersion)) { - context.reportProblem(format("%s version %s does not match required version: %s", credentialType, version, agreementVersion)); - return false; - } - return true; - } - case GT -> { - if (version.compareTo(agreementVersion) <= 0) { - context.reportProblem(format("%s version %s must be at greater than the required version: %s", credentialType, version, agreementVersion)); - return false; - } - return true; - } - case GEQ -> { - if (version.compareTo(agreementVersion) < 0) { - context.reportProblem(format("%s version %s must be at least the required version: %s", credentialType, version, agreementVersion)); - return false; - } - return true; - } - default -> { - return false; - } + if (credentials.isEmpty()) { + context.reportProblem("No credentials found that match the give Policy constraint: [%s %s %s]".formatted(leftValue.toString(), operator.toString(), rightValue.toString())); + return false; } + return true; + } /** - * Configures a new constraint instance. + * Returns {@code true} if the left-operand starts with {@link FrameworkAgreementConstraintFunction#FRAMEWORK_AGREEMENT_LITERAL}, {@link false} otherwise. */ - public static class Builder { - private final FrameworkAgreementConstraintFunction constraint; + @Override + public boolean canHandle(Object leftValue) { + return leftValue instanceof String && leftValue.toString().startsWith(FRAMEWORK_AGREEMENT_LITERAL); + } - private Builder(String credentialType) { - constraint = new FrameworkAgreementConstraintFunction(credentialType); - } + @NotNull + private Predicate reducePredicates(List> predicates, Operator operator) { + return Operator.EQ.equals(operator) ? + predicates.stream().reduce(Predicate::and).orElse(x -> true) : + predicates.stream().map(Predicate::negate).reduce(Predicate::and).orElse(x -> true); + } - /** - * Sets the framework agreement type. - */ - public Builder agreementType(String agreementType) { - constraint.agreementType = agreementType; - return this; + /** + * Extracts a {@link List} of {@link VerifiableCredential} objects from the {@link ParticipantAgent}. Credentials must be + * stored in the agent's claims map using the "vc" key. + */ + private Result> getCredentialList(ParticipantAgent agent) { + var vcListClaim = agent.getClaims().get(VC_CLAIM); + + if (vcListClaim == null) { + return Result.failure("ParticipantAgent did not contain a '%s' claim.".formatted(VC_CLAIM)); + } + if (!(vcListClaim instanceof List)) { + return Result.failure("ParticipantAgent contains a '%s' claim, but the type is incorrect. Expected %s, got %s.".formatted(VC_CLAIM, List.class.getName(), vcListClaim.getClass().getName())); + } + var vcList = (List) vcListClaim; + if (vcList.isEmpty()) { + return Result.failure("ParticipantAgent contains a '%s' claim but it did not contain any VerifiableCredentials.".formatted(VC_CLAIM)); } + return Result.success(vcList); + } - /** - * Sets the optional required agreement version. Equals, greater than, and greater than or equals operations are supported. - */ - public Builder agreementVersion(String version) { - constraint.agreementVersion = version; - return this; + /** + * Converts the right-operand (new notation) into either 1 or 2 predicates, depending on whether the version was encoded or not. + */ + private Result>> getFilterPredicate(String rightOperand) { + var tokens = rightOperand.split(":"); + if (tokens.length > 2 || tokens.length == 0 || tokens[0] == null || tokens[0].isEmpty()) { + return Result.failure("Right-operand must contain the sub-type followed by an optional version string: [:version], but was '%s'.".formatted(rightOperand)); } + var subtype = tokens[0]; + var version = tokens.length == 2 ? tokens[1] : null; + + return Result.success(createPredicates(subtype, version)); + } - public FrameworkAgreementConstraintFunction build() { - requireNonNull(constraint.agreementType, "agreementType"); - return constraint; + /** + * Converts the left- and right-operand (legacy notation) into either 1 or 2 predicates, depending on whether the version was encoded or not. + */ + private Result>> getFilterPredicateLegacy(String leftOperand, String rightOperand) { + var subType = leftOperand.replace(FRAMEWORK_AGREEMENT_LITERAL + ".", ""); + if (subType.isEmpty()) { + return Result.failure("Left-operand must contain the sub-type 'FrameworkAgreement.'."); + } + if (!rightOperand.startsWith(ACTIVE)) { + return Result.failure("Right-operand must contain the keyword 'active' followed by an optional version string: 'active'[:version], but was '%s'.".formatted(rightOperand)); + } + var version = rightOperand.replace(ACTIVE, "").replace(":", ""); + if (version.isEmpty()) { + version = null; } - /** - * Ctor. - * - * @param credentialType the framework credential type required by the constraint instance. - * @return the builder - */ - public static Builder newInstance(String credentialType) { - return new Builder(credentialType); + return Result.success(createPredicates(subType, version)); + } + + @NotNull + private List> createPredicates(String subtype, @Nullable String version) { + var list = new ArrayList>(); + list.add(credential -> credential.getTypes().contains(capitalize(subtype) + CREDENTIAL_LITERAL)); + if (version != null) { + list.add(credential -> credential.getCredentialSubject().stream().anyMatch(cs -> cs.getClaims().get(CONTRACT_VERSION_PROPERTY).equals(version))); } + return list; } + /** + * Capitalizes (makes uppercase) the first character of a non-null input string. + */ + private String capitalize(@NotNull String input) { + return input.substring(0, 1).toUpperCase() + input.substring(1); + } } diff --git a/edc-extensions/cx-policy/src/test/java/org/eclipse/tractusx/edc/policy/cx/framework/FrameworkAgreementConstraintFunctionTest.java b/edc-extensions/cx-policy/src/test/java/org/eclipse/tractusx/edc/policy/cx/framework/FrameworkAgreementConstraintFunctionTest.java index 3c7c49ef9..9d9c0ceef 100644 --- a/edc-extensions/cx-policy/src/test/java/org/eclipse/tractusx/edc/policy/cx/framework/FrameworkAgreementConstraintFunctionTest.java +++ b/edc-extensions/cx-policy/src/test/java/org/eclipse/tractusx/edc/policy/cx/framework/FrameworkAgreementConstraintFunctionTest.java @@ -19,129 +19,298 @@ package org.eclipse.tractusx.edc.policy.cx.framework; -import com.fasterxml.jackson.core.JsonProcessingException; -import jakarta.json.JsonObject; +import org.eclipse.edc.identitytrust.model.CredentialSubject; +import org.eclipse.edc.identitytrust.model.Issuer; +import org.eclipse.edc.identitytrust.model.VerifiableCredential; import org.eclipse.edc.policy.engine.spi.PolicyContext; +import org.eclipse.edc.policy.model.Operator; import org.eclipse.edc.policy.model.Permission; import org.eclipse.edc.spi.agent.ParticipantAgent; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; -import org.mockito.Mockito; +import java.time.Instant; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.List; import java.util.Map; +import java.util.UUID; import static org.assertj.core.api.Assertions.assertThat; -import static org.eclipse.edc.policy.model.Operator.EQ; -import static org.eclipse.edc.policy.model.Operator.GEQ; -import static org.eclipse.edc.policy.model.Operator.GT; -import static org.eclipse.tractusx.edc.iam.ssi.spi.jsonld.CredentialsNamespaces.CX_USE_CASE_NS_V1; -import static org.eclipse.tractusx.edc.iam.ssi.spi.jsonld.CredentialsNamespaces.VP_PROPERTY; -import static org.eclipse.tractusx.edc.iam.ssi.spi.jsonld.JsonLdTextFixtures.createObjectMapper; -import static org.eclipse.tractusx.edc.iam.ssi.spi.jsonld.JsonLdTextFixtures.expand; -import static org.eclipse.tractusx.edc.policy.cx.framework.PcfCredential.PCF_VP; -import static org.eclipse.tractusx.edc.policy.cx.framework.UseCaseContext.USE_CASE_CONTEXT; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.startsWith; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; class FrameworkAgreementConstraintFunctionTest { - private static final Map CONTEXT_CACHE = Map.of(CX_USE_CASE_NS_V1, USE_CASE_CONTEXT); + private final FrameworkAgreementConstraintFunction function = new FrameworkAgreementConstraintFunction(); + private final PolicyContext context = mock(); private Permission permission; - private PolicyContext context; + private ParticipantAgent participantAgent; - @Test - void verify_constraint() throws JsonProcessingException { - var function = FrameworkAgreementConstraintFunction.Builder - .newInstance("PcfCredential") - .agreementType("PcfAgreement") - .build(); - - setVpInContextVp(); - - var result = function.evaluate(EQ, "active", permission, context); - - assertThat(result).isTrue(); + @BeforeEach + void setup() { + participantAgent = mock(ParticipantAgent.class); + when(context.getContextData(eq(ParticipantAgent.class))) + .thenReturn(participantAgent); } @Test - void verify_contract_version() throws JsonProcessingException { - var function = FrameworkAgreementConstraintFunction.Builder - .newInstance("PcfCredential") - .agreementType("PcfAgreement") - .agreementVersion("1.0.0") - .build(); - - setVpInContextVp(); - - var result = function.evaluate(EQ, "active", permission, context); - assertThat(result).isTrue(); - - result = function.evaluate(GEQ, "active", permission, context); - assertThat(result).isTrue(); + void evaluate_leftOperandInvalid() { + assertThat(function.evaluate("ThisIsInvalid", Operator.EQ, "irrelevant", permission, context)).isFalse(); + verify(context).reportProblem(startsWith("Constraint left-operand must start with 'FrameworkAgreement'")); + } - result = function.evaluate(GT, "active", permission, context); - assertThat(result).isFalse(); // should fail because version is equal + @Test + void evaluate_invalidOperator() { + assertThat(function.evaluate("FrameworkAgreement.foobar", Operator.HAS_PART, "irrelevant", permission, context)).isFalse(); + verify(context).reportProblem(eq("Invalid operator: allowed operators are [EQ, NEQ], got 'HAS_PART'.")); + verifyNoMoreInteractions(context); } @Test - void verify_contract_version_gt_fail() throws JsonProcessingException { - var function = FrameworkAgreementConstraintFunction.Builder - .newInstance("PcfCredential") - .agreementType("PcfAgreement") - .agreementVersion("2.0.0") - .build(); + void evaluate_noParticipantOnContext() { + when(context.getContextData(eq(ParticipantAgent.class))).thenReturn(null); + assertThat(function.evaluate("FrameworkAgreement.foobar", Operator.EQ, "irrelevant", permission, context)).isFalse(); + verify(context).reportProblem(eq("Required PolicyContext data not found: " + ParticipantAgent.class.getName())); + verify(context).getContextData(eq(ParticipantAgent.class)); + verifyNoMoreInteractions(context); + } - setVpInContextVp(); + @Test + void evaluate_vcClaimNotPresent() { + when(participantAgent.getClaims()).thenReturn(Map.of()); + assertThat(function.evaluate("FrameworkAgreement.foobar", Operator.EQ, "active", permission, context)).isFalse(); + verify(context).reportProblem(eq("ParticipantAgent did not contain a 'vc' claim.")); + } - var result = function.evaluate(GT, "active", permission, context); - assertThat(result).isFalse(); // should fail because version is equal + @Test + void evaluate_vcClaimNotListOfCredentials() { + when(participantAgent.getClaims()).thenReturn(Map.of( + "vc", new Object() + )); + assertThat(function.evaluate("FrameworkAgreement.foobar", Operator.EQ, "active:0.0.1", permission, context)).isFalse(); + verify(context).reportProblem(eq("ParticipantAgent contains a 'vc' claim, but the type is incorrect. Expected java.util.List, got java.lang.Object.")); + } - verify(context, times(1)).reportProblem(Mockito.contains("version")); + @Test + void evaluate_vcClaimCredentialsEmpty() { + when(participantAgent.getClaims()).thenReturn(Map.of( + "vc", new ArrayList() + )); + assertThat(function.evaluate("FrameworkAgreement.foobar", Operator.EQ, "active", permission, context)).isFalse(); + verify(context).reportProblem(eq("ParticipantAgent contains a 'vc' claim but it did not contain any VerifiableCredentials.")); } @Test - void verify_invalid_agreement_fail() throws JsonProcessingException { - var function = FrameworkAgreementConstraintFunction.Builder - .newInstance("PcfCredential") - .agreementType("UnknownAgreement") - .build(); + void evaluate_rightOperandInvalidFormat() { + when(participantAgent.getClaims()).thenReturn(Map.of( + "vc", List.of(createPcfCredential().build()) + )); + assertThat(function.evaluate("FrameworkAgreement.pcf", Operator.EQ, "/violate$", permission, context)).isFalse(); + verify(context).reportProblem(eq("Right-operand must contain the keyword 'active' followed by an optional version string: 'active'[:version], but was '/violate$'.")); + } - setVpInContextVp(); + @Test + void evaluate_requiredCredentialNotFound() { + when(participantAgent.getClaims()).thenReturn(Map.of( + "vc", List.of( + createCredential("PcfCredential", "1.3.0").build(), + createCredential("PcfCredential", "1.0.0").build()) + )); + assertThat(function.evaluate("FrameworkAgreement", Operator.EQ, "someOther:1.3.0", permission, context)).isFalse(); + } - var result = function.evaluate(EQ, "active", permission, context); + @Test + void evaluate_requiredCredential_wrongVersion() { + when(participantAgent.getClaims()).thenReturn(Map.of( + "vc", List.of( + createCredential("SomeOtherCredential", "2.0.0").build(), + createCredential("PcfCredential", "1.8.0").build(), + createCredential("PcfCredential", "1.0.0").build()) + )); + assertThat(function.evaluate("FrameworkAgreement", Operator.EQ, "pcf:1.3.0", permission, context)).isFalse(); + } - assertThat(result).isFalse(); + @Test + void evaluate_requiredCredentialFound() { + when(participantAgent.getClaims()).thenReturn(Map.of( + "vc", List.of( + createCredential("PcfCredential", "6.0.0").build(), + createCredential("SomeOtherType", "3.4.1").build() + ) + )); + assertThat(function.evaluate("FrameworkAgreement", Operator.EQ, "pcf", permission, context)).isTrue(); + } - verify(context, times(1)).reportProblem(Mockito.contains("missing the usecase type")); + @Test + void evaluate_requiredCredentialFound_withCorrectVersion() { + when(participantAgent.getClaims()).thenReturn(Map.of( + "vc", List.of( + createCredential("PcfCredential", "2.0.0").build(), + createCredential("PcfCredential", "1.3.0").build(), + createCredential("PcfCredential", "1.0.0").build()) + )); + assertThat(function.evaluate("FrameworkAgreement", Operator.EQ, "pcf:1.3.0", permission, context)).isTrue(); } @Test - void verify_no_credential_fail() { - var function = FrameworkAgreementConstraintFunction.Builder - .newInstance("PcfCredential") - .agreementType("PcfAgreement") - .build(); + void evaluate_neq_requiredCredentialFound() { + when(participantAgent.getClaims()).thenReturn(Map.of( + "vc", List.of( + createCredential("PcfCredential", "6.0.0").build(), + createCredential("SomeOtherType", "3.4.1").build() + ) + )); + assertThat(function.evaluate("FrameworkAgreement", Operator.NEQ, "sustainability", permission, context)).isTrue(); + } - when(context.getContextData(ParticipantAgent.class)).thenReturn(new ParticipantAgent(Map.of(), Map.of())); + @Test + void evaluate_neq_oneOfManyViolates() { + when(participantAgent.getClaims()).thenReturn(Map.of( + "vc", List.of( + createCredential("PcfCredential", "6.0.0").build(), + createCredential("SustainabilityCredential", "6.0.0").build(), + createCredential("SomeOtherType", "3.4.1").build() + ) + )); + assertThat(function.evaluate("FrameworkAgreement", Operator.NEQ, "sustainability", permission, context)).isTrue(); + } - var result = function.evaluate(EQ, "active", permission, context); + @Test + void evaluate_neq_oneViolates() { + when(participantAgent.getClaims()).thenReturn(Map.of( + "vc", List.of( + createCredential("SustainabilityCredential", "6.0.0").build() + ) + )); + assertThat(function.evaluate("FrameworkAgreement", Operator.NEQ, "sustainability", permission, context)).isFalse(); + } + + @Test + void evaluate_neq_requiredCredentialFound_withCorrectVersion() { + when(participantAgent.getClaims()).thenReturn(Map.of( + "vc", List.of( + createCredential("PcfCredential", "2.0.0").build(), + createCredential("FooBarCredential", "1.3.0").build(), + createCredential("BarBazCredential", "1.0.0").build()) + )); + assertThat(function.evaluate("FrameworkAgreement", Operator.NEQ, "sustainability:1.3.0", permission, context)).isTrue(); + } - assertThat(result).isFalse(); - verify(context, times(1)).reportProblem(Mockito.contains("VP not found")); + private VerifiableCredential.Builder createCredential(String type, String version) { + return VerifiableCredential.Builder.newInstance() + .types(List.of("VerifiableCredential", type)) + .id(UUID.randomUUID().toString()) + .issuer(new Issuer(UUID.randomUUID().toString(), Map.of("prop1", "val1"))) + .expirationDate(Instant.now().plus(365, ChronoUnit.DAYS)) + .issuanceDate(Instant.now()) + .credentialSubject(CredentialSubject.Builder.newInstance() + .id("subject-id") + .claim("https://w3id.org/catenax/credentials/v1.0.0/holderIdentifier", "did:web:holder") + .claim("https://w3id.org/catenax/credentials/v1.0.0/contractVersion", version) + .claim("https://w3id.org/catenax/credentials/v1.0.0/contractTemplate", "https://public.catena-x.org/contracts/pcf.v1.pdf") + .build()); } - @BeforeEach - void setUp() { - permission = Permission.Builder.newInstance().build(); - context = mock(PolicyContext.class); + private VerifiableCredential.Builder createPcfCredential() { + return createCredential("PcfCredential", "1.0.0"); } - private void setVpInContextVp() throws JsonProcessingException { - var vp = expand(createObjectMapper().readValue(PCF_VP, JsonObject.class), CONTEXT_CACHE); - when(context.getContextData(ParticipantAgent.class)).thenReturn(new ParticipantAgent(Map.of(VP_PROPERTY, vp), Map.of())); + @Nested + class LegacyLeftOperand { + @Test + void evaluate_leftOperand_notContainSubtype() { + when(participantAgent.getClaims()).thenReturn(Map.of( + "vc", List.of(createPcfCredential().build()) + )); + assertThat(function.evaluate("FrameworkAgreement.", Operator.EQ, "active:0.4.2", permission, context)).isFalse(); + verify(context).reportProblem(eq("Left-operand must contain the sub-type 'FrameworkAgreement.'.")); + } + + @Test + void evaluate_leftOperand_notContainFrameworkLiteral() { + when(participantAgent.getClaims()).thenReturn(Map.of( + "vc", List.of(createPcfCredential().build()) + )); + assertThat(function.evaluate("foobar.pcf", Operator.EQ, "active:0.4.2", permission, context)).isFalse(); + verify(context).reportProblem(startsWith("Constraint left-operand must start with 'FrameworkAgreement' but was")); + } + + @Test + void evaluate_leftOperand_notStartsWithFrameworkLiteral() { + when(participantAgent.getClaims()).thenReturn(Map.of( + "vc", List.of(createPcfCredential().build()) + )); + assertThat(function.evaluate("foobarFrameworkAgreement.pcf", Operator.EQ, "active:0.4.2", permission, context)).isFalse(); + verify(context).reportProblem(startsWith("Constraint left-operand must start with 'FrameworkAgreement' but was")); + } + + @Test + void evaluate_rightOperand_notStartWithActiveLiteral() { + when(participantAgent.getClaims()).thenReturn(Map.of( + "vc", List.of(createPcfCredential().build()) + )); + assertThat(function.evaluate("FrameworkAgreement.pcf", Operator.EQ, "violates", permission, context)).isFalse(); + verify(context).reportProblem(eq("Right-operand must contain the keyword 'active' followed by an optional version string: 'active'[:version], but was 'violates'.")); + } + + @Test + void evaluate_rightOperandWithVersion() { + when(participantAgent.getClaims()).thenReturn(Map.of( + "vc", List.of(createPcfCredential().build()) + )); + assertThat(function.evaluate("FrameworkAgreement.pcf", Operator.EQ, "active:1.0.0", permission, context)).isTrue(); + assertThat(function.evaluate("FrameworkAgreement.pcf", Operator.EQ, "active:5.3.1", permission, context)).isFalse(); + } + + @Test + void evaluate_rightOperand() { + when(participantAgent.getClaims()).thenReturn(Map.of( + "vc", List.of(createPcfCredential().build()) + )); + assertThat(function.evaluate("FrameworkAgreement.pcf", Operator.EQ, "active", permission, context)).isTrue(); + } } - + @Nested + class NewLeftOperand { + @Test + void evaluate_leftOperandNotFrameworkLiteral() { + when(participantAgent.getClaims()).thenReturn(Map.of( + "vc", List.of(createPcfCredential().build()) + )); + assertThat(function.evaluate("Foobar", Operator.EQ, "active:0.4.2", permission, context)).isFalse(); + verify(context).reportProblem(eq("Constraint left-operand must start with 'FrameworkAgreement' but was 'Foobar'.")); + } + + @Test + void evaluate_rightOperand_onlySubtype() { + when(participantAgent.getClaims()).thenReturn(Map.of( + "vc", List.of(createPcfCredential().build()) + )); + assertThat(function.evaluate("FrameworkAgreement", Operator.EQ, "pcf", permission, context)).isTrue(); + } + + @Test + void evaluate_rightOperand_withVersion() { + when(participantAgent.getClaims()).thenReturn(Map.of( + "vc", List.of(createPcfCredential().build()) + )); + assertThat(function.evaluate("FrameworkAgreement", Operator.EQ, "pcf:1.0.0", permission, context)).isTrue(); + assertThat(function.evaluate("FrameworkAgreement", Operator.EQ, "pcf:4.2.0", permission, context)).isFalse(); + } + + @Test + void evaluate_rightOperandMissesSubtype() { + when(participantAgent.getClaims()).thenReturn(Map.of( + "vc", List.of(createPcfCredential().build()) + )); + assertThat(function.evaluate("FrameworkAgreement", Operator.EQ, ":1.0.0", permission, context)).isFalse(); + } + } } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 35a01b066..b95140619 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -2,7 +2,7 @@ format.version = "1.1" [versions] -edc = "0.5.1" +edc = "0.5.2-SNAPSHOT" apache-sshd = "2.12.0" assertj = "3.25.3" awaitility = "4.2.0" @@ -39,6 +39,7 @@ edc-spi-controlplane = { module = "org.eclipse.edc:control-plane-spi", version.r edc-controlplane-apiclient = { module = "org.eclipse.edc:control-plane-api-client", version.ref = "edc" } edc-spi-web = { module = "org.eclipse.edc:web-spi", version.ref = "edc" } edc-spi-http = { module = "org.eclipse.edc:http-spi", version.ref = "edc" } +edc-spi-identitytrust = { module = "org.eclipse.edc:identity-trust-spi", version.ref = "edc" } edc-spi-jsonld = { module = "org.eclipse.edc:json-ld-spi", version.ref = "edc" } edc-spi-jwt = { module = "org.eclipse.edc:jwt-spi", version.ref = "edc" } edc-spi-token = { module = "org.eclipse.edc:token-spi", version.ref = "edc" } diff --git a/spi/ssi-spi/src/main/java/org/eclipse/tractusx/edc/iam/ssi/spi/jsonld/CredentialsNamespaces.java b/spi/ssi-spi/src/main/java/org/eclipse/tractusx/edc/iam/ssi/spi/jsonld/CredentialsNamespaces.java index dee293b0d..b622d5d11 100644 --- a/spi/ssi-spi/src/main/java/org/eclipse/tractusx/edc/iam/ssi/spi/jsonld/CredentialsNamespaces.java +++ b/spi/ssi-spi/src/main/java/org/eclipse/tractusx/edc/iam/ssi/spi/jsonld/CredentialsNamespaces.java @@ -27,13 +27,21 @@ public interface CredentialsNamespaces { String W3C_VC_PREFIX = "https://www.w3.org/2018/credentials"; String W3C_VC_NS = W3C_VC_PREFIX + "/v1"; String VP_PROPERTY = "vp"; + @Deprecated String CX_NS = "https://w3id.org/2023/catenax/credentials/"; + @Deprecated String CX_SUMMARY_NS = CX_NS + "summary"; + @Deprecated String CX_SUMMARY_NS_V1 = CX_SUMMARY_NS + "/v1"; + @Deprecated String SUMMARY_CREDENTIAL_TYPE = CX_SUMMARY_NS + "/SummaryCredential"; + @Deprecated String HOLDER_IDENTIFIER = CX_SUMMARY_NS + "/holderIdentifier"; + @Deprecated String CX_USE_CASE_NS = CX_NS + "usecase"; + @Deprecated String CX_USE_CASE_NS_V1 = CX_USE_CASE_NS + "/v1"; + String CX_NS_1_0 = "https://w3id.org/catenax/credentials/v1.0.0/"; String CX_SUMMARY_CREDENTIAL = "SummaryCredential"; String CREDENTIAL_SUBJECT = W3C_VC_PREFIX + "#credentialSubject"; String CREDENTIAL_ISSUER = W3C_VC_PREFIX + "#issuer"; From 3a5e352b039b786399774b275252f7924e816e86 Mon Sep 17 00:00:00 2001 From: Enrico Risa Date: Fri, 16 Feb 2024 11:01:27 +0100 Subject: [PATCH 012/100] chore: trivy fix (#1061) --- .github/workflows/trivy.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/trivy.yml b/.github/workflows/trivy.yml index bd8f6db98..2005fb6aa 100644 --- a/.github/workflows/trivy.yml +++ b/.github/workflows/trivy.yml @@ -62,7 +62,7 @@ jobs: with: scan-type: "config" # ignore-unfixed: true - exit-code: "1" + exit-code: "0" hide-progress: false format: "sarif" output: "trivy-results-config.sarif" @@ -107,7 +107,7 @@ jobs: image-ref: "tractusx/${{ matrix.image }}:sha-${{ needs.git-sha7.outputs.value }}" format: "sarif" output: "trivy-results-${{ matrix.image }}.sarif" - exit-code: "1" + exit-code: "0" severity: "CRITICAL,HIGH" timeout: "10m0s" - name: Upload Trivy scan results to GitHub Security tab From 2b67545dd8669147b9e8d4d0a011c63a4c3ce736 Mon Sep 17 00:00:00 2001 From: Paul Latzelsperger <43503240+paullatzelsperger@users.noreply.github.com> Date: Fri, 16 Feb 2024 11:01:39 +0100 Subject: [PATCH 013/100] feat: add Dismantler constraint eval function (#1059) * add dismantler function impl * refactoring * javadoc * checkstyle * javaodc * Apply suggestions from code review Co-authored-by: Jim Marino * cleanup --------- Co-authored-by: Jim Marino --- .../AbstractDynamicConstraintFunction.java | 76 +++ .../cx/common/CredentialTypePredicate.java | 37 ++ .../DismantlerConstraintFunction.java | 169 +++++++ .../FrameworkAgreementConstraintFunction.java | 37 +- .../edc/policy/cx/CredentialFunctions.java | 75 +++ .../DismantlerConstraintFunctionTest.java | 440 ++++++++++++++++++ ...meworkAgreementConstraintFunctionTest.java | 32 +- 7 files changed, 808 insertions(+), 58 deletions(-) create mode 100644 edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/common/AbstractDynamicConstraintFunction.java create mode 100644 edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/common/CredentialTypePredicate.java create mode 100644 edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/dismantler/DismantlerConstraintFunction.java create mode 100644 edc-extensions/cx-policy/src/test/java/org/eclipse/tractusx/edc/policy/cx/CredentialFunctions.java create mode 100644 edc-extensions/cx-policy/src/test/java/org/eclipse/tractusx/edc/policy/cx/dismantler/DismantlerConstraintFunctionTest.java diff --git a/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/common/AbstractDynamicConstraintFunction.java b/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/common/AbstractDynamicConstraintFunction.java new file mode 100644 index 000000000..9ffe3bbb5 --- /dev/null +++ b/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/common/AbstractDynamicConstraintFunction.java @@ -0,0 +1,76 @@ +/******************************************************************************** + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +package org.eclipse.tractusx.edc.policy.cx.common; + +import org.eclipse.edc.identitytrust.model.VerifiableCredential; +import org.eclipse.edc.policy.engine.spi.DynamicAtomicConstraintFunction; +import org.eclipse.edc.policy.engine.spi.PolicyContext; +import org.eclipse.edc.policy.model.Operator; +import org.eclipse.edc.policy.model.Permission; +import org.eclipse.edc.spi.agent.ParticipantAgent; +import org.eclipse.edc.spi.result.Result; + +import java.util.Arrays; +import java.util.Collection; +import java.util.List; + +/** + * This is a base class for dynamically bound Tractus-X constraint evaluation functions that implements some basic common functionality and defines some + * common constants + */ +public abstract class AbstractDynamicConstraintFunction implements DynamicAtomicConstraintFunction { + public static final String VC_CLAIM = "vc"; + public static final String ACTIVE = "active"; + public static final String CREDENTIAL_LITERAL = "Credential"; + protected static final Collection EQUALITY_OPERATORS = List.of(Operator.EQ, Operator.NEQ); + + protected boolean checkOperator(Operator actual, PolicyContext context, Operator... expectedOperators) { + return checkOperator(actual, context, Arrays.asList(expectedOperators)); + } + + protected boolean checkOperator(Operator actual, PolicyContext context, Collection expectedOperators) { + if (!expectedOperators.contains(actual)) { + context.reportProblem("Invalid operator: this constraint only allows the following operators: %s, but received '%s'.".formatted(EQUALITY_OPERATORS, actual)); + return false; + } + return true; + } + + /** + * Extracts a {@link List} of {@link VerifiableCredential} objects from the {@link ParticipantAgent}. Credentials must be + * stored in the agent's claims map using the "vc" key. + */ + protected Result> getCredentialList(ParticipantAgent agent) { + var vcListClaim = agent.getClaims().get(VC_CLAIM); + + if (vcListClaim == null) { + return Result.failure("ParticipantAgent did not contain a '%s' claim.".formatted(VC_CLAIM)); + } + if (!(vcListClaim instanceof List)) { + return Result.failure("ParticipantAgent contains a '%s' claim, but the type is incorrect. Expected %s, received %s.".formatted(VC_CLAIM, List.class.getName(), vcListClaim.getClass().getName())); + } + var vcList = (List) vcListClaim; + if (vcList.isEmpty()) { + return Result.failure("ParticipantAgent contains a '%s' claim but it did not contain any VerifiableCredentials.".formatted(VC_CLAIM)); + } + return Result.success(vcList); + } + +} diff --git a/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/common/CredentialTypePredicate.java b/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/common/CredentialTypePredicate.java new file mode 100644 index 000000000..0fc858efd --- /dev/null +++ b/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/common/CredentialTypePredicate.java @@ -0,0 +1,37 @@ +/******************************************************************************** + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +package org.eclipse.tractusx.edc.policy.cx.common; + +import org.eclipse.edc.identitytrust.model.VerifiableCredential; + +import java.util.function.Predicate; + +public class CredentialTypePredicate implements Predicate { + private final String expectedType; + + public CredentialTypePredicate(String expectedType) { + this.expectedType = expectedType; + } + + @Override + public boolean test(VerifiableCredential credential) { + return credential.getTypes().contains(expectedType); + } +} diff --git a/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/dismantler/DismantlerConstraintFunction.java b/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/dismantler/DismantlerConstraintFunction.java new file mode 100644 index 000000000..7013a4cc7 --- /dev/null +++ b/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/dismantler/DismantlerConstraintFunction.java @@ -0,0 +1,169 @@ +/******************************************************************************** + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +package org.eclipse.tractusx.edc.policy.cx.dismantler; + +import org.eclipse.edc.identitytrust.model.VerifiableCredential; +import org.eclipse.edc.policy.engine.spi.PolicyContext; +import org.eclipse.edc.policy.model.Operator; +import org.eclipse.edc.policy.model.Permission; +import org.eclipse.edc.spi.agent.ParticipantAgent; +import org.eclipse.tractusx.edc.policy.cx.common.AbstractDynamicConstraintFunction; +import org.eclipse.tractusx.edc.policy.cx.common.CredentialTypePredicate; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.function.Predicate; + +import static org.eclipse.edc.policy.model.Operator.EQ; +import static org.eclipse.edc.policy.model.Operator.IN; +import static org.eclipse.edc.policy.model.Operator.IS_ANY_OF; +import static org.eclipse.edc.policy.model.Operator.IS_NONE_OF; +import static org.eclipse.edc.policy.model.Operator.NEQ; +import static org.eclipse.tractusx.edc.iam.ssi.spi.jsonld.CredentialsNamespaces.CX_NS_1_0; + +/** + * Enforces a Dismantler constraint. This function can check for these properties: + *
    + *
  • presence: whether a Dismantler credential is present or not
  • + *
  • activityType: whether an existing DismantlerCredential permits the activity types required by the constraint
  • + *
  • allowedBrands: whether an existing DismantlerCredential permits the vehicle brands required by the constraint
  • + *
+ */ +public class DismantlerConstraintFunction extends AbstractDynamicConstraintFunction { + + public static final String ALLOWED_VEHICLE_BRANDS = CX_NS_1_0 + "allowedVehicleBrands"; + private static final String DISMANTLER_LITERAL = "Dismantler"; + private static final String ALLOWED_ACTIVITIES = CX_NS_1_0 + "activityType"; + + @Override + public boolean evaluate(Object leftOperand, Operator operator, Object rightOperand, Permission permission, PolicyContext context) { + Predicate predicate = c -> false; + + // make sure the ParticipantAgent is there + var participantAgent = context.getContextData(ParticipantAgent.class); + if (participantAgent == null) { + context.reportProblem("Required PolicyContext data not found: " + ParticipantAgent.class.getName()); + return false; + } + + // check if the participant agent contains the correct data + var vcListResult = getCredentialList(participantAgent); + if (vcListResult.failed()) { // couldn't extract credential list from agent + context.reportProblem(vcListResult.getFailureDetail()); + return false; + } + + if (leftOperand.equals(DISMANTLER_LITERAL)) { // only checks for presence + if (!checkOperator(operator, context, EQUALITY_OPERATORS)) { + return false; + } + if (!ACTIVE.equals(rightOperand)) { + context.reportProblem("Right-operand must be equal to '%s', but was '%s'".formatted(ACTIVE, rightOperand)); + return false; + } + predicate = new CredentialTypePredicate(DISMANTLER_LITERAL + CREDENTIAL_LITERAL); + if (operator == NEQ) { + predicate = predicate.negate(); + } + } else if (leftOperand.equals(DISMANTLER_LITERAL + ".activityType")) { + if (hasInvalidOperand(operator, rightOperand, context)) return false; + predicate = getCredentialPredicate(ALLOWED_ACTIVITIES, operator, rightOperand); + } else if (leftOperand.equals(DISMANTLER_LITERAL + ".allowedBrands")) { + if (hasInvalidOperand(operator, rightOperand, context)) return false; + predicate = getCredentialPredicate(ALLOWED_VEHICLE_BRANDS, operator, rightOperand); + } else { + context.reportProblem("Invalid left-operand: must be 'Dismantler[.activityType | .allowedBrands ], but was '%s'".formatted(leftOperand)); + return false; + } + + return !vcListResult.getContent().stream().filter(predicate) + .toList().isEmpty(); + } + + @Override + public boolean canHandle(Object leftOperand) { + return leftOperand instanceof String && ((String) leftOperand).startsWith(DISMANTLER_LITERAL); + } + + /** + * Creates a {@link Predicate} based on the {@code rightOperand} that tests whether whatever property is extracted from the {@link VerifiableCredential} + * is valid, according to the operator. For example {@link Operator#IS_ALL_OF} would check that the list from the constraint (= rightOperand) intersects with the list + * stored in the claim identified by {@code credentialSubjectProperty} in the {@link VerifiableCredential#getCredentialSubject()}. + * + * @param credentialSubjectProperty The name of the claim to be extracted from the {@link VerifiableCredential#getCredentialSubject()} + * @param operator the operator + * @param rightOperand The constraint value (i.e. policy expression right-operand) + * @return A predicate that tests a {@link VerifiableCredential} for the constraint + */ + @NotNull + private Predicate getCredentialPredicate(String credentialSubjectProperty, Operator operator, Object rightOperand) { + Predicate predicate; + var allowedValues = getList(rightOperand); + // the filter predicate is determined by the operator + predicate = credential -> credential.getCredentialSubject().stream().anyMatch(subject -> { + var claimsFromCredential = getList(subject.getClaims().getOrDefault(credentialSubjectProperty, List.of())); + return switch (operator) { + case EQ -> claimsFromCredential.equals(allowedValues); + case NEQ -> !claimsFromCredential.equals(allowedValues); + case IN -> + new HashSet<>(allowedValues).containsAll(claimsFromCredential); //IntelliJ says Hashset has better performance + case IS_ANY_OF -> !intersect(allowedValues, claimsFromCredential).isEmpty(); + case IS_NONE_OF -> intersect(allowedValues, claimsFromCredential).isEmpty(); + default -> false; + }; + }); + return predicate; + } + + /** + * Checks whether {@code operator} is valid in the context of {@code rightOperand}. In practice, this means that if {@code rightOperand} is a String, it checks for {@link AbstractDynamicConstraintFunction#EQUALITY_OPERATORS}, + * and if its list type, it checks for {@code List.of(EQ, NEQ, IN, IS_ANY_OF, IS_NONE_OF)} + */ + private boolean hasInvalidOperand(Operator operator, Object rightOperand, PolicyContext context) { + if (rightOperand instanceof String) { + return !checkOperator(operator, context, EQUALITY_OPERATORS); + } else if (rightOperand instanceof Iterable) { + return !checkOperator(operator, context, List.of(EQ, NEQ, IN, IS_ANY_OF, IS_NONE_OF)); + } else { + context.reportProblem("Invalid right-operand type: expected String or List, but received: %s".formatted(rightOperand.getClass().getName())); + return true; + } + } + + /** + * Checks whether two lists "intersect", i.e. that at least one element is found in both lists. + * Caution: {@code list1} may be modified! + */ + private List intersect(List list1, List list2) { + list1.retainAll(list2); + return list1; + } + + private List getList(Object object) { + if (object instanceof Iterable iterable) { + var list = new ArrayList<>(); + iterable.iterator().forEachRemaining(list::add); + return list; + } + return List.of(object); + } +} diff --git a/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/framework/FrameworkAgreementConstraintFunction.java b/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/framework/FrameworkAgreementConstraintFunction.java index d7a13ee5b..f005add2f 100644 --- a/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/framework/FrameworkAgreementConstraintFunction.java +++ b/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/framework/FrameworkAgreementConstraintFunction.java @@ -20,17 +20,17 @@ package org.eclipse.tractusx.edc.policy.cx.framework; import org.eclipse.edc.identitytrust.model.VerifiableCredential; -import org.eclipse.edc.policy.engine.spi.DynamicAtomicConstraintFunction; import org.eclipse.edc.policy.engine.spi.PolicyContext; import org.eclipse.edc.policy.model.Operator; import org.eclipse.edc.policy.model.Permission; import org.eclipse.edc.spi.agent.ParticipantAgent; import org.eclipse.edc.spi.result.Result; +import org.eclipse.tractusx.edc.policy.cx.common.AbstractDynamicConstraintFunction; +import org.eclipse.tractusx.edc.policy.cx.common.CredentialTypePredicate; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.ArrayList; -import java.util.Collection; import java.util.List; import java.util.function.Predicate; @@ -52,13 +52,9 @@ * policy is considered not fulfilled. Note that if the {@code version} is specified, it must be satisfied by the same * credential that satisfies the {@code subtype} requirement. */ -public class FrameworkAgreementConstraintFunction implements DynamicAtomicConstraintFunction { +public class FrameworkAgreementConstraintFunction extends AbstractDynamicConstraintFunction { public static final String CONTRACT_VERSION_PROPERTY = CX_NS_1_0 + "contractVersion"; - private static final String VC_CLAIM = "vc"; - private static final String ACTIVE = "active"; private static final String FRAMEWORK_AGREEMENT_LITERAL = "FrameworkAgreement"; - private static final String CREDENTIAL_LITERAL = "Credential"; - private static final Collection ALLOWED_OPERATORS = List.of(Operator.EQ, Operator.NEQ); public FrameworkAgreementConstraintFunction() { } @@ -77,8 +73,7 @@ public FrameworkAgreementConstraintFunction() { @Override public boolean evaluate(Object leftValue, Operator operator, Object rightValue, Permission rule, PolicyContext context) { - if (!ALLOWED_OPERATORS.contains(operator)) { - context.reportProblem("Invalid operator: allowed operators are %s, got '%s'.".formatted(ALLOWED_OPERATORS, operator)); + if (!checkOperator(operator, context, EQUALITY_OPERATORS)) { return false; } @@ -131,7 +126,7 @@ public boolean evaluate(Object leftValue, Operator operator, Object rightValue, } /** - * Returns {@code true} if the left-operand starts with {@link FrameworkAgreementConstraintFunction#FRAMEWORK_AGREEMENT_LITERAL}, {@link false} otherwise. + * Returns {@code true} if the left-operand starts with {@link FrameworkAgreementConstraintFunction#FRAMEWORK_AGREEMENT_LITERAL}, {@code false} otherwise. */ @Override public boolean canHandle(Object leftValue) { @@ -145,26 +140,6 @@ private Predicate reducePredicates(List true); } - /** - * Extracts a {@link List} of {@link VerifiableCredential} objects from the {@link ParticipantAgent}. Credentials must be - * stored in the agent's claims map using the "vc" key. - */ - private Result> getCredentialList(ParticipantAgent agent) { - var vcListClaim = agent.getClaims().get(VC_CLAIM); - - if (vcListClaim == null) { - return Result.failure("ParticipantAgent did not contain a '%s' claim.".formatted(VC_CLAIM)); - } - if (!(vcListClaim instanceof List)) { - return Result.failure("ParticipantAgent contains a '%s' claim, but the type is incorrect. Expected %s, got %s.".formatted(VC_CLAIM, List.class.getName(), vcListClaim.getClass().getName())); - } - var vcList = (List) vcListClaim; - if (vcList.isEmpty()) { - return Result.failure("ParticipantAgent contains a '%s' claim but it did not contain any VerifiableCredentials.".formatted(VC_CLAIM)); - } - return Result.success(vcList); - } - /** * Converts the right-operand (new notation) into either 1 or 2 predicates, depending on whether the version was encoded or not. */ @@ -201,7 +176,7 @@ private Result>> getFilterPredicateLegacy(S @NotNull private List> createPredicates(String subtype, @Nullable String version) { var list = new ArrayList>(); - list.add(credential -> credential.getTypes().contains(capitalize(subtype) + CREDENTIAL_LITERAL)); + list.add(new CredentialTypePredicate(capitalize(subtype) + CREDENTIAL_LITERAL)); if (version != null) { list.add(credential -> credential.getCredentialSubject().stream().anyMatch(cs -> cs.getClaims().get(CONTRACT_VERSION_PROPERTY).equals(version))); } diff --git a/edc-extensions/cx-policy/src/test/java/org/eclipse/tractusx/edc/policy/cx/CredentialFunctions.java b/edc-extensions/cx-policy/src/test/java/org/eclipse/tractusx/edc/policy/cx/CredentialFunctions.java new file mode 100644 index 000000000..1d60aa3a1 --- /dev/null +++ b/edc-extensions/cx-policy/src/test/java/org/eclipse/tractusx/edc/policy/cx/CredentialFunctions.java @@ -0,0 +1,75 @@ +/******************************************************************************** + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +package org.eclipse.tractusx.edc.policy.cx; + +import org.eclipse.edc.identitytrust.model.CredentialSubject; +import org.eclipse.edc.identitytrust.model.Issuer; +import org.eclipse.edc.identitytrust.model.VerifiableCredential; + +import java.time.Instant; +import java.time.temporal.ChronoUnit; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +public class CredentialFunctions { + + public static VerifiableCredential.Builder createCredential(String type, String version) { + return VerifiableCredential.Builder.newInstance() + .types(List.of("VerifiableCredential", type)) + .id(UUID.randomUUID().toString()) + .issuer(new Issuer(UUID.randomUUID().toString(), Map.of("prop1", "val1"))) + .expirationDate(Instant.now().plus(365, ChronoUnit.DAYS)) + .issuanceDate(Instant.now()) + .credentialSubject(CredentialSubject.Builder.newInstance() + .id("subject-id") + .claim("https://w3id.org/catenax/credentials/v1.0.0/holderIdentifier", "did:web:holder") + .claim("https://w3id.org/catenax/credentials/v1.0.0/contractVersion", version) + .claim("https://w3id.org/catenax/credentials/v1.0.0/contractTemplate", "https://public.catena-x.org/contracts/pcf.v1.pdf") + .build()); + } + + public static VerifiableCredential.Builder createPcfCredential() { + return createCredential("PcfCredential", "1.0.0"); + } + + public static VerifiableCredential.Builder createDismantlerCredential(String... brands) { + return createDismantlerCredential(Arrays.asList(brands), "vehicleDismantle"); + } + + public static VerifiableCredential.Builder createDismantlerCredential(Collection brands, String... activityType) { + var at = activityType.length == 1 ? activityType[0] : List.of(activityType); + return VerifiableCredential.Builder.newInstance() + .types(List.of("VerifiableCredential", "DismantlerCredential")) + .id(UUID.randomUUID().toString()) + .issuer(new Issuer(UUID.randomUUID().toString(), Map.of("prop1", "val1"))) + .expirationDate(Instant.now().plus(365, ChronoUnit.DAYS)) + .issuanceDate(Instant.now()) + .credentialSubject(CredentialSubject.Builder.newInstance() + .id("subject-id") + .claim("https://w3id.org/catenax/credentials/v1.0.0/holderIdentifier", "did:web:holder") + .claim("https://w3id.org/catenax/credentials/v1.0.0/allowedVehicleBrands", brands) + .claim("https://w3id.org/catenax/credentials/v1.0.0/activityType", at) + .build()); + } + +} diff --git a/edc-extensions/cx-policy/src/test/java/org/eclipse/tractusx/edc/policy/cx/dismantler/DismantlerConstraintFunctionTest.java b/edc-extensions/cx-policy/src/test/java/org/eclipse/tractusx/edc/policy/cx/dismantler/DismantlerConstraintFunctionTest.java new file mode 100644 index 000000000..8462b40b8 --- /dev/null +++ b/edc-extensions/cx-policy/src/test/java/org/eclipse/tractusx/edc/policy/cx/dismantler/DismantlerConstraintFunctionTest.java @@ -0,0 +1,440 @@ +/******************************************************************************** + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +package org.eclipse.tractusx.edc.policy.cx.dismantler; + +import org.eclipse.edc.policy.engine.spi.PolicyContext; +import org.eclipse.edc.policy.model.Operator; +import org.eclipse.edc.spi.agent.ParticipantAgent; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.eclipse.edc.policy.model.Operator.IN; +import static org.eclipse.tractusx.edc.policy.cx.CredentialFunctions.createDismantlerCredential; +import static org.eclipse.tractusx.edc.policy.cx.CredentialFunctions.createPcfCredential; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.startsWith; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +class DismantlerConstraintFunctionTest { + + private final DismantlerConstraintFunction function = new DismantlerConstraintFunction(); + private final PolicyContext context = mock(); + private ParticipantAgent participantAgent; + + @BeforeEach + void setup() { + participantAgent = mock(ParticipantAgent.class); + when(context.getContextData(eq(ParticipantAgent.class))) + .thenReturn(participantAgent); + } + + @Test + void evaluate_leftOperandInvalid() { + when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createDismantlerCredential("Tatra", "Moskvich").build()))); + assertThat(function.evaluate("foobar", Operator.EQ, "active", null, context)).isFalse(); + verify(context).reportProblem(eq("Invalid left-operand: must be 'Dismantler[.activityType | .allowedBrands ], but was 'foobar'")); + } + + @Test + void evaluate_noParticipantAgentOnContext() { + when(context.getContextData(eq(ParticipantAgent.class))).thenReturn(null); + assertThat(function.evaluate("Dismantler", Operator.EQ, "active", null, context)).isFalse(); + verify(context).reportProblem("Required PolicyContext data not found: org.eclipse.edc.spi.agent.ParticipantAgent"); + } + + @Test + void evaluate_noVcClaimOnParticipantAgent() { + assertThat(function.evaluate("Dismantler", Operator.EQ, "active", null, context)).isFalse(); + verify(context).reportProblem(eq("ParticipantAgent did not contain a 'vc' claim.")); + } + + @Test + void evaluate_vcClaimEmpty() { + when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of())); + assertThat(function.evaluate("Dismantler", Operator.EQ, "active", null, context)).isFalse(); + verify(context).reportProblem(eq("ParticipantAgent contains a 'vc' claim but it did not contain any VerifiableCredentials.")); + } + + @Test + void evaluate_vcClaimNotList() { + when(participantAgent.getClaims()).thenReturn(Map.of("vc", new Object())); + assertThat(function.evaluate("Dismantler", Operator.EQ, "active", null, context)).isFalse(); + verify(context).reportProblem(eq("ParticipantAgent contains a 'vc' claim, but the type is incorrect. Expected java.util.List, received java.lang.Object.")); + } + + @Nested + class Active { + @Test + void evaluate_eq_satisfied() { + when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createDismantlerCredential("Tatra", "Moskvich").build()))); + assertThat(function.evaluate("Dismantler", Operator.EQ, "active", null, context)).isTrue(); + } + + @Test + void evaluate_eq_notSatisfied() { + when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createPcfCredential().build()))); + assertThat(function.evaluate("Dismantler", Operator.EQ, "active", null, context)).isFalse(); + } + + @Test + void evaluate_neq_satisfied() { + when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createPcfCredential().build()))); + assertThat(function.evaluate("Dismantler", Operator.NEQ, "active", null, context)).isTrue(); + } + + @Test + void evaluate_neq_notSatisfied() { + when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createDismantlerCredential("Yugo", "Tatra").build()))); + assertThat(function.evaluate("Dismantler", Operator.NEQ, "active", null, context)).isFalse(); + } + + @Test + void evaluate_invalidOperators() { + var invalidOperators = new ArrayList<>(Arrays.asList(Operator.values())); + invalidOperators.remove(Operator.EQ); + invalidOperators.remove(Operator.NEQ); + when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createPcfCredential().build()))); + + assertThat(invalidOperators).allSatisfy(invalidOperator -> assertThat(function.evaluate("Dismantler", invalidOperator, "active", null, context)).isFalse()); + + } + + @Test + void evaluate_rightOperandInvalid() { + when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createPcfCredential().build()))); + assertThat(function.evaluate("Dismantler", Operator.EQ, "invalid", null, context)).isFalse(); + verify(context).reportProblem("Right-operand must be equal to 'active', but was 'invalid'"); + } + } + + @Nested + class AllowedBrands { + + @DisplayName("Constraint (list) must match credential EXACTLY") + @Test + void evaluate_eq_list() { + when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createDismantlerCredential("Tatra", "Moskvich").build()))); + assertThat(function.evaluate("Dismantler.allowedBrands", Operator.EQ, List.of("Tatra", "Moskvich"), null, context)).isTrue(); + } + + @DisplayName("Constraint (list) must credential EXACTLY - failure") + @Test + void evaluate_eq_list_notSatisfied() { + when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createDismantlerCredential("Tatra", "Moskvich", "Lada").build()))); + assertThat(function.evaluate("Dismantler.allowedBrands", Operator.EQ, List.of("Tatra", "Moskvich"), null, context)).isFalse(); + verify(context, never()).reportProblem(anyString()); + } + + @DisplayName("Constraint (scalar) must match credential EXACTLY") + @Test + void evaluate_eq_scalar() { + when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createDismantlerCredential("Yugo").build()))); + assertThat(function.evaluate("Dismantler.allowedBrands", Operator.EQ, "Yugo", null, context)).isTrue(); + } + + @DisplayName("Constraint (scalar) must credential EXACTLY - failure") + @Test + void evaluate_eq_scalar_notSatisfied() { + when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createDismantlerCredential("Tatra").build()))); + assertThat(function.evaluate("Dismantler.allowedBrands", Operator.EQ, "Yugo", null, context)).isFalse(); + verify(context, never()).reportProblem(anyString()); + } + + @DisplayName("Constraint and credential must be DISJOINT") + @Test + void evaluate_neq_satisfied() { + when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createDismantlerCredential("Tatra", "Moskvich").build()))); + assertThat(function.evaluate("Dismantler.allowedBrands", Operator.NEQ, List.of("Lada", "Yugo"), null, context)).isTrue(); + + when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createDismantlerCredential("Tatra", "Moskvich", "Yugo", "Lada").build()))); + assertThat(function.evaluate("Dismantler.allowedBrands", Operator.NEQ, List.of("Lada", "Yugo"), null, context)).isTrue(); + } + + @DisplayName("Constraint and credential must be DISJOINT - failure") + @Test + void evaluate_neq_notSatisfied() { + when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createDismantlerCredential("Lada", "Yugo").build()))); + assertThat(function.evaluate("Dismantler.allowedBrands", Operator.NEQ, List.of("Lada", "Yugo"), null, context)).isFalse(); + } + + @DisplayName("Constraint and credential must INTERSECT") + @Test + void evaluate_isAnyOf_satisfied() { + when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createDismantlerCredential("Lada").build()))); + assertThat(function.evaluate("Dismantler.allowedBrands", Operator.IS_ANY_OF, List.of("Tatra", "Moskvich", "Lada"), null, context)).isTrue(); + + when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createDismantlerCredential("Moskvich", "Tatra").build()))); + assertThat(function.evaluate("Dismantler.allowedBrands", Operator.IS_ANY_OF, List.of("Lada", "Moskvich"), null, context)).isTrue(); + } + + @DisplayName("Constraint and credential must INTERSECT - failure") + @Test + void evaluate_isAnyOf_notSatisfied() { + when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createDismantlerCredential("Gaz").build()))); + assertThat(function.evaluate("Dismantler.allowedBrands", Operator.IS_ANY_OF, List.of("Tatra", "Moskvich", "Lada"), null, context)).isFalse(); + + when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createDismantlerCredential("Gaz", "Yugo").build()))); + assertThat(function.evaluate("Dismantler.allowedBrands", Operator.IS_ANY_OF, List.of("Tatra", "Moskvich", "Lada"), null, context)).isFalse(); + + when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createDismantlerCredential().build()))); + assertThat(function.evaluate("Dismantler.allowedBrands", Operator.IS_ANY_OF, List.of("Tatra", "Moskvich", "Lada"), null, context)).isFalse(); + + when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createDismantlerCredential("Moskvich", "Tatra").build()))); + assertThat(function.evaluate("Dismantler.allowedBrands", Operator.IS_ANY_OF, List.of(), null, context)).isFalse(); + } + + @DisplayName("Constraint and credential must NOT INTERSECT") + @Test + void evaluate_isNoneOf_satisfied() { + when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createDismantlerCredential("Gaz", "Yugo").build()))); + assertThat(function.evaluate("Dismantler.allowedBrands", Operator.IS_NONE_OF, List.of("Tatra", "Moskvich", "Lada"), null, context)).isTrue(); + + when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createDismantlerCredential("Gaz", "Yugo").build()))); + assertThat(function.evaluate("Dismantler.allowedBrands", Operator.IS_NONE_OF, List.of(), null, context)).isTrue(); + + when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createDismantlerCredential().build()))); + assertThat(function.evaluate("Dismantler.allowedBrands", Operator.IS_NONE_OF, List.of("Tatra", "Moskvich", "Lada"), null, context)).isTrue(); + } + + @DisplayName("Constraint and credential must NOT INTERSECT - failure") + @Test + void evaluate_isNoneOf_notSatisfied() { + when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createDismantlerCredential("Gaz", "Yugo").build()))); + assertThat(function.evaluate("Dismantler.allowedBrands", Operator.IS_NONE_OF, List.of("Tatra", "Moskvich", "Yugo"), null, context)).isFalse(); + + } + + @DisplayName("Brand list from credential must be FULLY CONTAINED within constraint") + @Test + void evaluate_in_satisfied() { + when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createDismantlerCredential("Gaz", "Yugo").build()))); + assertThat(function.evaluate("Dismantler.allowedBrands", IN, List.of("Gaz", "Moskvich", "Yugo", "Lada"), null, context)).isTrue(); + + when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createDismantlerCredential("Gaz").build()))); + assertThat(function.evaluate("Dismantler.allowedBrands", IN, List.of("Gaz"), null, context)).isTrue(); + } + + @DisplayName("Brand list from credential must be FULLY CONTAINED within constraint - failure") + @Test + void evaluate_in_notSatisfied() { + when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createDismantlerCredential("Gaz", "Yugo").build()))); + assertThat(function.evaluate("Dismantler.allowedBrands", IN, List.of("Gaz", "Moskvich", "Yugo", "Lada"), null, context)).isTrue(); + } + + @DisplayName("Illegal operator when constraint contains a list value") + @Test + void evaluate_illegalOperator_constraintIsList() { + when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createDismantlerCredential("Gaz", "Yugo").build()))); + var illegalOp = List.of(Operator.HAS_PART, Operator.GEQ, Operator.LEQ, Operator.GT, Operator.LT, Operator.IS_ALL_OF); + + assertThat(illegalOp).allSatisfy(op -> { + assertThat(function.evaluate("Dismantler.allowedBrands", op, List.of("Gaz", "Moskvich"), null, context)).isFalse(); + verify(context).reportProblem("Invalid operator: this constraint only allows the following operators: [EQ, NEQ], but received '%s'.".formatted(op)); + }); + } + + @DisplayName("Illegal operator when constraint contains a scalar value") + @Test + void evaluate_illegalOperator_constraintIsScalar() { + when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createDismantlerCredential("Gaz", "Yugo").build()))); + + var invalidOperators = new ArrayList<>(Arrays.asList(Operator.values())); + invalidOperators.remove(Operator.EQ); + invalidOperators.remove(Operator.NEQ); + + assertThat(invalidOperators).allSatisfy(op -> { + assertThat(function.evaluate("Dismantler.allowedBrands", op, "Moskvich", null, context)).isFalse(); + verify(context).reportProblem("Invalid operator: this constraint only allows the following operators: [EQ, NEQ], but received '%s'.".formatted(op)); + }); + } + + @DisplayName("Constraint right-operand has an invalid type") + @Test + void evaluate_righOpInvalidType() { + when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createDismantlerCredential("Gaz", "Yugo").build()))); + assertThat(function.evaluate("Dismantler.allowedBrands", IN, Map.of("foo", "bar"), null, context)).isFalse(); + verify(context).reportProblem(startsWith("Invalid right-operand type: expected String or List, but received:")); + } + } + + @Nested + class ActivityType { + private final Collection brands = List.of("Tatra", "Yugo"); + + @DisplayName("Constraint (list) must match credential EXACTLY") + @Test + void evaluate_eq_list() { + when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createDismantlerCredential(brands, "vehicleDismantle", "vehicleScrap").build()))); + assertThat(function.evaluate("Dismantler.activityType", Operator.EQ, List.of("vehicleDismantle", "vehicleScrap"), null, context)).isTrue(); + } + + @DisplayName("Constraint (list) must credential EXACTLY - failure") + @Test + void evaluate_eq_list_notSatisfied() { + when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createDismantlerCredential(brands, "vehicleDismantle", "vehicleScrap").build()))); + assertThat(function.evaluate("Dismantler.activityType", Operator.EQ, List.of("vehicleRefurbish"), null, context)).isFalse(); + verify(context, never()).reportProblem(anyString()); + } + + @DisplayName("Constraint (scalar) must match credential EXACTLY") + @Test + void evaluate_eq_scalar() { + when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createDismantlerCredential(brands, "vehicleDismantle").build()))); + assertThat(function.evaluate("Dismantler.activityType", Operator.EQ, "vehicleDismantle", null, context)).isTrue(); + } + + @DisplayName("Constraint (scalar) must credential EXACTLY - failure") + @Test + void evaluate_eq_scalar_notSatisfied() { + when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createDismantlerCredential(brands, "vehicleDismantle").build()))); + assertThat(function.evaluate("Dismantler.activityType", Operator.EQ, "vehicleScrap", null, context)).isFalse(); + verify(context, never()).reportProblem(anyString()); + } + + @DisplayName("Constraint and credential must be DISJOINT") + @Test + void evaluate_neq_satisfied() { + when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createDismantlerCredential(brands, "vehicleDismantle").build()))); + assertThat(function.evaluate("Dismantler.activityType", Operator.NEQ, "vehicleScrap", null, context)).isTrue(); + + when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createDismantlerCredential(brands, "vehicleDismantle").build()))); + assertThat(function.evaluate("Dismantler.activityType", Operator.NEQ, List.of("vehicleScrap", "vehicleRefurbish"), null, context)).isTrue(); + } + + @DisplayName("Constraint and credential must be DISJOINT - failure") + @Test + void evaluate_neq_notSatisfied() { + when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createDismantlerCredential(brands, "vehicleDismantle").build()))); + assertThat(function.evaluate("Dismantler.activityType", Operator.NEQ, "vehicleDismantle", null, context)).isFalse(); + + when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createDismantlerCredential(brands, "vehicleDismantle").build()))); + assertThat(function.evaluate("Dismantler.activityType", Operator.NEQ, List.of("vehicleDismantle", "vehicleRefurbish"), null, context)).isTrue(); + } + + @DisplayName("Constraint and credential must INTERSECT") + @Test + void evaluate_isAnyOf_satisfied() { + when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createDismantlerCredential(brands, "vehicleDismantle", "vehicleScrap").build()))); + assertThat(function.evaluate("Dismantler.activityType", Operator.IS_ANY_OF, List.of("vehicleDismantle", "vehicleRefurbish"), null, context)).isTrue(); + } + + @DisplayName("Constraint and credential must INTERSECT - failure") + @Test + void evaluate_isAnyOf_notSatisfied() { + when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createDismantlerCredential(brands, "vehicleDismantle", "vehicleScrap").build()))); + assertThat(function.evaluate("Dismantler.activityType", Operator.IS_ANY_OF, List.of("vehicleCrush", "vehicleRefurbish"), null, context)).isFalse(); + + when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createDismantlerCredential(brands, "vehicleDismantle", "vehicleScrap").build()))); + assertThat(function.evaluate("Dismantler.activityType", Operator.IS_ANY_OF, List.of(), null, context)).isFalse(); + + when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createDismantlerCredential(brands).build()))); + assertThat(function.evaluate("Dismantler.activityType", Operator.IS_ANY_OF, List.of("vehicleCrush", "vehicleRefurbish"), null, context)).isFalse(); + } + + @DisplayName("Constraint and credential must NOT INTERSECT") + @Test + void evaluate_isNoneOf_satisfied() { + when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createDismantlerCredential(brands, "vehicleDismantle", "vehicleScrap").build()))); + assertThat(function.evaluate("Dismantler.activityType", Operator.IS_NONE_OF, List.of("vehicleRefurbish"), null, context)).isTrue(); + + + when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createDismantlerCredential(brands, "vehicleDismantle", "vehicleScrap").build()))); + assertThat(function.evaluate("Dismantler.activityType", Operator.IS_NONE_OF, List.of(), null, context)).isTrue(); + + when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createDismantlerCredential(brands).build()))); + assertThat(function.evaluate("Dismantler.activityType", Operator.IS_NONE_OF, List.of("vehicleRefurbish"), null, context)).isTrue(); + } + + @DisplayName("Constraint and credential must NOT INTERSECT - failure") + @Test + void evaluate_isNoneOf_notSatisfied() { + when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createDismantlerCredential(brands, "vehicleDismantle", "vehicleRefurbish").build()))); + assertThat(function.evaluate("Dismantler.activityType", Operator.IS_NONE_OF, List.of("vehicleRefurbish"), null, context)).isFalse(); + } + + @DisplayName("Activity list from credential must be FULLY CONTAINED within constraint") + @Test + void evaluate_in_satisfied() { + when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createDismantlerCredential(brands, "vehicleRefurbish").build()))); + assertThat(function.evaluate("Dismantler.activityType", Operator.IN, List.of("vehicleRefurbish", "vehicleDismantle"), null, context)).isTrue(); + + when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createDismantlerCredential(brands, "vehicleDismantle").build()))); + assertThat(function.evaluate("Dismantler.activityType", Operator.IN, List.of("vehicleDismantle"), null, context)).isTrue(); + } + + @DisplayName("Activity list from credential must be FULLY CONTAINED within constraint - failure") + @Test + void evaluate_in_notSatisfied() { + when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createDismantlerCredential(brands, "vehicleRefurbish", "vehicleScrap").build()))); + assertThat(function.evaluate("Dismantler.activityType", Operator.IN, List.of("vehicleRefurbish", "vehicleDismantle"), null, context)).isFalse(); + + when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createDismantlerCredential(brands, "vehicleScrap").build()))); + assertThat(function.evaluate("Dismantler.activityType", Operator.IN, List.of("vehicleRefurbish", "vehicleDismantle"), null, context)).isFalse(); + + } + + @DisplayName("Illegal operator when constraint contains a list value") + @Test + void evaluate_illegalOperator_constraintIsList() { + when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createDismantlerCredential(brands, "vehicleDismantle").build()))); + var illegalOp = List.of(Operator.HAS_PART, Operator.GEQ, Operator.LEQ, Operator.GT, Operator.LT, Operator.IS_ALL_OF); + + assertThat(illegalOp).allSatisfy(op -> { + assertThat(function.evaluate("Dismantler.activityType", op, List.of("vehicleDismantle"), null, context)).isFalse(); + }); + } + + @DisplayName("Illegal operator when constraint contains a scalar value") + @Test + void evaluate_illegalOperator_constraintIsScalar() { + when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createDismantlerCredential(brands, "vehicleDismantle").build()))); + + var invalidOperators = new ArrayList<>(Arrays.asList(Operator.values())); + invalidOperators.remove(Operator.EQ); + invalidOperators.remove(Operator.NEQ); + + assertThat(invalidOperators).allSatisfy(op -> { + assertThat(function.evaluate("Dismantler.activityType", op, "vehicleDismantle", null, context)).isFalse(); + verify(context).reportProblem("Invalid operator: this constraint only allows the following operators: [EQ, NEQ], but received '%s'.".formatted(op)); + }); + } + + @DisplayName("Constraint right-operand has an invalid type") + @Test + void evaluate_righOpInvalidType() { + when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createDismantlerCredential(brands, "vehicleDismantle").build()))); + assertThat(function.evaluate("Dismantler.activityType", IN, Map.of("foo", "bar"), null, context)).isFalse(); + verify(context).reportProblem(startsWith("Invalid right-operand type: expected String or List, but received:")); + } + } +} \ No newline at end of file diff --git a/edc-extensions/cx-policy/src/test/java/org/eclipse/tractusx/edc/policy/cx/framework/FrameworkAgreementConstraintFunctionTest.java b/edc-extensions/cx-policy/src/test/java/org/eclipse/tractusx/edc/policy/cx/framework/FrameworkAgreementConstraintFunctionTest.java index 9d9c0ceef..bfcd2513d 100644 --- a/edc-extensions/cx-policy/src/test/java/org/eclipse/tractusx/edc/policy/cx/framework/FrameworkAgreementConstraintFunctionTest.java +++ b/edc-extensions/cx-policy/src/test/java/org/eclipse/tractusx/edc/policy/cx/framework/FrameworkAgreementConstraintFunctionTest.java @@ -19,8 +19,6 @@ package org.eclipse.tractusx.edc.policy.cx.framework; -import org.eclipse.edc.identitytrust.model.CredentialSubject; -import org.eclipse.edc.identitytrust.model.Issuer; import org.eclipse.edc.identitytrust.model.VerifiableCredential; import org.eclipse.edc.policy.engine.spi.PolicyContext; import org.eclipse.edc.policy.model.Operator; @@ -30,14 +28,13 @@ import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; -import java.time.Instant; -import java.time.temporal.ChronoUnit; import java.util.ArrayList; import java.util.List; import java.util.Map; -import java.util.UUID; import static org.assertj.core.api.Assertions.assertThat; +import static org.eclipse.tractusx.edc.policy.cx.CredentialFunctions.createCredential; +import static org.eclipse.tractusx.edc.policy.cx.CredentialFunctions.createPcfCredential; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.startsWith; import static org.mockito.Mockito.mock; @@ -67,7 +64,7 @@ void evaluate_leftOperandInvalid() { @Test void evaluate_invalidOperator() { assertThat(function.evaluate("FrameworkAgreement.foobar", Operator.HAS_PART, "irrelevant", permission, context)).isFalse(); - verify(context).reportProblem(eq("Invalid operator: allowed operators are [EQ, NEQ], got 'HAS_PART'.")); + verify(context).reportProblem(eq("Invalid operator: this constraint only allows the following operators: [EQ, NEQ], but received 'HAS_PART'.")); verifyNoMoreInteractions(context); } @@ -93,7 +90,7 @@ void evaluate_vcClaimNotListOfCredentials() { "vc", new Object() )); assertThat(function.evaluate("FrameworkAgreement.foobar", Operator.EQ, "active:0.0.1", permission, context)).isFalse(); - verify(context).reportProblem(eq("ParticipantAgent contains a 'vc' claim, but the type is incorrect. Expected java.util.List, got java.lang.Object.")); + verify(context).reportProblem(eq("ParticipantAgent contains a 'vc' claim, but the type is incorrect. Expected java.util.List, received java.lang.Object.")); } @Test @@ -189,7 +186,7 @@ void evaluate_neq_oneViolates() { )); assertThat(function.evaluate("FrameworkAgreement", Operator.NEQ, "sustainability", permission, context)).isFalse(); } - + @Test void evaluate_neq_requiredCredentialFound_withCorrectVersion() { when(participantAgent.getClaims()).thenReturn(Map.of( @@ -202,25 +199,6 @@ void evaluate_neq_requiredCredentialFound_withCorrectVersion() { } - private VerifiableCredential.Builder createCredential(String type, String version) { - return VerifiableCredential.Builder.newInstance() - .types(List.of("VerifiableCredential", type)) - .id(UUID.randomUUID().toString()) - .issuer(new Issuer(UUID.randomUUID().toString(), Map.of("prop1", "val1"))) - .expirationDate(Instant.now().plus(365, ChronoUnit.DAYS)) - .issuanceDate(Instant.now()) - .credentialSubject(CredentialSubject.Builder.newInstance() - .id("subject-id") - .claim("https://w3id.org/catenax/credentials/v1.0.0/holderIdentifier", "did:web:holder") - .claim("https://w3id.org/catenax/credentials/v1.0.0/contractVersion", version) - .claim("https://w3id.org/catenax/credentials/v1.0.0/contractTemplate", "https://public.catena-x.org/contracts/pcf.v1.pdf") - .build()); - } - - private VerifiableCredential.Builder createPcfCredential() { - return createCredential("PcfCredential", "1.0.0"); - } - @Nested class LegacyLeftOperand { @Test From eb250baefff202b9d5e7ec85b27f39ca4b281019 Mon Sep 17 00:00:00 2001 From: KilianHaag Date: Sun, 18 Feb 2024 09:46:30 +0100 Subject: [PATCH 014/100] improvement(memory-edc): remove EDC_VAULT_SECRETS rewrite (#1040) * improvement(memory-chart): remove EC_VAULT_SECRETS rewrite resolves #1039 * improvement(memory-chart): remove EDC_VAULT_SECRETS rewrite resolves #1039 --- .../templates/deployment-runtime.yaml | 2 +- charts/tractusx-connector-memory/values.yaml | 3 +-- edc-controlplane/edc-runtime-memory/README.md | 2 +- edc-controlplane/edc-runtime-memory/src/main/docker/Dockerfile | 3 +-- 4 files changed, 4 insertions(+), 6 deletions(-) diff --git a/charts/tractusx-connector-memory/templates/deployment-runtime.yaml b/charts/tractusx-connector-memory/templates/deployment-runtime.yaml index 3634e2402..054e4bd91 100644 --- a/charts/tractusx-connector-memory/templates/deployment-runtime.yaml +++ b/charts/tractusx-connector-memory/templates/deployment-runtime.yaml @@ -252,7 +252,7 @@ spec: ########### # see extension https://github.com/eclipse-tractusx/tractusx-edc/tree/develop/edc-extensions/hashicorp-vault - - name: "SECRETS" + - name: "EDC_VAULT_SECRETS" value: {{ .Values.vault.secrets | quote}} ##################### diff --git a/charts/tractusx-connector-memory/values.yaml b/charts/tractusx-connector-memory/values.yaml index ef4341779..047c40093 100644 --- a/charts/tractusx-connector-memory/values.yaml +++ b/charts/tractusx-connector-memory/values.yaml @@ -18,7 +18,6 @@ # SPDX-License-Identifier: Apache-2.0 ################################################################################# - --- # Default values for eclipse-dataspace-connector. # This is a YAML-formatted file. @@ -289,7 +288,7 @@ runtime: public: "" readiness: "" vault: - # secrets can be seeded by supplying them in a comma separated list key1:secret2,key2:secret2 + # secrets can be seeded by supplying them in a semicolon separated list key1:secret2;key2:secret2 secrets: "" secretNames: transferProxyTokenEncryptionAesKey: transfer-proxy-token-encryption-aes-key diff --git a/edc-controlplane/edc-runtime-memory/README.md b/edc-controlplane/edc-runtime-memory/README.md index 6ba6cdc5a..4283877d4 100644 --- a/edc-controlplane/edc-runtime-memory/README.md +++ b/edc-controlplane/edc-runtime-memory/README.md @@ -30,7 +30,7 @@ extension. When in doubt, check the extensions' README that will likely be in [t ```shell docker run \ - -e SECRETS="key1:secret1,key2:secret2" \ + -e EDC_VAULT_SECRETS="key1:secret1;key2:secret2" \ -p 8080:8080 -p 8181:8181 -p 8282:8282 -p 9090:9090 -p 9999:9999 \ -v ${CONFIGURATION_PROPERTIES_FILE:-/dev/null}:/app/configuration.properties \ -v ${LOGGING_PROPERTIES_FILE:-/dev/null}:/app/logging.properties \ diff --git a/edc-controlplane/edc-runtime-memory/src/main/docker/Dockerfile b/edc-controlplane/edc-runtime-memory/src/main/docker/Dockerfile index 136f0f4df..281f7baaf 100644 --- a/edc-controlplane/edc-runtime-memory/src/main/docker/Dockerfile +++ b/edc-controlplane/edc-runtime-memory/src/main/docker/Dockerfile @@ -47,6 +47,5 @@ COPY ${ADDITIONAL_FILES} ./ HEALTHCHECK NONE -# need the sh -c syntax so that the SECRETS variable gets expanded # use the "exec" syntax so that SIGINT reaches the JVM -> graceful termination -CMD ["sh", "-c", "exec java -Dedc.fs.config=/app/configuration.properties -Dedc.vault.secrets=\"${SECRETS}\" -Djava.util.logging.config.file=/app/logging.properties -Djava.security.egd=file:/dev/urandom -jar edc-controlplane.jar"] +CMD ["sh", "-c", "exec java -Dedc.fs.config=/app/configuration.properties -Djava.util.logging.config.file=/app/logging.properties -Djava.security.egd=file:/dev/urandom -jar edc-controlplane.jar"] From d5750b9b48015af6ef319903c3eaa03fd646f451 Mon Sep 17 00:00:00 2001 From: Enrico Risa Date: Mon, 19 Feb 2024 08:50:54 +0100 Subject: [PATCH 015/100] feat: implements DIM STS adapter (#1054) * feat: implements DIM STS adapter * chore: pr suggestions * chore: removes temporary credentials functions --- core/core-utils/build.gradle.kts | 25 ++ .../tractusx/edc/core}/utils/PathUtils.java | 2 +- .../edc/core}/utils/PathUtilsTest.java | 2 +- .../iatp/tx-iatp-sts-dim/build.gradle.kts | 32 ++ .../iatp/sts/dim/DimOauthClientExtension.java | 59 ++++ .../iatp/sts/dim/DimSecureTokenService.java | 227 +++++++++++++ .../dim/DimSecureTokenServiceExtension.java | 68 ++++ .../sts/dim/DimStsConfigurationExtension.java | 62 ++++ .../sts/dim/StsRemoteClientConfiguration.java | 23 +- .../iatp/sts/dim/oauth/DimOauth2Client.java | 38 +++ .../sts/dim/oauth/DimOauthClientImpl.java | 66 ++++ ...rg.eclipse.edc.spi.system.ServiceExtension | 23 ++ .../sts/dim/DimOauthClientExtensionTest.java | 45 +++ .../dim/DimSecureServiceExtensionTest.java | 51 +++ .../sts/dim/DimSecureTokenServiceTest.java | 299 ++++++++++++++++++ .../dim/DimStsConfigurationExtensionTest.java | 54 ++++ .../sts/dim/oauth/DimOauthClientImplTest.java | 75 +++++ edc-extensions/iatp/tx-iatp/build.gradle.kts | 2 +- .../iam/iatp/IatpDefaultScopeExtension.java | 8 +- .../iatp/IatpDefaultScopeExtensionTest.java | 6 +- .../build.gradle.kts | 1 + .../ssi/miw/SsiMiwConfigurationExtension.java | 2 +- .../ssi/miw/SsiMiwOauth2ClientExtension.java | 2 +- edc-tests/e2e-tests/build.gradle.kts | 3 + .../edc/helpers/IatpHelperFunctions.java | 57 ++++ .../lifecycle/tx/iatp/IatpDimParticipant.java | 45 +++ .../lifecycle/tx/iatp/IatpParticipant.java | 19 +- ...HttpConsumerPullWithProxyInMemoryTest.java | 136 ++++++++ ...HttpConsumerPullWithProxyInMemoryTest.java | 3 - ...HttpConsumerPullWithProxyInMemoryTest.java | 62 +--- .../tractusx/edc/token/DimDispatcher.java | 117 +++++++ .../edc/token/KeycloakDispatcher.java | 11 +- .../CredentialPolicyEvaluationExtension.java | 51 +-- ...FrameworkCredentialEvaluationFunction.java | 74 ----- .../edc/iatp/policy/IdentityExtractor.java | 55 +++- ...embershipCredentialEvaluationFunction.java | 91 ------ .../iatp/runtime-memory-iatp-dim-ih/README.md | 3 + .../build.gradle.kts | 69 ++++ gradle/libs.versions.toml | 5 +- settings.gradle.kts | 3 + 40 files changed, 1659 insertions(+), 317 deletions(-) create mode 100644 core/core-utils/build.gradle.kts rename {edc-extensions/ssi/ssi-miw-credential-client/src/main/java/org/eclipse/tractusx/edc/iam/ssi/miw => core/core-utils/src/main/java/org/eclipse/tractusx/edc/core}/utils/PathUtils.java (95%) rename {edc-extensions/ssi/ssi-miw-credential-client/src/test/java/org/eclipse/tractusx/edc/iam/ssi/miw => core/core-utils/src/test/java/org/eclipse/tractusx/edc/core}/utils/PathUtilsTest.java (97%) create mode 100644 edc-extensions/iatp/tx-iatp-sts-dim/build.gradle.kts create mode 100644 edc-extensions/iatp/tx-iatp-sts-dim/src/main/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/DimOauthClientExtension.java create mode 100644 edc-extensions/iatp/tx-iatp-sts-dim/src/main/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/DimSecureTokenService.java create mode 100644 edc-extensions/iatp/tx-iatp-sts-dim/src/main/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/DimSecureTokenServiceExtension.java create mode 100644 edc-extensions/iatp/tx-iatp-sts-dim/src/main/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/DimStsConfigurationExtension.java rename edc-tests/runtime/iatp/iatp-extensions/src/main/java/org/eclipse/tractusx/edc/iatp/policy/BaseCredentialEvaluationFunction.java => edc-extensions/iatp/tx-iatp-sts-dim/src/main/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/StsRemoteClientConfiguration.java (60%) create mode 100644 edc-extensions/iatp/tx-iatp-sts-dim/src/main/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/oauth/DimOauth2Client.java create mode 100644 edc-extensions/iatp/tx-iatp-sts-dim/src/main/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/oauth/DimOauthClientImpl.java create mode 100644 edc-extensions/iatp/tx-iatp-sts-dim/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension create mode 100644 edc-extensions/iatp/tx-iatp-sts-dim/src/test/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/DimOauthClientExtensionTest.java create mode 100644 edc-extensions/iatp/tx-iatp-sts-dim/src/test/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/DimSecureServiceExtensionTest.java create mode 100644 edc-extensions/iatp/tx-iatp-sts-dim/src/test/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/DimSecureTokenServiceTest.java create mode 100644 edc-extensions/iatp/tx-iatp-sts-dim/src/test/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/DimStsConfigurationExtensionTest.java create mode 100644 edc-extensions/iatp/tx-iatp-sts-dim/src/test/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/oauth/DimOauthClientImplTest.java create mode 100644 edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/tx/iatp/IatpDimParticipant.java create mode 100644 edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/DimHttpConsumerPullWithProxyInMemoryTest.java create mode 100644 edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/token/DimDispatcher.java delete mode 100644 edc-tests/runtime/iatp/iatp-extensions/src/main/java/org/eclipse/tractusx/edc/iatp/policy/FrameworkCredentialEvaluationFunction.java delete mode 100644 edc-tests/runtime/iatp/iatp-extensions/src/main/java/org/eclipse/tractusx/edc/iatp/policy/MembershipCredentialEvaluationFunction.java create mode 100644 edc-tests/runtime/iatp/runtime-memory-iatp-dim-ih/README.md create mode 100644 edc-tests/runtime/iatp/runtime-memory-iatp-dim-ih/build.gradle.kts diff --git a/core/core-utils/build.gradle.kts b/core/core-utils/build.gradle.kts new file mode 100644 index 000000000..331074def --- /dev/null +++ b/core/core-utils/build.gradle.kts @@ -0,0 +1,25 @@ +/******************************************************************************** + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +plugins { + `java-library` +} + +dependencies { +} diff --git a/edc-extensions/ssi/ssi-miw-credential-client/src/main/java/org/eclipse/tractusx/edc/iam/ssi/miw/utils/PathUtils.java b/core/core-utils/src/main/java/org/eclipse/tractusx/edc/core/utils/PathUtils.java similarity index 95% rename from edc-extensions/ssi/ssi-miw-credential-client/src/main/java/org/eclipse/tractusx/edc/iam/ssi/miw/utils/PathUtils.java rename to core/core-utils/src/main/java/org/eclipse/tractusx/edc/core/utils/PathUtils.java index 7f77ad5ce..f439ab596 100644 --- a/edc-extensions/ssi/ssi-miw-credential-client/src/main/java/org/eclipse/tractusx/edc/iam/ssi/miw/utils/PathUtils.java +++ b/core/core-utils/src/main/java/org/eclipse/tractusx/edc/core/utils/PathUtils.java @@ -17,7 +17,7 @@ * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ -package org.eclipse.tractusx.edc.iam.ssi.miw.utils; +package org.eclipse.tractusx.edc.core.utils; public class PathUtils { diff --git a/edc-extensions/ssi/ssi-miw-credential-client/src/test/java/org/eclipse/tractusx/edc/iam/ssi/miw/utils/PathUtilsTest.java b/core/core-utils/src/test/java/org/eclipse/tractusx/edc/core/utils/PathUtilsTest.java similarity index 97% rename from edc-extensions/ssi/ssi-miw-credential-client/src/test/java/org/eclipse/tractusx/edc/iam/ssi/miw/utils/PathUtilsTest.java rename to core/core-utils/src/test/java/org/eclipse/tractusx/edc/core/utils/PathUtilsTest.java index 9f8879fb1..1654d8690 100644 --- a/edc-extensions/ssi/ssi-miw-credential-client/src/test/java/org/eclipse/tractusx/edc/iam/ssi/miw/utils/PathUtilsTest.java +++ b/core/core-utils/src/test/java/org/eclipse/tractusx/edc/core/utils/PathUtilsTest.java @@ -17,7 +17,7 @@ * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ -package org.eclipse.tractusx.edc.iam.ssi.miw.utils; +package org.eclipse.tractusx.edc.core.utils; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.params.ParameterizedTest; diff --git a/edc-extensions/iatp/tx-iatp-sts-dim/build.gradle.kts b/edc-extensions/iatp/tx-iatp-sts-dim/build.gradle.kts new file mode 100644 index 000000000..1286f6cf1 --- /dev/null +++ b/edc-extensions/iatp/tx-iatp-sts-dim/build.gradle.kts @@ -0,0 +1,32 @@ +/******************************************************************************** + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +plugins { + `java-library` + `maven-publish` +} + +dependencies { + implementation(libs.edc.identity.trust.spi) + implementation(libs.edc.auth.oauth2.client) + implementation(project(":spi:core-spi")) + implementation(project(":core:core-utils")) + + testImplementation(libs.edc.junit) +} diff --git a/edc-extensions/iatp/tx-iatp-sts-dim/src/main/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/DimOauthClientExtension.java b/edc-extensions/iatp/tx-iatp-sts-dim/src/main/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/DimOauthClientExtension.java new file mode 100644 index 000000000..a21184a80 --- /dev/null +++ b/edc-extensions/iatp/tx-iatp-sts-dim/src/main/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/DimOauthClientExtension.java @@ -0,0 +1,59 @@ +/******************************************************************************** + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +package org.eclipse.tractusx.edc.iam.iatp.sts.dim; + +import org.eclipse.edc.iam.oauth2.spi.client.Oauth2Client; +import org.eclipse.edc.runtime.metamodel.annotation.Extension; +import org.eclipse.edc.runtime.metamodel.annotation.Inject; +import org.eclipse.edc.runtime.metamodel.annotation.Provider; +import org.eclipse.edc.spi.security.Vault; +import org.eclipse.edc.spi.system.ServiceExtension; +import org.eclipse.tractusx.edc.iam.iatp.sts.dim.oauth.DimOauth2Client; +import org.eclipse.tractusx.edc.iam.iatp.sts.dim.oauth.DimOauthClientImpl; + +/** + * Extension that provides an implementation if {@link DimOauth2Client} using {@link Oauth2Client} + * and the {@link StsRemoteClientConfiguration} configuration for fetching an OAuth token + */ +@Extension(DimOauthClientExtension.NAME) +public class DimOauthClientExtension implements ServiceExtension { + + protected static final String NAME = "DIM OAuth client extension"; + + @Inject + private StsRemoteClientConfiguration clientConfiguration; + + @Inject + private Oauth2Client oauth2Client; + + @Inject + private Vault vault; + + @Override + public String name() { + return NAME; + } + + @Provider + public DimOauth2Client oauth2Client() { + return new DimOauthClientImpl(oauth2Client, vault, clientConfiguration); + } + +} \ No newline at end of file diff --git a/edc-extensions/iatp/tx-iatp-sts-dim/src/main/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/DimSecureTokenService.java b/edc-extensions/iatp/tx-iatp-sts-dim/src/main/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/DimSecureTokenService.java new file mode 100644 index 000000000..1de0a017f --- /dev/null +++ b/edc-extensions/iatp/tx-iatp-sts-dim/src/main/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/DimSecureTokenService.java @@ -0,0 +1,227 @@ +/******************************************************************************** + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +package org.eclipse.tractusx.edc.iam.iatp.sts.dim; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; +import okhttp3.MediaType; +import okhttp3.Request; +import okhttp3.RequestBody; +import okhttp3.Response; +import org.eclipse.edc.identitytrust.SecureTokenService; +import org.eclipse.edc.spi.http.EdcHttpClient; +import org.eclipse.edc.spi.iam.TokenRepresentation; +import org.eclipse.edc.spi.monitor.Monitor; +import org.eclipse.edc.spi.result.Result; +import org.eclipse.tractusx.edc.iam.iatp.sts.dim.oauth.DimOauth2Client; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.io.IOException; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.Set; +import java.util.function.Consumer; + +import static java.lang.String.format; +import static org.eclipse.edc.identitytrust.SelfIssuedTokenConstants.PRESENTATION_ACCESS_TOKEN_CLAIM; +import static org.eclipse.edc.jwt.spi.JwtRegisteredClaimNames.AUDIENCE; +import static org.eclipse.edc.jwt.spi.JwtRegisteredClaimNames.ISSUER; +import static org.eclipse.edc.jwt.spi.JwtRegisteredClaimNames.SUBJECT; +import static org.eclipse.edc.spi.http.FallbackFactories.retryWhenStatusIsNotIn; + +/** + * Implementation of {@link SecureTokenService} that talks with DIM wallet. It supports two APIs for fetching the + * SI Token: + *
    + *
  • grantAccess: request the SI token to DIM by providing the credential types required
  • + *
  • signToken: request the SI token to DIM by providing the extracted `access_token` from the received SI token
  • + *
+ */ +public class DimSecureTokenService implements SecureTokenService { + + public static final MediaType TYPE_JSON = MediaType.parse("application/json"); + public static final String READ_SCOPE = "read"; + public static final String GRANT_ACCESS = "grantAccess"; + public static final String SCOPE = "scope"; + public static final String CREDENTIAL_TYPES = "credentialTypes"; + public static final String SIGN_TOKEN = "signToken"; + + private final EdcHttpClient httpClient; + private final String dimUrl; + private final DimOauth2Client dimOauth2Client; + private final ObjectMapper mapper; + private final Monitor monitor; + + private final Map grantAccessMapper = Map.of( + ISSUER, "consumerDid", + AUDIENCE, "providerDid"); + + private final Map signTokenMapper = Map.of( + AUDIENCE, "audience", + ISSUER, "issuer", + SUBJECT, "subject", + PRESENTATION_ACCESS_TOKEN_CLAIM, "token"); + + public DimSecureTokenService(EdcHttpClient httpClient, String dimBaseUrl, DimOauth2Client dimOauth2Client, ObjectMapper mapper, Monitor monitor) { + this.httpClient = httpClient; + this.dimUrl = dimBaseUrl + "/iatp"; + this.dimOauth2Client = dimOauth2Client; + this.mapper = mapper; + this.monitor = monitor; + } + + @Override + public Result createToken(Map claims, @Nullable String bearerAccessScope) { + return Optional.ofNullable(bearerAccessScope) + .map(scope -> grantAccessRequest(claims, scope)) + .orElseGet(() -> signTokenRequest(claims)); + } + + private Result grantAccessRequest(Map claims, @Nullable String bearerAccessScope) { + return grantAccessPayload(claims, bearerAccessScope) + .compose(this::postRequest) + .map(builder -> builder.url(dimUrl).build()) + .compose(request -> executeRequest(request, GRANT_ACCESS)); + } + + private Result signTokenRequest(Map claims) { + return signTokenPayload(claims) + .compose(this::postRequest) + .map(builder -> builder.url(dimUrl).build()) + .compose(request -> executeRequest(request, SIGN_TOKEN)); + } + + private Result> grantAccessPayload(Map claims, String bearerAccessScope) { + return mapClaims(claims, grantAccessMapper) + .compose(payload -> extractScopes(bearerAccessScope) + .onSuccess(scopes -> payload.put(CREDENTIAL_TYPES, scopes)) + .compose(i -> Result.success(payload))) + .map(payload -> { + payload.put(SCOPE, READ_SCOPE); + return Map.of(GRANT_ACCESS, payload); + }); + } + + private Result> extractScopes(String bearerAccessScope) { + var scopes = new HashSet(); + var split = bearerAccessScope.split(" "); + + var result = Arrays.stream(split) + .map(scope -> extractCredential(scope, scopes::add)) + .reduce(Result::merge) + .orElseGet(Result::success); + + if (result.succeeded()) { + return Result.success(scopes); + } else { + return Result.failure(result.getFailureDetail()); + } + } + + private Result extractCredential(String scope, Consumer consumer) { + var tokens = scope.split(":"); + if (tokens.length != 3) { + return Result.failure("Scope string %s has invalid format".formatted(scope)); + } + consumer.accept(tokens[1]); + return Result.success(); + } + + @NotNull + private Result> signTokenPayload(Map claims) { + return mapClaims(claims, signTokenMapper) + .map(payload -> Map.of(SIGN_TOKEN, payload)); + } + + private Result executeRequest(Request request, String context) { + return httpClient.execute(request, List.of(retryWhenStatusIsNotIn(200, 201)), this::handleResponse) + .recover(failure -> Result.failure("[%s] %s".formatted(context, failure.getFailureDetail()))); + } + + private Result handleResponse(Response response) { + try { + var body = Objects.requireNonNull(response.body()).string(); + var parsedBody = mapper.readValue(body, new TypeReference>() { + }); + return Optional.ofNullable(parsedBody.get("jwt")) + .map(token -> TokenRepresentation.Builder.newInstance().token(token).build()) + .map(Result::success) + .orElseGet(() -> Result.failure("Failed to get jwt field")); + } catch (IOException e) { + monitor.severe("Failed to parse response from DIM"); + return Result.failure(e.getMessage()); + } + } + + private Result postRequest(Map body) { + try { + var requestBody = RequestBody.create(mapper.writeValueAsString(body), TYPE_JSON); + return baseRequestWithToken() + .map(builder -> builder.post(requestBody)); + } catch (JsonProcessingException e) { + return Result.failure(e.getMessage()); + } + + } + + private Result baseRequestWithToken() { + return dimOauth2Client.obtainRequestToken() + .map(this::baseRequestWithToken); + } + + private Request.Builder baseRequestWithToken(TokenRepresentation tokenRepresentation) { + return new Request.Builder() + .addHeader("Authorization", format("Bearer %s", tokenRepresentation.getToken())); + } + + private Result> mapClaims(Map claims, Map mappings) { + var payload = new HashMap(); + var result = mappings.entrySet().stream() + .map((entry -> mapClaim(claims, entry))) + .peek(inner -> inner.onSuccess(mapped -> payload.put(mapped.getKey(), mapped.getValue()))) + .map(Result::mapTo) + .reduce(Result::merge) + .orElseGet(() -> Result.success(null)); + + if (result.failed()) { + return Result.failure(result.getFailureDetail()); + } else { + return Result.success(payload); + } + + } + + private Result> mapClaim(Map claims, Map.Entry mapping) { + var value = claims.get(mapping.getKey()); + if (value != null) { + return Result.success(Map.entry(mapping.getValue(), value)); + } else { + return Result.failure("Key %s not found in the input claims".formatted(mapping.getKey())); + } + } + +} diff --git a/edc-extensions/iatp/tx-iatp-sts-dim/src/main/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/DimSecureTokenServiceExtension.java b/edc-extensions/iatp/tx-iatp-sts-dim/src/main/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/DimSecureTokenServiceExtension.java new file mode 100644 index 000000000..5b161a848 --- /dev/null +++ b/edc-extensions/iatp/tx-iatp-sts-dim/src/main/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/DimSecureTokenServiceExtension.java @@ -0,0 +1,68 @@ +/******************************************************************************** + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +package org.eclipse.tractusx.edc.iam.iatp.sts.dim; + +import org.eclipse.edc.identitytrust.SecureTokenService; +import org.eclipse.edc.runtime.metamodel.annotation.Extension; +import org.eclipse.edc.runtime.metamodel.annotation.Inject; +import org.eclipse.edc.runtime.metamodel.annotation.Provider; +import org.eclipse.edc.runtime.metamodel.annotation.Setting; +import org.eclipse.edc.spi.http.EdcHttpClient; +import org.eclipse.edc.spi.monitor.Monitor; +import org.eclipse.edc.spi.system.ServiceExtension; +import org.eclipse.edc.spi.system.ServiceExtensionContext; +import org.eclipse.edc.spi.types.TypeManager; +import org.eclipse.tractusx.edc.iam.iatp.sts.dim.oauth.DimOauth2Client; + +import static org.eclipse.tractusx.edc.core.utils.PathUtils.removeTrailingSlash; + +@Extension(DimSecureTokenServiceExtension.NAME) +public class DimSecureTokenServiceExtension implements ServiceExtension { + + @Setting(value = "STS Dim endpoint") + public static final String DIM_URL = "edc.iam.sts.dim.url"; + protected static final String NAME = "DIM Secure token service extension"; + + @Inject + private StsRemoteClientConfiguration stsRemoteClientConfiguration; + + @Inject + private DimOauth2Client dimOauth2Client; + + @Inject + private EdcHttpClient httpClient; + + @Inject + private Monitor monitor; + + @Inject + private TypeManager typeManager; + + @Override + public String name() { + return NAME; + } + + @Provider + public SecureTokenService secureTokenService(ServiceExtensionContext context) { + return new DimSecureTokenService(httpClient, removeTrailingSlash(context.getConfig().getString(DIM_URL)), dimOauth2Client, typeManager.getMapper(), monitor); + } + +} \ No newline at end of file diff --git a/edc-extensions/iatp/tx-iatp-sts-dim/src/main/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/DimStsConfigurationExtension.java b/edc-extensions/iatp/tx-iatp-sts-dim/src/main/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/DimStsConfigurationExtension.java new file mode 100644 index 000000000..e0e653438 --- /dev/null +++ b/edc-extensions/iatp/tx-iatp-sts-dim/src/main/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/DimStsConfigurationExtension.java @@ -0,0 +1,62 @@ +/******************************************************************************** + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +package org.eclipse.tractusx.edc.iam.iatp.sts.dim; + +import org.eclipse.edc.runtime.metamodel.annotation.Extension; +import org.eclipse.edc.runtime.metamodel.annotation.Provider; +import org.eclipse.edc.runtime.metamodel.annotation.Setting; +import org.eclipse.edc.spi.system.ServiceExtension; +import org.eclipse.edc.spi.system.ServiceExtensionContext; + +import static org.eclipse.tractusx.edc.core.utils.PathUtils.removeTrailingSlash; + +/** + * Configuration Extension for the STS OAuth2 client + */ +@Extension(DimStsConfigurationExtension.NAME) +public class DimStsConfigurationExtension implements ServiceExtension { + + @Setting(value = "STS OAuth2 endpoint for requesting a token") + public static final String TOKEN_URL = "edc.iam.sts.oauth.token.url"; + + @Setting(value = "STS OAuth2 client id") + public static final String CLIENT_ID = "edc.iam.sts.oauth.client.id"; + + @Setting(value = "Vault alias of STS OAuth2 client secret") + public static final String CLIENT_SECRET_ALIAS = "edc.iam.sts.oauth.client.secret.alias"; + + protected static final String NAME = "DIM STS client configuration extension"; + + @Override + public String name() { + return NAME; + } + + @Provider + public StsRemoteClientConfiguration clientConfiguration(ServiceExtensionContext context) { + + var tokenUrl = removeTrailingSlash(context.getConfig().getString(TOKEN_URL)); + var clientId = context.getConfig().getString(CLIENT_ID); + var clientSecretAlias = context.getConfig().getString(CLIENT_SECRET_ALIAS); + + return new StsRemoteClientConfiguration(tokenUrl, clientId, clientSecretAlias); + } + +} diff --git a/edc-tests/runtime/iatp/iatp-extensions/src/main/java/org/eclipse/tractusx/edc/iatp/policy/BaseCredentialEvaluationFunction.java b/edc-extensions/iatp/tx-iatp-sts-dim/src/main/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/StsRemoteClientConfiguration.java similarity index 60% rename from edc-tests/runtime/iatp/iatp-extensions/src/main/java/org/eclipse/tractusx/edc/iatp/policy/BaseCredentialEvaluationFunction.java rename to edc-extensions/iatp/tx-iatp-sts-dim/src/main/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/StsRemoteClientConfiguration.java index de45f5d0a..35cd8c913 100644 --- a/edc-tests/runtime/iatp/iatp-extensions/src/main/java/org/eclipse/tractusx/edc/iatp/policy/BaseCredentialEvaluationFunction.java +++ b/edc-extensions/iatp/tx-iatp-sts-dim/src/main/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/StsRemoteClientConfiguration.java @@ -17,20 +17,17 @@ * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ -package org.eclipse.tractusx.edc.iatp.policy; +package org.eclipse.tractusx.edc.iam.iatp.sts.dim; -import org.eclipse.edc.policy.engine.spi.AtomicConstraintFunction; -import org.eclipse.edc.policy.model.Permission; +import org.eclipse.edc.spi.security.Vault; -import java.util.Map; - -public abstract class BaseCredentialEvaluationFunction implements AtomicConstraintFunction { +/** + * Configuration of the OAuth2 client for the OAuth2 Client credentials flow + * + * @param tokenUrl The token endpoint + * @param clientId The identifier of the client + * @param clientSecretAlias The client secret alias to be used with the {@link Vault} for fetching the secret + */ +public record StsRemoteClientConfiguration(String tokenUrl, String clientId, String clientSecretAlias) { - protected T getClaim(Class type, String postfix, Map claims) { - return claims.entrySet().stream().filter(e -> e.getKey().endsWith(postfix)) - .findFirst() - .map(Map.Entry::getValue) - .map(type::cast) - .orElse(null); - } } diff --git a/edc-extensions/iatp/tx-iatp-sts-dim/src/main/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/oauth/DimOauth2Client.java b/edc-extensions/iatp/tx-iatp-sts-dim/src/main/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/oauth/DimOauth2Client.java new file mode 100644 index 000000000..e3aff4b97 --- /dev/null +++ b/edc-extensions/iatp/tx-iatp-sts-dim/src/main/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/oauth/DimOauth2Client.java @@ -0,0 +1,38 @@ +/******************************************************************************** + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +package org.eclipse.tractusx.edc.iam.iatp.sts.dim.oauth; + +import org.eclipse.edc.runtime.metamodel.annotation.ExtensionPoint; +import org.eclipse.edc.spi.iam.TokenRepresentation; +import org.eclipse.edc.spi.result.Result; + +/** + * OAuth2 client for fetching an access token to be added when using the DIM APIs + */ +@ExtensionPoint +public interface DimOauth2Client { + + /** + * Request a token from the Auth server + * + * @return The {@link TokenRepresentation} + */ + Result obtainRequestToken(); +} diff --git a/edc-extensions/iatp/tx-iatp-sts-dim/src/main/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/oauth/DimOauthClientImpl.java b/edc-extensions/iatp/tx-iatp-sts-dim/src/main/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/oauth/DimOauthClientImpl.java new file mode 100644 index 000000000..d0b3f2fcc --- /dev/null +++ b/edc-extensions/iatp/tx-iatp-sts-dim/src/main/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/oauth/DimOauthClientImpl.java @@ -0,0 +1,66 @@ +/******************************************************************************** + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +package org.eclipse.tractusx.edc.iam.iatp.sts.dim.oauth; + +import org.eclipse.edc.iam.oauth2.spi.client.Oauth2Client; +import org.eclipse.edc.iam.oauth2.spi.client.Oauth2CredentialsRequest; +import org.eclipse.edc.iam.oauth2.spi.client.SharedSecretOauth2CredentialsRequest; +import org.eclipse.edc.spi.iam.TokenRepresentation; +import org.eclipse.edc.spi.result.Result; +import org.eclipse.edc.spi.security.Vault; +import org.eclipse.tractusx.edc.iam.iatp.sts.dim.StsRemoteClientConfiguration; +import org.jetbrains.annotations.NotNull; + +public class DimOauthClientImpl implements DimOauth2Client { + + private static final String GRANT_TYPE = "client_credentials"; + private final StsRemoteClientConfiguration configuration; + private final Oauth2Client oauth2Client; + + private final Vault vault; + + public DimOauthClientImpl(Oauth2Client oauth2Client, Vault vault, StsRemoteClientConfiguration configuration) { + this.configuration = configuration; + this.oauth2Client = oauth2Client; + this.vault = vault; + } + + @Override + public Result obtainRequestToken() { + return createRequest().compose(oauth2Client::requestToken); + + } + + @NotNull + private Result createRequest() { + var secret = vault.resolveSecret(configuration.clientSecretAlias()); + if (secret != null) { + var builder = SharedSecretOauth2CredentialsRequest.Builder.newInstance() + .url(configuration.tokenUrl()) + .clientId(configuration.clientId()) + .clientSecret(secret) + .grantType(GRANT_TYPE); + + return Result.success(builder.build()); + } else { + return Result.failure("Failed to fetch client secret from the vault with alias: %s".formatted(configuration.clientSecretAlias())); + } + } +} diff --git a/edc-extensions/iatp/tx-iatp-sts-dim/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension b/edc-extensions/iatp/tx-iatp-sts-dim/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension new file mode 100644 index 000000000..dfaffa2a0 --- /dev/null +++ b/edc-extensions/iatp/tx-iatp-sts-dim/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension @@ -0,0 +1,23 @@ +################################################################################# +# Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License, Version 2.0 which is available at +# https://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. +# +# SPDX-License-Identifier: Apache-2.0 +################################################################################# + +org.eclipse.tractusx.edc.iam.iatp.sts.dim.DimOauthClientExtension +org.eclipse.tractusx.edc.iam.iatp.sts.dim.DimSecureTokenServiceExtension +org.eclipse.tractusx.edc.iam.iatp.sts.dim.DimStsConfigurationExtension + diff --git a/edc-extensions/iatp/tx-iatp-sts-dim/src/test/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/DimOauthClientExtensionTest.java b/edc-extensions/iatp/tx-iatp-sts-dim/src/test/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/DimOauthClientExtensionTest.java new file mode 100644 index 000000000..0c366f52d --- /dev/null +++ b/edc-extensions/iatp/tx-iatp-sts-dim/src/test/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/DimOauthClientExtensionTest.java @@ -0,0 +1,45 @@ +/******************************************************************************** + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +package org.eclipse.tractusx.edc.iam.iatp.sts.dim; + +import org.eclipse.edc.junit.extensions.DependencyInjectionExtension; +import org.eclipse.edc.spi.system.ServiceExtensionContext; +import org.eclipse.tractusx.edc.iam.iatp.sts.dim.oauth.DimOauthClientImpl; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; + +import static org.assertj.core.api.Assertions.assertThat; + +@ExtendWith(DependencyInjectionExtension.class) +public class DimOauthClientExtensionTest { + + @BeforeEach + void setup(ServiceExtensionContext context) { + + } + + @Test + void initialize(DimOauthClientExtension extension) { + assertThat(extension.oauth2Client()).isInstanceOf(DimOauthClientImpl.class); + } + + +} diff --git a/edc-extensions/iatp/tx-iatp-sts-dim/src/test/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/DimSecureServiceExtensionTest.java b/edc-extensions/iatp/tx-iatp-sts-dim/src/test/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/DimSecureServiceExtensionTest.java new file mode 100644 index 000000000..36d836bb5 --- /dev/null +++ b/edc-extensions/iatp/tx-iatp-sts-dim/src/test/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/DimSecureServiceExtensionTest.java @@ -0,0 +1,51 @@ +/******************************************************************************** + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +package org.eclipse.tractusx.edc.iam.iatp.sts.dim; + +import org.eclipse.edc.junit.extensions.DependencyInjectionExtension; +import org.eclipse.edc.spi.EdcException; +import org.eclipse.edc.spi.system.ServiceExtensionContext; +import org.eclipse.edc.spi.system.configuration.Config; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.eclipse.tractusx.edc.iam.iatp.sts.dim.DimSecureTokenServiceExtension.DIM_URL; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +@ExtendWith(DependencyInjectionExtension.class) +public class DimSecureServiceExtensionTest { + + @Test + void initialize(ServiceExtensionContext context, DimSecureTokenServiceExtension extension) { + var config = mock(Config.class); + when(context.getConfig()).thenReturn(config); + when(config.getString(DIM_URL)).thenReturn("url"); + assertThat(extension.secureTokenService(context)).isInstanceOf(DimSecureTokenService.class); + } + + @Test + void initialize_shouldThrow_whenUrlIsMissing(ServiceExtensionContext context, DimSecureTokenServiceExtension extension) { + assertThatThrownBy(() -> extension.secureTokenService(context)).isInstanceOf(EdcException.class); + } + +} diff --git a/edc-extensions/iatp/tx-iatp-sts-dim/src/test/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/DimSecureTokenServiceTest.java b/edc-extensions/iatp/tx-iatp-sts-dim/src/test/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/DimSecureTokenServiceTest.java new file mode 100644 index 000000000..7254dac34 --- /dev/null +++ b/edc-extensions/iatp/tx-iatp-sts-dim/src/test/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/DimSecureTokenServiceTest.java @@ -0,0 +1,299 @@ +/******************************************************************************** + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +package org.eclipse.tractusx.edc.iam.iatp.sts.dim; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; +import okhttp3.Interceptor; +import okhttp3.MediaType; +import okhttp3.Protocol; +import okhttp3.Request; +import okhttp3.Response; +import okhttp3.ResponseBody; +import okio.Buffer; +import org.eclipse.edc.spi.iam.TokenRepresentation; +import org.eclipse.edc.spi.monitor.Monitor; +import org.eclipse.edc.spi.result.Result; +import org.eclipse.tractusx.edc.iam.iatp.sts.dim.oauth.DimOauth2Client; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.invocation.InvocationOnMock; + +import java.io.IOException; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.function.Consumer; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.eclipse.edc.identitytrust.SelfIssuedTokenConstants.PRESENTATION_ACCESS_TOKEN_CLAIM; +import static org.eclipse.edc.junit.assertions.AbstractResultAssert.assertThat; +import static org.eclipse.edc.junit.testfixtures.TestUtils.testHttpClient; +import static org.eclipse.edc.jwt.spi.JwtRegisteredClaimNames.AUDIENCE; +import static org.eclipse.edc.jwt.spi.JwtRegisteredClaimNames.ISSUER; +import static org.eclipse.edc.jwt.spi.JwtRegisteredClaimNames.SUBJECT; +import static org.mockito.ArgumentMatchers.isA; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + + +public class DimSecureTokenServiceTest { + + static final String BASE_URL = "http://localhost:8080"; + private final Monitor monitor = mock(Monitor.class); + private final DimOauth2Client oauth2Client = mock(DimOauth2Client.class); + private final ObjectMapper mapper = new ObjectMapper(); + private final Interceptor interceptor = mock(Interceptor.class); + private DimSecureTokenService client; + + @BeforeEach + void setup() { + client = new DimSecureTokenService(testHttpClient(interceptor), BASE_URL, oauth2Client, mapper, monitor); + } + + @SuppressWarnings({ "unchecked", "rawtypes" }) + @Test + void createToken_grantAccess() throws IOException { + var response = Map.of("jwt", "responseToken"); + Consumer requestAcceptor = (request) -> { + + var expectedBody = Map.of( + "consumerDid", "issuer", + "scope", "read", + "credentialTypes", List.of("TestCredential"), + "providerDid", "audience"); + var body = getBody(request, new TypeReference>() { + }); + + assertThat(body).extractingByKey("grantAccess").satisfies(payload -> { + assertThat(((Map) payload)).containsAllEntriesOf(expectedBody); + }); + + assertThat(request.url().url().toString()).isEqualTo(BASE_URL + "/iatp"); + + }; + + when(oauth2Client.obtainRequestToken()).thenReturn(Result.success(TokenRepresentation.Builder.newInstance().token("token").build())); + when(interceptor.intercept(isA(Interceptor.Chain.class))) + .thenAnswer(invocation -> createResponse(200, invocation, requestAcceptor, response)); + + var input = Map.of(ISSUER, "issuer", AUDIENCE, "audience"); + var result = client.createToken(input, "namespace:TestCredential:read"); + + + assertThat(result).isSucceeded() + .extracting(TokenRepresentation::getToken) + .isEqualTo("responseToken"); + } + + @SuppressWarnings({ "unchecked", "rawtypes" }) + @Test + void createToken_signToken() throws IOException { + var response = Map.of("jwt", "responseToken"); + Consumer requestAcceptor = (request) -> { + var expectedBody = Map.of( + "issuer", "issuer", + "audience", "audience", + "subject", "issuer", + "token", "accessToken"); + var body = getBody(request, new TypeReference>() { + }); + + assertThat(body).extractingByKey("signToken").satisfies(payload -> { + assertThat(((Map) payload)).containsAllEntriesOf(expectedBody); + }); + + assertThat(request.url().url().toString()).isEqualTo(BASE_URL + "/iatp"); + + }; + + when(oauth2Client.obtainRequestToken()).thenReturn(Result.success(TokenRepresentation.Builder.newInstance().token("token").build())); + when(interceptor.intercept(isA(Interceptor.Chain.class))) + .thenAnswer(invocation -> createResponse(200, invocation, requestAcceptor, response)); + + var input = Map.of(ISSUER, "issuer", SUBJECT, "issuer", AUDIENCE, "audience", PRESENTATION_ACCESS_TOKEN_CLAIM, "accessToken"); + var result = client.createToken(input, null); + + assertThat(result).isSucceeded() + .extracting(TokenRepresentation::getToken) + .isEqualTo("responseToken"); + } + + @Test + void createToken_grantFails_withDimFailure() throws IOException { + + when(oauth2Client.obtainRequestToken()).thenReturn(Result.success(TokenRepresentation.Builder.newInstance().token("token").build())); + when(interceptor.intercept(isA(Interceptor.Chain.class))) + .thenAnswer(invocation -> createResponse(500, invocation)); + + var input = Map.of(ISSUER, "issuer", AUDIENCE, "audience"); + var result = client.createToken(input, "namespace:TestCredential:read"); + + assertThat(result).isFailed() + .satisfies(failure -> assertThat(failure.getFailureDetail()).contains("grantAccess")); + + } + + @Test + void createToken_grantFails_whenClaimsMissing() throws IOException { + + when(oauth2Client.obtainRequestToken()).thenReturn(Result.success(TokenRepresentation.Builder.newInstance().token("token").build())); + when(interceptor.intercept(isA(Interceptor.Chain.class))) + .thenAnswer(invocation -> createResponse(500, invocation)); + + var input = Map.of("foo", "bar"); + var result = client.createToken(input, "namespace:TestCredential:read"); + + assertThat(result).isFailed() + .satisfies(failure -> assertThat(failure.getFailureDetail()) + .contains("Key iss not found") + .contains("Key aud not found")); + + } + + @Test + void createToken_grantFails_whenBadResponsePayload() throws IOException { + + when(oauth2Client.obtainRequestToken()).thenReturn(Result.success(TokenRepresentation.Builder.newInstance().token("token").build())); + when(interceptor.intercept(isA(Interceptor.Chain.class))) + .thenAnswer(invocation -> createResponse(200, invocation, Map.of())); + + var input = Map.of(ISSUER, "issuer", AUDIENCE, "audience"); + var result = client.createToken(input, "namespace:TestCredential:read"); + + assertThat(result).isFailed() + .satisfies(failure -> assertThat(failure.getFailureDetail()) + .contains("[grantAccess] Failed to get jwt field")); + + } + + @Test + void createToken_grantFails_whenInvalidScope() throws IOException { + + when(oauth2Client.obtainRequestToken()).thenReturn(Result.success(TokenRepresentation.Builder.newInstance().token("token").build())); + when(interceptor.intercept(isA(Interceptor.Chain.class))) + .thenAnswer(invocation -> createResponse(500, invocation)); + + var input = Map.of(ISSUER, "issuer", AUDIENCE, "audience"); + var result = client.createToken(input, "invalidScope"); + + assertThat(result).isFailed() + .satisfies(failure -> assertThat(failure.getFailureDetail()) + .contains("Scope string invalidScope has invalid format")); + + } + + @Test + void createToken_signFails_withDimFailure() throws IOException { + + when(oauth2Client.obtainRequestToken()).thenReturn(Result.success(TokenRepresentation.Builder.newInstance().token("token").build())); + when(interceptor.intercept(isA(Interceptor.Chain.class))) + .thenAnswer(invocation -> createResponse(500, invocation)); + + var input = Map.of(ISSUER, "issuer", SUBJECT, "issuer", AUDIENCE, "audience", PRESENTATION_ACCESS_TOKEN_CLAIM, "token"); + var result = client.createToken(input, null); + + assertThat(result).isFailed() + .satisfies(failure -> assertThat(failure.getFailureDetail()).contains("signToken")); + + } + + @Test + void createToken_signFails_whenBadResponsePayload() throws IOException { + + when(oauth2Client.obtainRequestToken()).thenReturn(Result.success(TokenRepresentation.Builder.newInstance().token("token").build())); + when(interceptor.intercept(isA(Interceptor.Chain.class))) + .thenAnswer(invocation -> createResponse(200, invocation, Map.of())); + + var input = Map.of(ISSUER, "issuer", SUBJECT, "issuer", AUDIENCE, "audience", PRESENTATION_ACCESS_TOKEN_CLAIM, "token"); + var result = client.createToken(input, null); + + assertThat(result).isFailed() + .satisfies(failure -> assertThat(failure.getFailureDetail()) + .contains("[signToken] Failed to get jwt field")); + + } + + @Test + void createToken_signFails_whenClaimsMissing() throws IOException { + + when(oauth2Client.obtainRequestToken()).thenReturn(Result.success(TokenRepresentation.Builder.newInstance().token("token").build())); + when(interceptor.intercept(isA(Interceptor.Chain.class))) + .thenAnswer(invocation -> createResponse(500, invocation)); + + var input = Map.of("foo", "bar"); + var result = client.createToken(input, null); + + assertThat(result).isFailed() + .satisfies(failure -> assertThat(failure.getFailureDetail()) + .contains("Key iss not found") + .contains("Key sub not found") + .contains("Key access_token not found") + .contains("Key aud not found")); + + } + + private Response createResponse(int code, InvocationOnMock invocation) { + return createResponse(code, invocation, (req) -> { + }, null); + } + + private Response createResponse(int code, InvocationOnMock invocation, Object body) { + return createResponse(code, invocation, (req) -> { + }, body); + } + + + private Response createResponse(int code, InvocationOnMock invocation, Consumer consumer, Object body) { + var bodyString = Optional.ofNullable(body).map(this::toJson).orElse(""); + var request = getRequest(invocation); + consumer.accept(request); + return new Response.Builder() + .protocol(Protocol.HTTP_1_1) + .request(request) + .code(code) + .message("") + .body(ResponseBody.create(bodyString, MediaType.parse("application/json"))) + .build(); + } + + private String toJson(Object body) { + try { + return mapper.writeValueAsString(body); + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + } + + private T getBody(Request request, TypeReference typeReference) { + try (var buffer = new Buffer()) { + Objects.requireNonNull(request.body()).writeTo(buffer); + return mapper.readValue(buffer.inputStream(), typeReference); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private Request getRequest(InvocationOnMock invocation) { + return invocation.getArgument(0, Interceptor.Chain.class).request(); + } +} diff --git a/edc-extensions/iatp/tx-iatp-sts-dim/src/test/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/DimStsConfigurationExtensionTest.java b/edc-extensions/iatp/tx-iatp-sts-dim/src/test/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/DimStsConfigurationExtensionTest.java new file mode 100644 index 000000000..a2a8dc1da --- /dev/null +++ b/edc-extensions/iatp/tx-iatp-sts-dim/src/test/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/DimStsConfigurationExtensionTest.java @@ -0,0 +1,54 @@ +/******************************************************************************** + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +package org.eclipse.tractusx.edc.iam.iatp.sts.dim; + +import org.eclipse.edc.junit.extensions.DependencyInjectionExtension; +import org.eclipse.edc.spi.system.ServiceExtensionContext; +import org.eclipse.edc.spi.system.configuration.Config; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.eclipse.tractusx.edc.iam.iatp.sts.dim.DimStsConfigurationExtension.CLIENT_ID; +import static org.eclipse.tractusx.edc.iam.iatp.sts.dim.DimStsConfigurationExtension.CLIENT_SECRET_ALIAS; +import static org.eclipse.tractusx.edc.iam.iatp.sts.dim.DimStsConfigurationExtension.TOKEN_URL; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +@ExtendWith(DependencyInjectionExtension.class) +public class DimStsConfigurationExtensionTest { + + @Test + void initialize(ServiceExtensionContext context, DimStsConfigurationExtension extension) { + var config = mock(Config.class); + when(context.getConfig()).thenReturn(config); + when(config.getString(TOKEN_URL)).thenReturn("url"); + when(config.getString(CLIENT_ID)).thenReturn("clientId"); + when(config.getString(CLIENT_SECRET_ALIAS)).thenReturn("clientSecretAlias"); + + assertThat(extension.clientConfiguration(context)).satisfies(stsConfig -> { + assertThat(stsConfig.clientId()).isEqualTo("clientId"); + assertThat(stsConfig.clientSecretAlias()).isEqualTo("clientSecretAlias"); + assertThat(stsConfig.tokenUrl()).isEqualTo("url"); + }); + } + + +} diff --git a/edc-extensions/iatp/tx-iatp-sts-dim/src/test/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/oauth/DimOauthClientImplTest.java b/edc-extensions/iatp/tx-iatp-sts-dim/src/test/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/oauth/DimOauthClientImplTest.java new file mode 100644 index 000000000..9e48d50fa --- /dev/null +++ b/edc-extensions/iatp/tx-iatp-sts-dim/src/test/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/oauth/DimOauthClientImplTest.java @@ -0,0 +1,75 @@ +/******************************************************************************** + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +package org.eclipse.tractusx.edc.iam.iatp.sts.dim.oauth; + +import org.eclipse.edc.iam.oauth2.spi.client.Oauth2Client; +import org.eclipse.edc.iam.oauth2.spi.client.SharedSecretOauth2CredentialsRequest; +import org.eclipse.edc.spi.iam.TokenRepresentation; +import org.eclipse.edc.spi.result.Result; +import org.eclipse.edc.spi.security.Vault; +import org.eclipse.tractusx.edc.iam.iatp.sts.dim.StsRemoteClientConfiguration; +import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +public class DimOauthClientImplTest { + + private final Oauth2Client oauth2Client = mock(Oauth2Client.class); + + private final Vault vault = mock(Vault.class); + + @Test + void obtainRequestToken() { + var config = new StsRemoteClientConfiguration("http://localhost:8081/token", "clientId", "client_secret_alias"); + var tokenRepresentation = TokenRepresentation.Builder.newInstance().token("token").build(); + when(vault.resolveSecret("client_secret_alias")).thenReturn("client_secret"); + when(oauth2Client.requestToken(any())).thenReturn(Result.success(tokenRepresentation)); + var client = new DimOauthClientImpl(oauth2Client, vault, config); + + var response = client.obtainRequestToken(); + assertThat(response).isNotNull().extracting(Result::getContent).isEqualTo(tokenRepresentation); + + var captor = ArgumentCaptor.forClass(SharedSecretOauth2CredentialsRequest.class); + verify(oauth2Client).requestToken(captor.capture()); + + var request = captor.getValue(); + + assertThat(request.getClientId()).isEqualTo(config.clientId()); + assertThat(request.getClientSecret()).isEqualTo("client_secret"); + assertThat(request.getUrl()).isEqualTo(config.tokenUrl()); + + } + + @Test + void obtainRequestToken_failed() { + var config = new StsRemoteClientConfiguration("http://localhost:8081/token", "clientId", "client_secret"); + + when(oauth2Client.requestToken(any())).thenReturn(Result.failure("failure")); + var client = new DimOauthClientImpl(oauth2Client, vault, config); + + var response = client.obtainRequestToken(); + assertThat(response).isNotNull().matches(Result::failed); + } +} diff --git a/edc-extensions/iatp/tx-iatp/build.gradle.kts b/edc-extensions/iatp/tx-iatp/build.gradle.kts index af54a6311..03633b26c 100644 --- a/edc-extensions/iatp/tx-iatp/build.gradle.kts +++ b/edc-extensions/iatp/tx-iatp/build.gradle.kts @@ -25,7 +25,7 @@ plugins { dependencies { implementation(libs.edc.spi.core) implementation(libs.edc.spi.policyengine) - implementation(libs.edc.identity.core.trust) + implementation(libs.edc.identity.trust.spi) implementation(project(":spi:core-spi")) testImplementation(libs.edc.junit) diff --git a/edc-extensions/iatp/tx-iatp/src/main/java/org/eclipse/tractusx/edc/iam/iatp/IatpDefaultScopeExtension.java b/edc-extensions/iatp/tx-iatp/src/main/java/org/eclipse/tractusx/edc/iam/iatp/IatpDefaultScopeExtension.java index 3f5c8cec4..5f48e5226 100644 --- a/edc-extensions/iatp/tx-iatp/src/main/java/org/eclipse/tractusx/edc/iam/iatp/IatpDefaultScopeExtension.java +++ b/edc-extensions/iatp/tx-iatp/src/main/java/org/eclipse/tractusx/edc/iam/iatp/IatpDefaultScopeExtension.java @@ -33,9 +33,6 @@ import java.util.stream.Collectors; import static java.lang.String.format; -import static org.eclipse.edc.iam.identitytrust.core.IatpScopeExtractorExtension.CATALOG_REQUEST_SCOPE; -import static org.eclipse.edc.iam.identitytrust.core.IatpScopeExtractorExtension.NEGOTIATION_REQUEST_SCOPE; -import static org.eclipse.edc.iam.identitytrust.core.IatpScopeExtractorExtension.TRANSFER_PROCESS_REQUEST_SCOPE; import static org.eclipse.tractusx.edc.iam.iatp.IatpDefaultScopeExtension.NAME; import static org.eclipse.tractusx.edc.iam.iatp.TxIatpConstants.DEFAULT_SCOPES; @@ -54,9 +51,10 @@ public class IatpDefaultScopeExtension implements ServiceExtension { @Setting(context = TX_IATP_DEFAULT_SCOPE_PREFIX_CONFIG_ALIAS, value = "The alias of the scope e.g. read", required = true) public static final String OPERATION = "operation"; - + public static final String CATALOG_REQUEST_SCOPE = "request.catalog"; + public static final String NEGOTIATION_REQUEST_SCOPE = "request.contract.negotiation"; + public static final String TRANSFER_PROCESS_REQUEST_SCOPE = "request.transfer.process"; static final String NAME = "Tractusx default scope extension"; - @Inject private PolicyEngine policyEngine; diff --git a/edc-extensions/iatp/tx-iatp/src/test/java/org/eclipse/tractusx/edc/iam/iatp/IatpDefaultScopeExtensionTest.java b/edc-extensions/iatp/tx-iatp/src/test/java/org/eclipse/tractusx/edc/iam/iatp/IatpDefaultScopeExtensionTest.java index 7c7714424..70cb93136 100644 --- a/edc-extensions/iatp/tx-iatp/src/test/java/org/eclipse/tractusx/edc/iam/iatp/IatpDefaultScopeExtensionTest.java +++ b/edc-extensions/iatp/tx-iatp/src/test/java/org/eclipse/tractusx/edc/iam/iatp/IatpDefaultScopeExtensionTest.java @@ -34,9 +34,9 @@ import java.util.Set; import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.eclipse.edc.iam.identitytrust.core.IatpScopeExtractorExtension.CATALOG_REQUEST_SCOPE; -import static org.eclipse.edc.iam.identitytrust.core.IatpScopeExtractorExtension.NEGOTIATION_REQUEST_SCOPE; -import static org.eclipse.edc.iam.identitytrust.core.IatpScopeExtractorExtension.TRANSFER_PROCESS_REQUEST_SCOPE; +import static org.eclipse.tractusx.edc.iam.iatp.IatpDefaultScopeExtension.CATALOG_REQUEST_SCOPE; +import static org.eclipse.tractusx.edc.iam.iatp.IatpDefaultScopeExtension.NEGOTIATION_REQUEST_SCOPE; +import static org.eclipse.tractusx.edc.iam.iatp.IatpDefaultScopeExtension.TRANSFER_PROCESS_REQUEST_SCOPE; import static org.eclipse.tractusx.edc.iam.iatp.IatpDefaultScopeExtension.TX_IATP_DEFAULT_SCOPE_PREFIX; import static org.eclipse.tractusx.edc.iam.iatp.TxIatpConstants.DEFAULT_SCOPES; import static org.mockito.ArgumentMatchers.argThat; diff --git a/edc-extensions/ssi/ssi-miw-credential-client/build.gradle.kts b/edc-extensions/ssi/ssi-miw-credential-client/build.gradle.kts index c5babfce4..87da94438 100644 --- a/edc-extensions/ssi/ssi-miw-credential-client/build.gradle.kts +++ b/edc-extensions/ssi/ssi-miw-credential-client/build.gradle.kts @@ -24,6 +24,7 @@ plugins { dependencies { implementation(project(":spi:ssi-spi")) + implementation(project(":core:core-utils")) implementation(libs.edc.spi.core) implementation(libs.edc.spi.http) implementation(libs.edc.spi.jsonld) diff --git a/edc-extensions/ssi/ssi-miw-credential-client/src/main/java/org/eclipse/tractusx/edc/iam/ssi/miw/SsiMiwConfigurationExtension.java b/edc-extensions/ssi/ssi-miw-credential-client/src/main/java/org/eclipse/tractusx/edc/iam/ssi/miw/SsiMiwConfigurationExtension.java index 95e435608..22febc5b1 100644 --- a/edc-extensions/ssi/ssi-miw-credential-client/src/main/java/org/eclipse/tractusx/edc/iam/ssi/miw/SsiMiwConfigurationExtension.java +++ b/edc-extensions/ssi/ssi-miw-credential-client/src/main/java/org/eclipse/tractusx/edc/iam/ssi/miw/SsiMiwConfigurationExtension.java @@ -31,7 +31,7 @@ import java.nio.charset.StandardCharsets; import static java.lang.String.format; -import static org.eclipse.tractusx.edc.iam.ssi.miw.utils.PathUtils.removeTrailingSlash; +import static org.eclipse.tractusx.edc.core.utils.PathUtils.removeTrailingSlash; @Extension(SsiMiwConfigurationExtension.EXTENSION_NAME) diff --git a/edc-extensions/ssi/ssi-miw-credential-client/src/main/java/org/eclipse/tractusx/edc/iam/ssi/miw/SsiMiwOauth2ClientExtension.java b/edc-extensions/ssi/ssi-miw-credential-client/src/main/java/org/eclipse/tractusx/edc/iam/ssi/miw/SsiMiwOauth2ClientExtension.java index e4becb2c0..ae52fb374 100644 --- a/edc-extensions/ssi/ssi-miw-credential-client/src/main/java/org/eclipse/tractusx/edc/iam/ssi/miw/SsiMiwOauth2ClientExtension.java +++ b/edc-extensions/ssi/ssi-miw-credential-client/src/main/java/org/eclipse/tractusx/edc/iam/ssi/miw/SsiMiwOauth2ClientExtension.java @@ -33,7 +33,7 @@ import java.util.Objects; -import static org.eclipse.tractusx.edc.iam.ssi.miw.utils.PathUtils.removeTrailingSlash; +import static org.eclipse.tractusx.edc.core.utils.PathUtils.removeTrailingSlash; @Extension(SsiMiwOauth2ClientExtension.EXTENSION_NAME) diff --git a/edc-tests/e2e-tests/build.gradle.kts b/edc-tests/e2e-tests/build.gradle.kts index 378e8499d..52ae1929c 100644 --- a/edc-tests/e2e-tests/build.gradle.kts +++ b/edc-tests/e2e-tests/build.gradle.kts @@ -46,6 +46,8 @@ dependencies { testImplementation(libs.edc.identity.jws2020) testImplementation(libs.edc.identity.vc.ldp) testImplementation(libs.edc.ih.spi.store) + testImplementation(libs.edc.identity.trust.sts.embedded) + testImplementation(libs.edc.token.core) testImplementation(testFixtures(libs.edc.sql.core)) testImplementation(testFixtures(libs.edc.api.management.test.fixtures)) testImplementation(libs.awaitility) @@ -60,6 +62,7 @@ dependencies { testCompileOnly(project(":edc-tests:runtime:runtime-memory")) testCompileOnly(project(":edc-tests:runtime:iatp:runtime-memory-sts")) testCompileOnly(project(":edc-tests:runtime:iatp:runtime-memory-iatp-ih")) + testCompileOnly(project(":edc-tests:runtime:iatp:runtime-memory-iatp-dim-ih")) testCompileOnly(project(":edc-tests:runtime:runtime-memory-ssi")) testCompileOnly(project(":edc-tests:runtime:runtime-postgresql")) diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/helpers/IatpHelperFunctions.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/helpers/IatpHelperFunctions.java index 5ea0a7646..030360c39 100644 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/helpers/IatpHelperFunctions.java +++ b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/helpers/IatpHelperFunctions.java @@ -23,7 +23,20 @@ import jakarta.json.JsonArray; import jakarta.json.JsonObject; import org.bouncycastle.openssl.jcajce.JcaPEMWriter; +import org.eclipse.edc.iam.did.spi.document.DidDocument; +import org.eclipse.edc.iam.did.spi.resolution.DidResolverRegistry; +import org.eclipse.edc.identityhub.spi.ParticipantContextService; +import org.eclipse.edc.identityhub.spi.model.VerifiableCredentialResource; +import org.eclipse.edc.identityhub.spi.model.participant.KeyDescriptor; +import org.eclipse.edc.identityhub.spi.model.participant.ParticipantManifest; +import org.eclipse.edc.identityhub.spi.store.CredentialStore; +import org.eclipse.edc.jsonld.spi.JsonLd; import org.eclipse.edc.spi.EdcException; +import org.eclipse.edc.spi.security.Vault; +import org.eclipse.tractusx.edc.did.DidExampleResolver; +import org.eclipse.tractusx.edc.lifecycle.ParticipantRuntime; +import org.eclipse.tractusx.edc.lifecycle.tx.iatp.DataspaceIssuer; +import org.eclipse.tractusx.edc.lifecycle.tx.iatp.IatpParticipant; import org.testcontainers.shaded.org.bouncycastle.jce.provider.BouncyCastleProvider; import java.io.IOException; @@ -35,6 +48,8 @@ import java.security.NoSuchAlgorithmException; import java.security.spec.ECGenParameterSpec; import java.time.Instant; +import java.util.List; +import java.util.Map; import java.util.function.Supplier; public class IatpHelperFunctions { @@ -114,4 +129,46 @@ private static JsonArray context() { .add("https://catenax-ng.github.io/product-core-schemas/businessPartnerData.json") .build(); } + + public static void configureParticipant(DataspaceIssuer issuer, IatpParticipant participant, ParticipantRuntime runtime, Map dids, ParticipantRuntime stsRuntime) { + + if (stsRuntime != null) { + stsRuntime.getContext().getService(Vault.class).storeSecret(participant.verificationId(), participant.privateKey()); + } + var participantContextService = runtime.getContext().getService(ParticipantContextService.class); + var vault = runtime.getContext().getService(Vault.class); + var didResolverRegistry = runtime.getContext().getService(DidResolverRegistry.class); + var didResolver = new DidExampleResolver(); + dids.forEach(didResolver::addCached); + didResolverRegistry.register(didResolver); + + var key = KeyDescriptor.Builder.newInstance() + .keyId(participant.keyId()) + .publicKeyPem(participant.publicKey()) + .build(); + + var participantManifest = ParticipantManifest.Builder.newInstance() + .participantId(participant.didUrl()) + .did(participant.didUrl()) + .key(key) + .build(); + + participantContextService.createParticipantContext(participantManifest); + vault.storeSecret(participant.keyId(), participant.privateKey()); + + storeCredentials(issuer, participant, runtime); + } + + private static void storeCredentials(DataspaceIssuer issuer, IatpParticipant participant, ParticipantRuntime runtime) { + var credentialStore = runtime.getContext().getService(CredentialStore.class); + var jsonLd = runtime.getContext().getService(JsonLd.class); + issueCredentials(issuer, participant, jsonLd).forEach(credentialStore::create); + } + + private static List issueCredentials(DataspaceIssuer issuer, IatpParticipant participant, JsonLd jsonLd) { + return List.of( + issuer.issueMembershipCredential(participant, jsonLd), + issuer.issueFrameworkCredential(participant, jsonLd, "PcfCredential")); + + } } diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/tx/iatp/IatpDimParticipant.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/tx/iatp/IatpDimParticipant.java new file mode 100644 index 000000000..e35e1150e --- /dev/null +++ b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/tx/iatp/IatpDimParticipant.java @@ -0,0 +1,45 @@ +/******************************************************************************** + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +package org.eclipse.tractusx.edc.lifecycle.tx.iatp; + +import org.eclipse.tractusx.edc.lifecycle.tx.TxParticipant; + +import java.net.URI; +import java.util.HashMap; +import java.util.Map; + +/** + * Extension of {@link IatpParticipant} with DIM specific configuration + */ +public class IatpDimParticipant extends IatpParticipant { + private final URI dimUri; + + public IatpDimParticipant(TxParticipant participant, URI stsUri, URI dimUri) { + super(participant, stsUri); + this.dimUri = dimUri; + } + + @Override + public Map iatpConfiguration(TxParticipant... others) { + var config = new HashMap<>(super.iatpConfiguration(others)); + config.put("edc.iam.sts.dim.url", dimUri.toString()); + return config; + } +} diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/tx/iatp/IatpParticipant.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/tx/iatp/IatpParticipant.java index f5ed7d1a3..d992a2f96 100644 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/tx/iatp/IatpParticipant.java +++ b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/tx/iatp/IatpParticipant.java @@ -31,6 +31,7 @@ import java.security.interfaces.ECPrivateKey; import java.security.interfaces.ECPublicKey; import java.util.Arrays; +import java.util.Base64; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -47,7 +48,7 @@ */ public class IatpParticipant { - public static final String KEY_ID = "#key1"; + public static final String KEY_ID = "key1"; public static final String DID_EXAMPLE = "did:example:"; protected final URI csService = URI.create("http://localhost:" + getFreePort() + "/api/resolution"); private final TxParticipant participant; @@ -109,7 +110,11 @@ public String didUrl() { } public String verificationId() { - return didUrl() + KEY_ID; + return didUrl() + "#" + KEY_ID; + } + + public String keyId() { + return KEY_ID; } public String privateKey() { @@ -124,11 +129,16 @@ public DidDocument didDocument() { return didDocument; } + + public KeyPair getKeyPair() { + return keyPair; + } + private DidDocument generateDidDocument() { var service = new Service(); service.setId("#credential-service"); service.setType("CredentialService"); - service.setServiceEndpoint(csService + "/participants/" + getBpn()); + service.setServiceEndpoint(csService + "/v1/participants/" + toBase64(didUrl())); var ecKey = new ECKey.Builder(Curve.P_256, (ECPublicKey) keyPair.getPublic()) .privateKey((ECPrivateKey) keyPair.getPrivate()) @@ -149,4 +159,7 @@ private DidDocument generateDidDocument() { .build(); } + private String toBase64(String s) { + return Base64.getUrlEncoder().encodeToString(s.getBytes()); + } } diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/DimHttpConsumerPullWithProxyInMemoryTest.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/DimHttpConsumerPullWithProxyInMemoryTest.java new file mode 100644 index 000000000..7a377bba7 --- /dev/null +++ b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/DimHttpConsumerPullWithProxyInMemoryTest.java @@ -0,0 +1,136 @@ +/******************************************************************************** + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +package org.eclipse.tractusx.edc.tests.transfer; + +import jakarta.json.JsonObject; +import okhttp3.mockwebserver.MockWebServer; +import org.eclipse.edc.iam.did.spi.document.DidDocument; +import org.eclipse.edc.iam.identitytrust.sts.embedded.EmbeddedSecureTokenService; +import org.eclipse.edc.junit.annotations.EndToEndTest; +import org.eclipse.edc.token.JwtGenerationService; +import org.eclipse.edc.token.spi.TokenGenerationService; +import org.eclipse.tractusx.edc.lifecycle.ParticipantRuntime; +import org.eclipse.tractusx.edc.lifecycle.tx.iatp.DataspaceIssuer; +import org.eclipse.tractusx.edc.lifecycle.tx.iatp.IatpDimParticipant; +import org.eclipse.tractusx.edc.lifecycle.tx.iatp.SecureTokenService; +import org.eclipse.tractusx.edc.token.DimDispatcher; +import org.eclipse.tractusx.edc.token.KeycloakDispatcher; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.extension.RegisterExtension; + +import java.io.IOException; +import java.net.URI; +import java.security.PrivateKey; +import java.time.Clock; +import java.util.HashMap; +import java.util.Map; +import java.util.function.Supplier; + +import static org.eclipse.edc.junit.testfixtures.TestUtils.getFreePort; +import static org.eclipse.tractusx.edc.helpers.IatpHelperFunctions.configureParticipant; +import static org.eclipse.tractusx.edc.helpers.PolicyHelperFunctions.TX_CREDENTIAL_NAMESPACE; +import static org.eclipse.tractusx.edc.helpers.PolicyHelperFunctions.frameworkPolicy; + +@EndToEndTest +public class DimHttpConsumerPullWithProxyInMemoryTest extends AbstractHttpConsumerPullWithProxyTest { + + protected static final URI DIM_URI = URI.create("http://localhost:" + getFreePort()); + protected static final DataspaceIssuer DATASPACE_ISSUER_PARTICIPANT = new DataspaceIssuer(); + protected static final SecureTokenService STS_PARTICIPANT = new SecureTokenService(); + protected static final IatpDimParticipant PLATO_IATP = new IatpDimParticipant(PLATO, STS_PARTICIPANT.stsUri(), DIM_URI); + + @RegisterExtension + protected static final ParticipantRuntime PLATO_RUNTIME = new ParticipantRuntime( + ":edc-tests:runtime:iatp:runtime-memory-iatp-dim-ih", + PLATO.getName(), + PLATO.getBpn(), + PLATO_IATP.iatpConfiguration(SOKRATES) + ); + protected static final IatpDimParticipant SOKRATES_IATP = new IatpDimParticipant(SOKRATES, STS_PARTICIPANT.stsUri(), DIM_URI); + + @RegisterExtension + protected static final ParticipantRuntime SOKRATES_RUNTIME = new ParticipantRuntime( + ":edc-tests:runtime:iatp:runtime-memory-iatp-dim-ih", + SOKRATES.getName(), + SOKRATES.getBpn(), + SOKRATES_IATP.iatpConfiguration(PLATO) + ); + private static MockWebServer oauthServer; + private static MockWebServer dimDispatcher; + + @BeforeAll + static void prepare() throws IOException { + + var tokenGeneration = new JwtGenerationService(); + + var generatorServices = Map.of( + SOKRATES_IATP.didUrl(), tokenServiceFor(tokenGeneration, SOKRATES_IATP), + PLATO_IATP.didUrl(), tokenServiceFor(tokenGeneration, PLATO_IATP)); + + oauthServer = new MockWebServer(); + oauthServer.start(STS_PARTICIPANT.stsUri().getPort()); + oauthServer.setDispatcher(new KeycloakDispatcher(STS_PARTICIPANT.stsUri().getPath() + "/token")); + + dimDispatcher = new MockWebServer(); + dimDispatcher.start(DIM_URI.getPort()); + dimDispatcher.setDispatcher(new DimDispatcher("/iatp", generatorServices)); + + // create the DIDs cache + var dids = new HashMap(); + dids.put(DATASPACE_ISSUER_PARTICIPANT.didUrl(), DATASPACE_ISSUER_PARTICIPANT.didDocument()); + dids.put(SOKRATES_IATP.didUrl(), SOKRATES_IATP.didDocument()); + dids.put(PLATO_IATP.didUrl(), PLATO_IATP.didDocument()); + + configureParticipant(DATASPACE_ISSUER_PARTICIPANT, SOKRATES_IATP, SOKRATES_RUNTIME, dids, null); + configureParticipant(DATASPACE_ISSUER_PARTICIPANT, PLATO_IATP, PLATO_RUNTIME, dids, null); + + } + + @AfterAll + static void unwind() throws IOException { + oauthServer.shutdown(); + dimDispatcher.shutdown(); + } + + private static EmbeddedSecureTokenService tokenServiceFor(TokenGenerationService tokenGenerationService, IatpDimParticipant iatpDimParticipant) { + return new EmbeddedSecureTokenService(tokenGenerationService, privateKeySupplier(iatpDimParticipant), publicIdSupplier(iatpDimParticipant), Clock.systemUTC(), 60 * 60); + } + + private static Supplier privateKeySupplier(IatpDimParticipant participant) { + return () -> participant.getKeyPair().getPrivate(); + } + + private static Supplier publicIdSupplier(IatpDimParticipant participant) { + return participant::verificationId; + } + + @BeforeEach + void setup() throws IOException { + super.setup(); + } + + @Override + protected JsonObject createContractPolicy(String bpn) { + return frameworkPolicy(Map.of(TX_CREDENTIAL_NAMESPACE + "Membership", "active")); + } + +} diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/IatpFrameworkAgreementHttpConsumerPullWithProxyInMemoryTest.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/IatpFrameworkAgreementHttpConsumerPullWithProxyInMemoryTest.java index 4691907cd..aa786c40d 100644 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/IatpFrameworkAgreementHttpConsumerPullWithProxyInMemoryTest.java +++ b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/IatpFrameworkAgreementHttpConsumerPullWithProxyInMemoryTest.java @@ -21,7 +21,6 @@ import jakarta.json.JsonObject; import org.eclipse.edc.junit.annotations.EndToEndTest; -import org.junit.jupiter.api.Disabled; import java.util.Map; @@ -29,8 +28,6 @@ import static org.eclipse.tractusx.edc.helpers.PolicyHelperFunctions.frameworkPolicy; @EndToEndTest -// temporarily disabled waiting for an upstream fix -@Disabled public class IatpFrameworkAgreementHttpConsumerPullWithProxyInMemoryTest extends IatpHttpConsumerPullWithProxyInMemoryTest { @Override diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/IatpHttpConsumerPullWithProxyInMemoryTest.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/IatpHttpConsumerPullWithProxyInMemoryTest.java index 2c6b38a4b..cc8c2e3ec 100644 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/IatpHttpConsumerPullWithProxyInMemoryTest.java +++ b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/IatpHttpConsumerPullWithProxyInMemoryTest.java @@ -21,36 +21,24 @@ import jakarta.json.JsonObject; import org.eclipse.edc.iam.did.spi.document.DidDocument; -import org.eclipse.edc.iam.did.spi.resolution.DidResolverRegistry; -import org.eclipse.edc.identityhub.spi.ParticipantContextService; -import org.eclipse.edc.identityhub.spi.model.VerifiableCredentialResource; -import org.eclipse.edc.identityhub.spi.model.participant.KeyDescriptor; -import org.eclipse.edc.identityhub.spi.model.participant.ParticipantManifest; -import org.eclipse.edc.identityhub.spi.store.CredentialStore; -import org.eclipse.edc.jsonld.spi.JsonLd; import org.eclipse.edc.junit.annotations.EndToEndTest; -import org.eclipse.edc.spi.security.Vault; -import org.eclipse.tractusx.edc.did.DidExampleResolver; import org.eclipse.tractusx.edc.lifecycle.ParticipantRuntime; import org.eclipse.tractusx.edc.lifecycle.tx.iatp.DataspaceIssuer; import org.eclipse.tractusx.edc.lifecycle.tx.iatp.IatpParticipant; import org.eclipse.tractusx.edc.lifecycle.tx.iatp.SecureTokenService; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.extension.RegisterExtension; import java.io.IOException; import java.util.HashMap; -import java.util.List; import java.util.Map; +import static org.eclipse.tractusx.edc.helpers.IatpHelperFunctions.configureParticipant; import static org.eclipse.tractusx.edc.helpers.PolicyHelperFunctions.TX_CREDENTIAL_NAMESPACE; import static org.eclipse.tractusx.edc.helpers.PolicyHelperFunctions.frameworkPolicy; @EndToEndTest -// temporarily disabled waiting for an upstream fix -@Disabled public class IatpHttpConsumerPullWithProxyInMemoryTest extends AbstractHttpConsumerPullWithProxyTest { protected static final DataspaceIssuer DATASPACE_ISSUER_PARTICIPANT = new DataspaceIssuer(); @@ -93,55 +81,11 @@ static void prepare() { dids.put(SOKRATES_IATP.didUrl(), SOKRATES_IATP.didDocument()); dids.put(PLATO_IATP.didUrl(), PLATO_IATP.didDocument()); - configureParticipant(SOKRATES_IATP, SOKRATES_RUNTIME, dids); - configureParticipant(PLATO_IATP, PLATO_RUNTIME, dids); + configureParticipant(DATASPACE_ISSUER_PARTICIPANT, SOKRATES_IATP, SOKRATES_RUNTIME, dids, STS_RUNTIME); + configureParticipant(DATASPACE_ISSUER_PARTICIPANT, PLATO_IATP, PLATO_RUNTIME, dids, STS_RUNTIME); } - private static void configureParticipant(IatpParticipant participant, ParticipantRuntime runtime, Map dids) { - STS_RUNTIME.getContext().getService(Vault.class).storeSecret(participant.verificationId(), participant.privateKey()); - var participantContextService = runtime.getContext().getService(ParticipantContextService.class); - var vault = runtime.getContext().getService(Vault.class); - var didResolverRegistry = runtime.getContext().getService(DidResolverRegistry.class); - var didResolver = new DidExampleResolver(); - dids.forEach(didResolver::addCached); - didResolverRegistry.register(didResolver); - - var key = KeyDescriptor.Builder.newInstance() - .keyId(participant.verificationId()) - .publicKeyPem(participant.publicKey()) - .build(); - - var participantManifest = ParticipantManifest.Builder.newInstance() - .participantId(participant.getBpn()) - .did(participant.didUrl()) - .key(key) - .build(); - - participantContextService.createParticipantContext(participantManifest); - vault.storeSecret(participant.verificationId(), participant.privateKey()); - - storeCredentials(participant, runtime); - } - - private static void storeCredentials(IatpParticipant participant, ParticipantRuntime runtime) { - var credentialStore = runtime.getContext().getService(CredentialStore.class); - var jsonLd = runtime.getContext().getService(JsonLd.class); - issueCredentials(participant, jsonLd).forEach(credentialStore::create); - } - - private static List issueCredentials(IatpParticipant participant, JsonLd jsonLd) { - - if (participant.getBpn().startsWith("PLATO")) { - return List.of( - DATASPACE_ISSUER_PARTICIPANT.issueMembershipCredential(participant, jsonLd)); - } else { - return List.of( - DATASPACE_ISSUER_PARTICIPANT.issueMembershipCredential(participant, jsonLd), - DATASPACE_ISSUER_PARTICIPANT.issueFrameworkCredential(participant, jsonLd, "PcfCredential")); - } - - } @BeforeEach void setup() throws IOException { diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/token/DimDispatcher.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/token/DimDispatcher.java new file mode 100644 index 000000000..b62a52f6b --- /dev/null +++ b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/token/DimDispatcher.java @@ -0,0 +1,117 @@ +/******************************************************************************** + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +package org.eclipse.tractusx.edc.token; + +import okhttp3.mockwebserver.Dispatcher; +import okhttp3.mockwebserver.MockResponse; +import okhttp3.mockwebserver.RecordedRequest; +import org.eclipse.edc.iam.identitytrust.sts.embedded.EmbeddedSecureTokenService; +import org.eclipse.edc.spi.iam.TokenRepresentation; +import org.eclipse.edc.spi.types.TypeManager; +import org.jetbrains.annotations.NotNull; + +import java.util.Collection; +import java.util.Map; +import java.util.Optional; +import java.util.stream.Collectors; + +import static org.eclipse.edc.identitytrust.SelfIssuedTokenConstants.PRESENTATION_ACCESS_TOKEN_CLAIM; +import static org.eclipse.edc.jwt.spi.JwtRegisteredClaimNames.AUDIENCE; +import static org.eclipse.edc.jwt.spi.JwtRegisteredClaimNames.ISSUER; +import static org.eclipse.edc.jwt.spi.JwtRegisteredClaimNames.SUBJECT; + +/** + * Mock service for DIM interaction. Underlying it uses the {@link EmbeddedSecureTokenService} for generating SI tokens + */ +public class DimDispatcher extends Dispatcher { + + private static final TypeManager MAPPER = new TypeManager(); + private final String path; + private final Map secureTokenServices; + + public DimDispatcher(String path, Map secureTokenServices) { + this.path = path; + this.secureTokenServices = secureTokenServices; + } + + public DimDispatcher(Map secureTokenServices) { + this("/", secureTokenServices); + } + + @NotNull + @Override + @SuppressWarnings({ "unchecked" }) + public MockResponse dispatch(@NotNull RecordedRequest recordedRequest) { + if (recordedRequest.getPath().split("\\?")[0].equals(path)) { + + var body = MAPPER.readValue(recordedRequest.getBody().readByteArray(), Map.class); + + var grant = Optional.ofNullable(body.get("grantAccess")) + .map((payload) -> grantAccessHandler((Map) payload)); + + var sign = Optional.ofNullable(body.get("signToken")) + .map((payload) -> signTokenHandler((Map) payload)); + + return grant.or(() -> sign).orElse(new MockResponse().setResponseCode(404)); + } + return new MockResponse().setResponseCode(404); + } + + @SuppressWarnings("unchecked") + private MockResponse grantAccessHandler(Map params) { + var issuer = params.get("consumerDid").toString(); + var audience = params.get("providerDid").toString(); + Collection scopes = (Collection) params.get("credentialTypes"); + var scope = scopes.stream().map("org.eclipse.tractusx.vc.type:%s:read"::formatted).collect(Collectors.joining(" ")); + var claims = Map.of(ISSUER, issuer, SUBJECT, issuer, AUDIENCE, audience); + + var sts = secureTokenServices.get(issuer); + var token = sts.createToken(claims, scope) + .map(TokenRepresentation::getToken) + .orElseThrow(failure -> new RuntimeException(failure.getFailureDetail())); + + return new MockResponse().setBody(MAPPER.writeValueAsString(Map.of("jwt", token))); + } + + private MockResponse signTokenHandler(Map params) { + var subject = params.get("subject").toString(); + var accessToken = params.get("token").toString(); + var audience = params.get("audience").toString(); + var issuer = params.get("issuer").toString(); + + var claims = Map.of( + ISSUER, issuer, + SUBJECT, subject, + AUDIENCE, audience, + PRESENTATION_ACCESS_TOKEN_CLAIM, accessToken); + + var sts = secureTokenServices.get(issuer); + var token = sts.createToken(claims, null) + .map(TokenRepresentation::getToken) + .orElseThrow(failure -> new RuntimeException(failure.getFailureDetail())); + + return new MockResponse().setBody(MAPPER.writeValueAsString(Map.of("jwt", token))); + } + + private MockResponse createTokenResponse() { + return new MockResponse().setBody(MAPPER.writeValueAsString(Map.of("jwt", "token"))); + } + +} diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/token/KeycloakDispatcher.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/token/KeycloakDispatcher.java index 53240d078..43e1c3310 100644 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/token/KeycloakDispatcher.java +++ b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/token/KeycloakDispatcher.java @@ -30,15 +30,20 @@ public class KeycloakDispatcher extends Dispatcher { private static final TypeManager MAPPER = new TypeManager(); - - public KeycloakDispatcher() { + private final String path; + + public KeycloakDispatcher(String path) { + this.path = path; + } + public KeycloakDispatcher() { + this("/"); } @NotNull @Override public MockResponse dispatch(@NotNull RecordedRequest recordedRequest) throws InterruptedException { - if (recordedRequest.getPath().split("\\?")[0].equals("/")) { + if (recordedRequest.getPath().split("\\?")[0].equals(path)) { return createTokenResponse(); } return new MockResponse().setResponseCode(404); diff --git a/edc-tests/runtime/iatp/iatp-extensions/src/main/java/org/eclipse/tractusx/edc/iatp/policy/CredentialPolicyEvaluationExtension.java b/edc-tests/runtime/iatp/iatp-extensions/src/main/java/org/eclipse/tractusx/edc/iatp/policy/CredentialPolicyEvaluationExtension.java index d3cfa820c..28cf6a19b 100644 --- a/edc-tests/runtime/iatp/iatp-extensions/src/main/java/org/eclipse/tractusx/edc/iatp/policy/CredentialPolicyEvaluationExtension.java +++ b/edc-tests/runtime/iatp/iatp-extensions/src/main/java/org/eclipse/tractusx/edc/iatp/policy/CredentialPolicyEvaluationExtension.java @@ -19,71 +19,22 @@ package org.eclipse.tractusx.edc.iatp.policy; -import org.eclipse.edc.policy.engine.spi.AtomicConstraintFunction; -import org.eclipse.edc.policy.engine.spi.PolicyEngine; -import org.eclipse.edc.policy.engine.spi.RuleBindingRegistry; -import org.eclipse.edc.policy.model.Permission; import org.eclipse.edc.runtime.metamodel.annotation.Extension; import org.eclipse.edc.runtime.metamodel.annotation.Inject; import org.eclipse.edc.spi.agent.ParticipantAgentService; import org.eclipse.edc.spi.system.ServiceExtension; import org.eclipse.edc.spi.system.ServiceExtensionContext; -import static org.eclipse.edc.policy.model.OdrlNamespace.ODRL_SCHEMA; -import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.TX_CREDENTIAL_NAMESPACE; - @Extension("TX credential policy evaluation extension") public class CredentialPolicyEvaluationExtension implements ServiceExtension { - - public static final String MEMBERSHIP_CONSTRAINT_KEY = "Membership"; - private static final String CATALOG_SCOPE = "catalog"; - private static final String NEGOTIATION_SCOPE = "contract.negotiation"; - private static final String TRANSFER_PROCESS_SCOPE = "transfer.process"; - - @Inject - private PolicyEngine policyEngine; - - @Inject - private RuleBindingRegistry ruleBindingRegistry; - - + @Inject private ParticipantAgentService participantAgentService; @Override public void initialize(ServiceExtensionContext context) { - var fct = new MembershipCredentialEvaluationFunction(); - - bindPermissionFunction(fct, TRANSFER_PROCESS_SCOPE, MEMBERSHIP_CONSTRAINT_KEY); - bindPermissionFunction(fct, NEGOTIATION_SCOPE, MEMBERSHIP_CONSTRAINT_KEY); - bindPermissionFunction(fct, CATALOG_SCOPE, MEMBERSHIP_CONSTRAINT_KEY); - - registerUseCase("pcf"); - registerUseCase("traceability"); - registerUseCase("sustainability"); - registerUseCase("quality"); - registerUseCase("resiliency"); - participantAgentService.register(new IdentityExtractor()); } - private void bindPermissionFunction(AtomicConstraintFunction function, String scope, String constraintType) { - ruleBindingRegistry.bind("USE", scope); - ruleBindingRegistry.bind(ODRL_SCHEMA + "use", scope); - ruleBindingRegistry.bind(constraintType, scope); - ruleBindingRegistry.bind(TX_CREDENTIAL_NAMESPACE + constraintType, scope); - - policyEngine.registerFunction(scope, Permission.class, constraintType, function); - policyEngine.registerFunction(scope, Permission.class, TX_CREDENTIAL_NAMESPACE + constraintType, function); - } - - private void registerUseCase(String useCaseName) { - var frameworkFunction = new FrameworkCredentialEvaluationFunction(useCaseName); - var usecase = frameworkFunction.key(); - - bindPermissionFunction(frameworkFunction, TRANSFER_PROCESS_SCOPE, usecase); - bindPermissionFunction(frameworkFunction, NEGOTIATION_SCOPE, usecase); - bindPermissionFunction(frameworkFunction, CATALOG_SCOPE, usecase); - } } diff --git a/edc-tests/runtime/iatp/iatp-extensions/src/main/java/org/eclipse/tractusx/edc/iatp/policy/FrameworkCredentialEvaluationFunction.java b/edc-tests/runtime/iatp/iatp-extensions/src/main/java/org/eclipse/tractusx/edc/iatp/policy/FrameworkCredentialEvaluationFunction.java deleted file mode 100644 index ef0e007c1..000000000 --- a/edc-tests/runtime/iatp/iatp-extensions/src/main/java/org/eclipse/tractusx/edc/iatp/policy/FrameworkCredentialEvaluationFunction.java +++ /dev/null @@ -1,74 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.iatp.policy; - -import org.eclipse.edc.policy.engine.spi.PolicyContext; -import org.eclipse.edc.policy.model.Operator; -import org.eclipse.edc.policy.model.Permission; -import org.eclipse.edc.spi.agent.ParticipantAgent; - -public class FrameworkCredentialEvaluationFunction extends BaseCredentialEvaluationFunction { - - public static final String CONTRACT_VERSION = "contractVersion"; - public static final String HOLDER_IDENTIFIER = "holderIdentifier"; - public static final String USE_CASE_TYPE = "useCaseType"; - public static final String CONTRACT_TEMPLATE = "contractTemplate"; - private final String usecase; - private final String useCaseCredential; - - public FrameworkCredentialEvaluationFunction(String usecase) { - this.usecase = usecase; - this.useCaseCredential = "%sCredential".formatted(capitalize(usecase)); - } - - @Override - public boolean evaluate(Operator operator, Object rightOperand, Permission permission, PolicyContext policyContext) { - if (!operator.equals(Operator.EQ)) { - policyContext.reportProblem("Cannot evaluate operator %s, only %s is supported".formatted(operator, Operator.EQ)); - return false; - } - if (!"active".equalsIgnoreCase(rightOperand.toString())) { - policyContext.reportProblem("Use case credentials only support right operand 'active', but found '%s'".formatted(operator.toString())); - return false; - } - var pa = policyContext.getContextData(ParticipantAgent.class); - if (pa == null) { - policyContext.reportProblem("ParticipantAgent not found on PolicyContext"); - return false; - } - - var claims = pa.getClaims(); - - var version = getClaim(String.class, CONTRACT_VERSION, claims); - var holderIdentifier = getClaim(String.class, HOLDER_IDENTIFIER, claims); - var contractTemplate = getClaim(String.class, CONTRACT_TEMPLATE, claims); - var useCaseType = getClaim(String.class, USE_CASE_TYPE, claims); - - return version != null && holderIdentifier != null && contractTemplate != null && useCaseCredential.equals(useCaseType); - } - - public String key() { - return "FrameworkAgreement.%s".formatted(usecase); - } - - private String capitalize(String input) { - return input.substring(0, 1).toUpperCase() + input.substring(1).toLowerCase(); - } -} diff --git a/edc-tests/runtime/iatp/iatp-extensions/src/main/java/org/eclipse/tractusx/edc/iatp/policy/IdentityExtractor.java b/edc-tests/runtime/iatp/iatp-extensions/src/main/java/org/eclipse/tractusx/edc/iatp/policy/IdentityExtractor.java index ca5bdcda0..056cdebaf 100644 --- a/edc-tests/runtime/iatp/iatp-extensions/src/main/java/org/eclipse/tractusx/edc/iatp/policy/IdentityExtractor.java +++ b/edc-tests/runtime/iatp/iatp-extensions/src/main/java/org/eclipse/tractusx/edc/iatp/policy/IdentityExtractor.java @@ -19,25 +19,68 @@ package org.eclipse.tractusx.edc.iatp.policy; +import org.eclipse.edc.identitytrust.model.VerifiableCredential; +import org.eclipse.edc.spi.EdcException; import org.eclipse.edc.spi.agent.ParticipantAgentServiceExtension; import org.eclipse.edc.spi.iam.ClaimToken; +import org.eclipse.edc.spi.result.Result; import org.jetbrains.annotations.NotNull; +import java.util.List; import java.util.Map; +import java.util.Optional; import static org.eclipse.edc.spi.agent.ParticipantAgent.PARTICIPANT_IDENTITY; +// TODO this is just a test identity extractor, the real one can be inspired by this but with final Identity credential public class IdentityExtractor implements ParticipantAgentServiceExtension { + + private static final String VC_CLAIM = "vc"; + private static final String IDENTITY_CREDENTIAL = "MembershipCredential"; + private static final String IDENTITY_PROPERTY = "holderIdentifier"; + @Override public @NotNull Map attributesFor(ClaimToken claimToken) { - return Map.of(PARTICIPANT_IDENTITY, getClaim(String.class, "holderIdentifier", claimToken.getClaims())); - } + var credentials = getCredentialList(claimToken) + .orElseThrow(failure -> new EdcException("Failed to fetch credentials from the claim token: %s".formatted(failure.getFailureDetail()))); - protected T getClaim(Class type, String postfix, Map claims) { - return claims.entrySet().stream().filter(e -> e.getKey().endsWith(postfix)) + return credentials.stream() + .filter(this::isIdentityCredential) .findFirst() + .flatMap(this::getIdentifier) + .map(identity -> Map.of(PARTICIPANT_IDENTITY, identity)) + .orElseThrow(() -> new EdcException("Failed to fetch %s property from %s credential".formatted(IDENTITY_PROPERTY, IDENTITY_CREDENTIAL))); + + + } + + private boolean isIdentityCredential(VerifiableCredential verifiableCredential) { + return verifiableCredential.getTypes().stream().anyMatch(t -> t.endsWith(IDENTITY_CREDENTIAL)); + } + + private Optional getIdentifier(VerifiableCredential verifiableCredential) { + return verifiableCredential.getCredentialSubject().stream() + .flatMap(credentialSubject -> credentialSubject.getClaims().entrySet().stream()) + .filter(entry -> entry.getKey().endsWith(IDENTITY_PROPERTY)) .map(Map.Entry::getValue) - .map(type::cast) - .orElse(null); + .map(String.class::cast) + .findFirst(); + } + + @SuppressWarnings("unchecked") + private Result> getCredentialList(ClaimToken claimToken) { + var vcListClaim = claimToken.getClaims().get(VC_CLAIM); + + if (vcListClaim == null) { + return Result.failure("ClaimToken did not contain a '%s' claim.".formatted(VC_CLAIM)); + } + if (!(vcListClaim instanceof List)) { + return Result.failure("ClaimToken contains a '%s' claim, but the type is incorrect. Expected %s, got %s.".formatted(VC_CLAIM, List.class.getName(), vcListClaim.getClass().getName())); + } + var vcList = (List) vcListClaim; + if (vcList.isEmpty()) { + return Result.failure("ClaimToken contains a '%s' claim but it did not contain any VerifiableCredentials.".formatted(VC_CLAIM)); + } + return Result.success(vcList); } } diff --git a/edc-tests/runtime/iatp/iatp-extensions/src/main/java/org/eclipse/tractusx/edc/iatp/policy/MembershipCredentialEvaluationFunction.java b/edc-tests/runtime/iatp/iatp-extensions/src/main/java/org/eclipse/tractusx/edc/iatp/policy/MembershipCredentialEvaluationFunction.java deleted file mode 100644 index eca1c8315..000000000 --- a/edc-tests/runtime/iatp/iatp-extensions/src/main/java/org/eclipse/tractusx/edc/iatp/policy/MembershipCredentialEvaluationFunction.java +++ /dev/null @@ -1,91 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.iatp.policy; - -import org.eclipse.edc.policy.engine.spi.PolicyContext; -import org.eclipse.edc.policy.model.Operator; -import org.eclipse.edc.policy.model.Permission; -import org.eclipse.edc.spi.agent.ParticipantAgent; - -import java.time.Instant; -import java.util.Map; -import java.util.function.BiFunction; - -public class MembershipCredentialEvaluationFunction extends BaseCredentialEvaluationFunction { - - public static final String START_TIME = "startTime"; - public static final String MEMBER_OF = "memberOf"; - public static final String STATUS = "status"; - public static final String ACTIVE = "Active"; - public static final String CATENA_X = "Catena-X"; - private final Map> claimsCheckers = Map.of( - STATUS, this::validateStatus, - MEMBER_OF, this::validateMemberOf, - START_TIME, this::validateStartTime - ); - - @Override - public boolean evaluate(Operator operator, Object rightOperand, Permission permission, PolicyContext policyContext) { - - if (!operator.equals(Operator.EQ)) { - policyContext.reportProblem("Invalid operator '%s', only accepts '%s'".formatted(operator, Operator.EQ)); - return false; - } - var pa = policyContext.getContextData(ParticipantAgent.class); - if (pa == null) { - policyContext.reportProblem("No ParticipantAgent found on context."); - return false; - } - var claims = pa.getClaims(); - if ("active".equalsIgnoreCase(rightOperand.toString())) { - return claimsCheckers.entrySet().stream() - .reduce(true, (i, checker) -> checker.getValue().apply(policyContext, getClaim(String.class, checker.getKey(), claims)), (first, left) -> first && left); - } - return false; - } - - private boolean validateMemberOf(PolicyContext policyContext, String memberOf) { - return validateField(policyContext, MEMBER_OF, CATENA_X, memberOf); - - } - - private boolean validateStatus(PolicyContext policyContext, String status) { - return validateField(policyContext, STATUS, ACTIVE, status); - } - - private boolean validateField(PolicyContext policyContext, String field, String expectedValue, String currentValue) { - if (expectedValue.equals(currentValue)) { - return true; - } else { - policyContext.reportProblem("Invalid membership %s '%s', only accepts '%s'".formatted(field, currentValue, expectedValue)); - return false; - } - } - - private boolean validateStartTime(PolicyContext policyContext, String since) { - var membershipStartDate = Instant.parse(since); - if (membershipStartDate.isBefore(Instant.now())) { - return true; - } else { - policyContext.reportProblem("Invalid membership start date"); - return false; - } - } -} diff --git a/edc-tests/runtime/iatp/runtime-memory-iatp-dim-ih/README.md b/edc-tests/runtime/iatp/runtime-memory-iatp-dim-ih/README.md new file mode 100644 index 000000000..2f9593a75 --- /dev/null +++ b/edc-tests/runtime/iatp/runtime-memory-iatp-dim-ih/README.md @@ -0,0 +1,3 @@ +# In-Memory Runtime for Testing Purposes + +This module provides a very small, purely in-mem runtime to execute tests against. Not intended for anything other than testing! diff --git a/edc-tests/runtime/iatp/runtime-memory-iatp-dim-ih/build.gradle.kts b/edc-tests/runtime/iatp/runtime-memory-iatp-dim-ih/build.gradle.kts new file mode 100644 index 000000000..d90e9e01d --- /dev/null +++ b/edc-tests/runtime/iatp/runtime-memory-iatp-dim-ih/build.gradle.kts @@ -0,0 +1,69 @@ +/******************************************************************************** + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +plugins { + `java-library` + id("application") +} + +dependencies { + + // use basic (all in-mem) control plane + implementation(project(":edc-controlplane:edc-controlplane-base")) { + exclude(module = "data-encryption") + exclude(module = "ssi-identity-core") + exclude(module = "ssi-miw-credential-client") + exclude(module = "ssi-identity-extractor") + exclude(module = "cx-policy") + } + implementation(project(":core:json-ld-core")) + implementation(project(":edc-extensions:iatp:tx-iatp")) + implementation(project(":edc-extensions:iatp:tx-iatp-sts-dim")) + + implementation(project(":edc-tests:runtime:extensions")) + implementation(project(":edc-tests:runtime:iatp:iatp-extensions")) + + // use basic (all in-mem) data plane + runtimeOnly(project(":edc-dataplane:edc-dataplane-base")) { + exclude("org.eclipse.edc", "api-observability") + } + + implementation(libs.edc.core.controlplane) + implementation(libs.edc.identity.core.trust) + implementation(libs.edc.identity.core.did) + implementation(libs.edc.identity.trust.transform) + implementation(libs.edc.identity.trust.issuers.configuration) + implementation(libs.edc.auth.oauth2.client) + implementation(libs.edc.ih.api) + implementation(libs.edc.ih.credentials) + implementation(libs.edc.ih.keypairs) + implementation(libs.edc.ih.participants) + implementation(libs.edc.ih.did) + + // for the controller + implementation(libs.jakarta.rsApi) +} + +application { + mainClass.set("org.eclipse.edc.boot.system.runtime.BaseRuntime") +} + +edcBuild { + publish.set(false) +} diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index b95140619..861912b41 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -112,7 +112,7 @@ edc-controlplane-callback-dispatcher-event = { module = "org.eclipse.edc:callbac edc-controlplane-callback-dispatcher-http = { module = "org.eclipse.edc:callback-http-dispatcher", version.ref = "edc" } # IATP Modules - +edc-identity-trust-spi = { module = "org.eclipse.edc:identity-trust-spi", version.ref = "edc" } edc-identity-core-trust = { module = "org.eclipse.edc:identity-trust-core", version.ref = "edc" } edc-identity-core-did = { module = "org.eclipse.edc:identity-did-core", version.ref = "edc" } edc-identity-did-web = { module = "org.eclipse.edc:identity-did-web", version.ref = "edc" } @@ -120,12 +120,13 @@ edc-identity-vc-ldp = { module = "org.eclipse.edc:ldp-verifiable-credentials", v edc-identity-vc-jwt = { module = "org.eclipse.edc:jwt-verifiable-credentials", version.ref = "edc" } edc-identity-jws2020 = { module = "org.eclipse.edc:jws2020", version.ref = "edc" } edc-identity-trust-transform = { module = "org.eclipse.edc:identity-trust-transform", version.ref = "edc" } -edc-identity-trust-sts-remote = { module = "org.eclipse.edc:identity-trust-sts-remote-core", version.ref = "edc" } edc-identity-trust-issuers-configuration = { module = "org.eclipse.edc:identity-trust-issuers-configuration", version.ref = "edc" } # IATP for Testing +edc-identity-trust-sts-remote = { module = "org.eclipse.edc:identity-trust-sts-remote-core", version.ref = "edc" } +edc-identity-trust-sts-embedded = { module = "org.eclipse.edc:identity-trust-sts-embedded", version.ref = "edc" } edc-identity-trust-sts-core = { module = "org.eclipse.edc:identity-trust-sts-core", version.ref = "edc" } edc-identity-trust-sts-api = { module = "org.eclipse.edc:identity-trust-sts-api", version.ref = "edc" } edc-identity-trust-sts-client-configuration = { module = "org.eclipse.edc:identity-trust-sts-client-configuration", version.ref = "edc" } diff --git a/settings.gradle.kts b/settings.gradle.kts index 3b2cbcff6..65841a7b9 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -30,6 +30,7 @@ include(":spi:ssi-spi") include(":core:edr-cache-core") include(":core:edr-core") include(":core:json-ld-core") +include(":core:core-utils") include(":edc-extensions:bpn-validation") @@ -52,6 +53,7 @@ include("edc-extensions:ssi:ssi-identity-core") include("edc-extensions:ssi:ssi-miw-credential-client") include(":edc-extensions:ssi:ssi-identity-extractor") include(":edc-extensions:iatp:tx-iatp") +include(":edc-extensions:iatp:tx-iatp-sts-dim") // test modules include(":edc-tests:e2e-tests") @@ -63,6 +65,7 @@ include(":edc-tests:runtime:runtime-memory-ssi") include(":edc-tests:runtime:runtime-postgresql") include(":edc-tests:runtime:runtime-postgresql-hashicorp") include(":edc-tests:runtime:iatp:runtime-memory-iatp-ih") +include(":edc-tests:runtime:iatp:runtime-memory-iatp-dim-ih") include(":edc-tests:runtime:iatp:runtime-memory-sts") include(":edc-tests:runtime:iatp:iatp-extensions") include(":edc-tests:edc-dataplane:edc-dataplane-proxy-e2e") From 66e21920e89e059bc664203f3cac078314eaef52 Mon Sep 17 00:00:00 2001 From: Enrico Risa Date: Mon, 19 Feb 2024 12:05:49 +0100 Subject: [PATCH 016/100] chore: fix after EDC snapshot update (#1070) * chore: fix after EDC snapshot update * chore: fix after EDC snapshot update * chore: fixed EDC version to 0.5.2-20240219-SNAPSHOT --- DEPENDENCIES | 296 +++++++++--------- .../edc/helpers/IatpHelperFunctions.java | 1 + .../edc/helpers/PolicyHelperFunctions.java | 3 + .../edc/lifecycle/tx/ParticipantEdrApi.java | 4 +- .../edc/lifecycle/tx/TxParticipant.java | 15 +- gradle/libs.versions.toml | 2 +- 6 files changed, 170 insertions(+), 151 deletions(-) diff --git a/DEPENDENCIES b/DEPENDENCIES index 3f657bc59..caa417584 100644 --- a/DEPENDENCIES +++ b/DEPENDENCIES @@ -248,154 +248,154 @@ maven/mavencentral/org.codehaus.plexus/plexus-container-default/2.1.0, Apache-2. maven/mavencentral/org.codehaus.plexus/plexus-utils/3.1.1, , approved, CQ16492 maven/mavencentral/org.codehaus.plexus/plexus-utils/3.3.0, , approved, CQ21066 maven/mavencentral/org.codehaus.woodstox/stax2-api/4.2.1, BSD-2-Clause, approved, #2670 -maven/mavencentral/org.eclipse.edc/api-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/api-observability/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/asset-api/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/asset-index-sql/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/asset-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/auth-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/auth-tokenbased/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/autodoc-processor/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/aws-s3-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/aws-s3-test/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/azure-blob-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/azure-test/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/boot/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/callback-event-dispatcher/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/callback-http-dispatcher/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/catalog-api/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/catalog-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/catalog-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/configuration-filesystem/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/connector-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/contract-agreement-api/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/contract-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/contract-definition-api/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/contract-definition-store-sql/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/contract-negotiation-api/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/contract-negotiation-store-sql/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/contract-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/control-api-configuration/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/control-plane-aggregate-services/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/control-plane-api-client-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/control-plane-api-client/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/control-plane-api/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/control-plane-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/control-plane-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/core-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/crypto-common/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-address-http-data-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-plane-aws-s3/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-plane-azure-storage/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-plane-client/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-plane-control-api/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-plane-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-plane-http-oauth2-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-plane-http-oauth2/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-plane-http-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-plane-http/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-plane-public-api/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-plane-selector-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-plane-selector-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-plane-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-plane-util/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-api-configuration/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-catalog-api/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-catalog-http-dispatcher/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-catalog-transform/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-catalog/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-http-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-http-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-negotiation-api/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-negotiation-http-dispatcher/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-negotiation-transform/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-negotiation/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-transfer-process-api/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-transfer-process-http-dispatcher/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-transfer-process-transform/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-transfer-process/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/http-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/http/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/iam-mock/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-did-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-did-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-hub-api/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-hub-credentials/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-hub-did-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-hub-did/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-hub-keypairs/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-hub-participants/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-hub-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-hub-store-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-trust-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-trust-issuers-configuration/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-trust-service/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-trust-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-trust-sts-api/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-trust-sts-client-configuration/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-trust-sts-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-trust-sts-embedded/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-trust-sts-remote-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-trust-sts-remote/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-trust-sts-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-trust-transform/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/jersey-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/jersey-micrometer/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/jersey-providers/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/jetty-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/jetty-micrometer/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/json-ld-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/json-ld/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/junit/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/jws2020/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/jwt-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/jwt-verifiable-credentials/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/ldp-verifiable-credentials/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/management-api-configuration/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/management-api-test-fixtures/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/management-api/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/micrometer-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/oauth2-client/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/oauth2-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/policy-definition-api/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/policy-definition-store-sql/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/policy-engine-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/policy-engine/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/policy-evaluator/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/policy-model/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/policy-monitor-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/policy-monitor-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/policy-monitor-store-sql/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/policy-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/runtime-metamodel/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/security/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/sql-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/sql-lease/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/sql-pool-apache-commons/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/state-machine/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/token-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/token-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/transaction-datasource-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/transaction-local/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/transaction-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/transfer-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/transfer-data-plane-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/transfer-data-plane/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/transfer-process-api/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/transfer-process-store-sql/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/transfer-pull-http-dynamic-receiver/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/transfer-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/transform-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/transform-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/util/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/validator-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/validator-data-address-http-data/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/validator-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/vault-azure/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/vault-hashicorp/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/web-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/api-core/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/api-observability/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/asset-api/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/asset-index-sql/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/asset-spi/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/auth-spi/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/auth-tokenbased/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/autodoc-processor/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/aws-s3-core/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/aws-s3-test/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/azure-blob-core/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/azure-test/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/boot/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/callback-event-dispatcher/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/callback-http-dispatcher/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/catalog-api/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/catalog-core/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/catalog-spi/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/configuration-filesystem/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/connector-core/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/contract-agreement-api/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/contract-core/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/contract-definition-api/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/contract-definition-store-sql/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/contract-negotiation-api/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/contract-negotiation-store-sql/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/contract-spi/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/control-api-configuration/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/control-plane-aggregate-services/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/control-plane-api-client-spi/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/control-plane-api-client/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/control-plane-api/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/control-plane-core/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/control-plane-spi/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/core-spi/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/crypto-common/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-address-http-data-spi/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-aws-s3/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-azure-storage/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-client/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-control-api/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-core/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-http-oauth2-core/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-http-oauth2/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-http-spi/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-http/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-public-api/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-selector-core/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-selector-spi/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-spi/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-util/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-api-configuration/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-catalog-api/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-catalog-http-dispatcher/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-catalog-transform/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-catalog/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-http-core/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-http-spi/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-negotiation-api/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-negotiation-http-dispatcher/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-negotiation-transform/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-negotiation/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-spi/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-transfer-process-api/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-transfer-process-http-dispatcher/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-transfer-process-transform/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-transfer-process/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/http-spi/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/http/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/iam-mock/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-did-core/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-did-spi/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-hub-api/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-hub-credentials/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-hub-did-spi/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-hub-did/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-hub-keypairs/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-hub-participants/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-hub-spi/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-hub-store-spi/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-trust-core/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-trust-issuers-configuration/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-trust-service/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-trust-spi/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-trust-sts-api/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-trust-sts-client-configuration/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-trust-sts-core/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-trust-sts-embedded/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-trust-sts-remote-core/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-trust-sts-remote/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-trust-sts-spi/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-trust-transform/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/jersey-core/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/jersey-micrometer/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/jersey-providers/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/jetty-core/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/jetty-micrometer/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/json-ld-spi/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/json-ld/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/junit/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/jws2020/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/jwt-spi/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/jwt-verifiable-credentials/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/ldp-verifiable-credentials/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/management-api-configuration/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/management-api-test-fixtures/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/management-api/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/micrometer-core/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/oauth2-client/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/oauth2-spi/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/policy-definition-api/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/policy-definition-store-sql/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/policy-engine-spi/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/policy-engine/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/policy-evaluator/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/policy-model/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/policy-monitor-core/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/policy-monitor-spi/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/policy-monitor-store-sql/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/policy-spi/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/runtime-metamodel/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/security/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/sql-core/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/sql-lease/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/sql-pool-apache-commons/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/state-machine/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/token-core/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/token-spi/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/transaction-datasource-spi/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/transaction-local/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/transaction-spi/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/transfer-core/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/transfer-data-plane-spi/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/transfer-data-plane/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/transfer-process-api/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/transfer-process-store-sql/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/transfer-pull-http-dynamic-receiver/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/transfer-spi/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/transform-core/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/transform-spi/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/util/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/validator-core/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/validator-data-address-http-data/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/validator-spi/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/vault-azure/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/vault-hashicorp/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/web-spi/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.jetty.toolchain/jetty-jakarta-servlet-api/5.0.2, EPL-2.0 OR Apache-2.0, approved, rt.jetty maven/mavencentral/org.eclipse.jetty.toolchain/jetty-jakarta-websocket-api/2.0.0, EPL-2.0 OR Apache-2.0, approved, rt.jetty maven/mavencentral/org.eclipse.jetty.websocket/websocket-core-client/11.0.20, EPL-2.0 OR Apache-2.0, approved, rt.jetty diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/helpers/IatpHelperFunctions.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/helpers/IatpHelperFunctions.java index 030360c39..81e3cc461 100644 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/helpers/IatpHelperFunctions.java +++ b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/helpers/IatpHelperFunctions.java @@ -145,6 +145,7 @@ public static void configureParticipant(DataspaceIssuer issuer, IatpParticipant var key = KeyDescriptor.Builder.newInstance() .keyId(participant.keyId()) .publicKeyPem(participant.publicKey()) + .privateKeyAlias(participant.keyId()) .build(); var participantManifest = ParticipantManifest.Builder.newInstance() diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/helpers/PolicyHelperFunctions.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/helpers/PolicyHelperFunctions.java index 5a16efe0b..fbff919f0 100644 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/helpers/PolicyHelperFunctions.java +++ b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/helpers/PolicyHelperFunctions.java @@ -77,6 +77,7 @@ private static JsonObject bpnGroupPolicy(String operator, String... allowedGroup return Json.createObjectBuilder() .add(CONTEXT, ODRL_JSONLD) + .add(TYPE, "Set") .add("permission", permission) .build(); } @@ -128,6 +129,7 @@ public static JsonObjectBuilder policyDefinitionBuilder(JsonObject policy) { public static JsonObject bnpPolicy(String... bnps) { return Json.createObjectBuilder() .add(CONTEXT, ODRL_JSONLD) + .add(TYPE, "Set") .add("permission", Json.createArrayBuilder() .add(permission(bnps))) .build(); @@ -151,6 +153,7 @@ private static JsonObject permission(String... bpns) { public static JsonObject frameworkPolicy(Map permissions) { return Json.createObjectBuilder() .add(CONTEXT, ODRL_JSONLD) + .add(TYPE, "Set") .add("permission", Json.createArrayBuilder() .add(frameworkPermission(permissions))) .build(); diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/tx/ParticipantEdrApi.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/tx/ParticipantEdrApi.java index 18f55c0d3..473ada2f1 100644 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/tx/ParticipantEdrApi.java +++ b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/tx/ParticipantEdrApi.java @@ -31,8 +31,10 @@ import static io.restassured.RestAssured.given; import static io.restassured.http.ContentType.JSON; +import static jakarta.json.Json.createObjectBuilder; import static org.assertj.core.api.Assertions.assertThat; import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.ID; +import static org.eclipse.edc.jsonld.spi.PropertyAndTypeNames.ODRL_TARGET_ATTRIBUTE; import static org.eclipse.tractusx.edc.helpers.CatalogHelperFunctions.getDatasetContractId; import static org.eclipse.tractusx.edc.helpers.CatalogHelperFunctions.getDatasetFirstPolicy; import static org.eclipse.tractusx.edc.helpers.EdrNegotiationHelperFunctions.createEdrNegotiationRequest; @@ -111,7 +113,7 @@ public String negotiateEdr(TxParticipant other, String assetId, JsonArray callba var dataset = participant.getDatasetForAsset(other, assetId); assertThat(dataset).withFailMessage("Catalog received from " + other.getName() + " was empty!").isNotEmpty(); - var policy = getDatasetFirstPolicy(dataset); + var policy = createObjectBuilder(getDatasetFirstPolicy(dataset)).add(ODRL_TARGET_ATTRIBUTE, createObjectBuilder().add(ID, dataset.get(ID))).build(); var contractId = getDatasetContractId(dataset); var requestBody = createEdrNegotiationRequest(other.getProtocolEndpoint().getUrl().toString(), other.getBpn(), contractId.toString(), contractId.assetIdPart(), policy, callbacks); diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/tx/TxParticipant.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/tx/TxParticipant.java index 5072d5079..db3c4dc5d 100644 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/tx/TxParticipant.java +++ b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/tx/TxParticipant.java @@ -31,7 +31,10 @@ import java.util.Map; import static io.restassured.http.ContentType.JSON; +import static jakarta.json.Json.createObjectBuilder; import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.ID; +import static org.eclipse.edc.jsonld.spi.PropertyAndTypeNames.ODRL_POLICY_ATTRIBUTE; +import static org.eclipse.edc.jsonld.spi.PropertyAndTypeNames.ODRL_TARGET_ATTRIBUTE; import static org.eclipse.edc.junit.testfixtures.TestUtils.getFreePort; import static org.eclipse.tractusx.edc.helpers.PolicyHelperFunctions.TX_NAMESPACE; import static org.eclipse.tractusx.edc.tests.TestCommon.ASYNC_TIMEOUT; @@ -66,7 +69,7 @@ public void createAsset(String id) { * Stores BPN groups */ public void storeBusinessPartner(String bpn, String... groups) { - var body = Json.createObjectBuilder() + var body = createObjectBuilder() .add(ID, bpn) .add(TX_NAMESPACE + "groups", Json.createArrayBuilder(Arrays.asList(groups))) .build(); @@ -131,6 +134,16 @@ public String getContractNegotiationError(String negotiationId) { return getContractNegotiationField(negotiationId, "errorDetail"); } + // TODO: temporary override due https://github.com/eclipse-edc/Connector/pull/3868 + // remove once fixed in EDC upstream + @Override + public String initContractNegotiation(Participant provider, String assetId) { + var dataset = getDatasetForAsset(provider, assetId); + var policy = dataset.getJsonArray(ODRL_POLICY_ATTRIBUTE).get(0).asJsonObject(); + var policyWithTarget = createObjectBuilder(policy).add(ODRL_TARGET_ATTRIBUTE, createObjectBuilder().add(ID, dataset.get(ID))).build(); + return super.initContractNegotiation(provider, policyWithTarget); + } + /** * Returns the base configuration */ diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 861912b41..edbdfdc82 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -2,7 +2,7 @@ format.version = "1.1" [versions] -edc = "0.5.2-SNAPSHOT" +edc = "0.5.2-20240219-SNAPSHOT" apache-sshd = "2.12.0" assertj = "3.25.3" awaitility = "4.2.0" From edbed255eb82e919da5a27710990f96dd7d4d24b Mon Sep 17 00:00:00 2001 From: Paul Latzelsperger <43503240+paullatzelsperger@users.noreply.github.com> Date: Mon, 19 Feb 2024 12:38:13 +0100 Subject: [PATCH 017/100] feat: implement Membership constraint fct (#1069) * implement membership credential function * renamed base class * javadoc --- ...tDynamicCredentialConstraintFunction.java} | 16 ++- ...smantlerCredentialConstraintFunction.java} | 15 ++- ...greementCredentialConstraintFunction.java} | 17 ++- ...embershipCredentialConstraintFunction.java | 67 +++++++++++ .../edc/policy/cx/CredentialFunctions.java | 13 ++ .../DismantlerConstraintFunctionTest.java | 2 +- ...meworkAgreementConstraintFunctionTest.java | 2 +- .../MembershipConstraintFunctionTest.java | 112 ++++++++++++++++++ 8 files changed, 219 insertions(+), 25 deletions(-) rename edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/common/{AbstractDynamicConstraintFunction.java => AbstractDynamicCredentialConstraintFunction.java} (85%) rename edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/dismantler/{DismantlerConstraintFunction.java => DismantlerCredentialConstraintFunction.java} (93%) rename edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/framework/{FrameworkAgreementConstraintFunction.java => FrameworkAgreementCredentialConstraintFunction.java} (93%) create mode 100644 edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/membership/MembershipCredentialConstraintFunction.java create mode 100644 edc-extensions/cx-policy/src/test/java/org/eclipse/tractusx/edc/policy/cx/membership/MembershipConstraintFunctionTest.java diff --git a/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/common/AbstractDynamicConstraintFunction.java b/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/common/AbstractDynamicCredentialConstraintFunction.java similarity index 85% rename from edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/common/AbstractDynamicConstraintFunction.java rename to edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/common/AbstractDynamicCredentialConstraintFunction.java index 9ffe3bbb5..164744403 100644 --- a/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/common/AbstractDynamicConstraintFunction.java +++ b/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/common/AbstractDynamicCredentialConstraintFunction.java @@ -27,7 +27,6 @@ import org.eclipse.edc.spi.agent.ParticipantAgent; import org.eclipse.edc.spi.result.Result; -import java.util.Arrays; import java.util.Collection; import java.util.List; @@ -35,16 +34,12 @@ * This is a base class for dynamically bound Tractus-X constraint evaluation functions that implements some basic common functionality and defines some * common constants */ -public abstract class AbstractDynamicConstraintFunction implements DynamicAtomicConstraintFunction { +public abstract class AbstractDynamicCredentialConstraintFunction implements DynamicAtomicConstraintFunction { public static final String VC_CLAIM = "vc"; public static final String ACTIVE = "active"; public static final String CREDENTIAL_LITERAL = "Credential"; protected static final Collection EQUALITY_OPERATORS = List.of(Operator.EQ, Operator.NEQ); - protected boolean checkOperator(Operator actual, PolicyContext context, Operator... expectedOperators) { - return checkOperator(actual, context, Arrays.asList(expectedOperators)); - } - protected boolean checkOperator(Operator actual, PolicyContext context, Collection expectedOperators) { if (!expectedOperators.contains(actual)) { context.reportProblem("Invalid operator: this constraint only allows the following operators: %s, but received '%s'.".formatted(EQUALITY_OPERATORS, actual)); @@ -53,6 +48,15 @@ protected boolean checkOperator(Operator actual, PolicyContext context, Collecti return true; } + protected Result extractParticipantAgent(PolicyContext context) { + // make sure the ParticipantAgent is there + var participantAgent = context.getContextData(ParticipantAgent.class); + if (participantAgent == null) { + return Result.failure("Required PolicyContext data not found: " + ParticipantAgent.class.getName()); + } + return Result.success(participantAgent); + } + /** * Extracts a {@link List} of {@link VerifiableCredential} objects from the {@link ParticipantAgent}. Credentials must be * stored in the agent's claims map using the "vc" key. diff --git a/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/dismantler/DismantlerConstraintFunction.java b/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/dismantler/DismantlerCredentialConstraintFunction.java similarity index 93% rename from edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/dismantler/DismantlerConstraintFunction.java rename to edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/dismantler/DismantlerCredentialConstraintFunction.java index 7013a4cc7..9991309f3 100644 --- a/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/dismantler/DismantlerConstraintFunction.java +++ b/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/dismantler/DismantlerCredentialConstraintFunction.java @@ -23,8 +23,7 @@ import org.eclipse.edc.policy.engine.spi.PolicyContext; import org.eclipse.edc.policy.model.Operator; import org.eclipse.edc.policy.model.Permission; -import org.eclipse.edc.spi.agent.ParticipantAgent; -import org.eclipse.tractusx.edc.policy.cx.common.AbstractDynamicConstraintFunction; +import org.eclipse.tractusx.edc.policy.cx.common.AbstractDynamicCredentialConstraintFunction; import org.eclipse.tractusx.edc.policy.cx.common.CredentialTypePredicate; import org.jetbrains.annotations.NotNull; @@ -48,7 +47,7 @@ *
  • allowedBrands: whether an existing DismantlerCredential permits the vehicle brands required by the constraint
  • * */ -public class DismantlerConstraintFunction extends AbstractDynamicConstraintFunction { +public class DismantlerCredentialConstraintFunction extends AbstractDynamicCredentialConstraintFunction { public static final String ALLOWED_VEHICLE_BRANDS = CX_NS_1_0 + "allowedVehicleBrands"; private static final String DISMANTLER_LITERAL = "Dismantler"; @@ -59,14 +58,14 @@ public boolean evaluate(Object leftOperand, Operator operator, Object rightOpera Predicate predicate = c -> false; // make sure the ParticipantAgent is there - var participantAgent = context.getContextData(ParticipantAgent.class); - if (participantAgent == null) { - context.reportProblem("Required PolicyContext data not found: " + ParticipantAgent.class.getName()); + var participantAgent = extractParticipantAgent(context); + if (participantAgent.failed()) { + context.reportProblem(participantAgent.getFailureDetail()); return false; } // check if the participant agent contains the correct data - var vcListResult = getCredentialList(participantAgent); + var vcListResult = getCredentialList(participantAgent.getContent()); if (vcListResult.failed()) { // couldn't extract credential list from agent context.reportProblem(vcListResult.getFailureDetail()); return false; @@ -135,7 +134,7 @@ private Predicate getCredentialPredicate(String credential } /** - * Checks whether {@code operator} is valid in the context of {@code rightOperand}. In practice, this means that if {@code rightOperand} is a String, it checks for {@link AbstractDynamicConstraintFunction#EQUALITY_OPERATORS}, + * Checks whether {@code operator} is valid in the context of {@code rightOperand}. In practice, this means that if {@code rightOperand} is a String, it checks for {@link AbstractDynamicCredentialConstraintFunction#EQUALITY_OPERATORS}, * and if its list type, it checks for {@code List.of(EQ, NEQ, IN, IS_ANY_OF, IS_NONE_OF)} */ private boolean hasInvalidOperand(Operator operator, Object rightOperand, PolicyContext context) { diff --git a/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/framework/FrameworkAgreementConstraintFunction.java b/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/framework/FrameworkAgreementCredentialConstraintFunction.java similarity index 93% rename from edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/framework/FrameworkAgreementConstraintFunction.java rename to edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/framework/FrameworkAgreementCredentialConstraintFunction.java index f005add2f..3ef30ee30 100644 --- a/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/framework/FrameworkAgreementConstraintFunction.java +++ b/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/framework/FrameworkAgreementCredentialConstraintFunction.java @@ -25,7 +25,7 @@ import org.eclipse.edc.policy.model.Permission; import org.eclipse.edc.spi.agent.ParticipantAgent; import org.eclipse.edc.spi.result.Result; -import org.eclipse.tractusx.edc.policy.cx.common.AbstractDynamicConstraintFunction; +import org.eclipse.tractusx.edc.policy.cx.common.AbstractDynamicCredentialConstraintFunction; import org.eclipse.tractusx.edc.policy.cx.common.CredentialTypePredicate; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -52,11 +52,11 @@ * policy is considered not fulfilled. Note that if the {@code version} is specified, it must be satisfied by the same * credential that satisfies the {@code subtype} requirement. */ -public class FrameworkAgreementConstraintFunction extends AbstractDynamicConstraintFunction { +public class FrameworkAgreementCredentialConstraintFunction extends AbstractDynamicCredentialConstraintFunction { public static final String CONTRACT_VERSION_PROPERTY = CX_NS_1_0 + "contractVersion"; private static final String FRAMEWORK_AGREEMENT_LITERAL = "FrameworkAgreement"; - public FrameworkAgreementConstraintFunction() { + public FrameworkAgreementCredentialConstraintFunction() { } /** @@ -83,10 +83,9 @@ public boolean evaluate(Object leftValue, Operator operator, Object rightValue, return false; } - // make sure the ParticipantAgent is there - var participantAgent = context.getContextData(ParticipantAgent.class); - if (participantAgent == null) { - context.reportProblem("Required PolicyContext data not found: " + ParticipantAgent.class.getName()); + var participantAgent = extractParticipantAgent(context); + if (participantAgent.failed()) { + context.reportProblem(participantAgent.getFailureDetail()); return false; } @@ -109,7 +108,7 @@ public boolean evaluate(Object leftValue, Operator operator, Object rightValue, return false; } - var vcListResult = getCredentialList(participantAgent); + var vcListResult = getCredentialList(participantAgent.getContent()); if (vcListResult.failed()) { // couldn't extract credential list from agent context.reportProblem(vcListResult.getFailureDetail()); return false; @@ -126,7 +125,7 @@ public boolean evaluate(Object leftValue, Operator operator, Object rightValue, } /** - * Returns {@code true} if the left-operand starts with {@link FrameworkAgreementConstraintFunction#FRAMEWORK_AGREEMENT_LITERAL}, {@code false} otherwise. + * Returns {@code true} if the left-operand starts with {@link FrameworkAgreementCredentialConstraintFunction#FRAMEWORK_AGREEMENT_LITERAL}, {@code false} otherwise. */ @Override public boolean canHandle(Object leftValue) { diff --git a/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/membership/MembershipCredentialConstraintFunction.java b/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/membership/MembershipCredentialConstraintFunction.java new file mode 100644 index 000000000..2866eb49c --- /dev/null +++ b/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/membership/MembershipCredentialConstraintFunction.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.eclipse.tractusx.edc.policy.cx.membership; + +import org.eclipse.edc.policy.engine.spi.PolicyContext; +import org.eclipse.edc.policy.model.Operator; +import org.eclipse.edc.policy.model.Permission; +import org.eclipse.edc.spi.agent.ParticipantAgent; +import org.eclipse.tractusx.edc.policy.cx.common.AbstractDynamicCredentialConstraintFunction; +import org.eclipse.tractusx.edc.policy.cx.common.CredentialTypePredicate; + +/** + * This constraint function checks that a MembershipCredential is present in a list of {@link org.eclipse.edc.identitytrust.model.VerifiableCredential} + * objects extracted from a {@link ParticipantAgent} which is expected to be present on the {@link PolicyContext}. + */ +public class MembershipCredentialConstraintFunction extends AbstractDynamicCredentialConstraintFunction { + private static final String MEMBERSHIP_LITERAL = "Membership"; + + @Override + public boolean evaluate(Object leftOperand, Operator operator, Object rightOperand, Permission permission, PolicyContext context) { + if (!ACTIVE.equals(rightOperand)) { + context.reportProblem("Right-operand must be equal to '%s', but was '%s'".formatted(ACTIVE, rightOperand)); + return false; + } + if (!MEMBERSHIP_LITERAL.equalsIgnoreCase(leftOperand.toString())) { + context.reportProblem("Invalid left-operand: must be 'Membership', but was '%s'".formatted(leftOperand)); + return false; + } + // make sure the ParticipantAgent is there + var participantAgent = context.getContextData(ParticipantAgent.class); + if (participantAgent == null) { + context.reportProblem("Required PolicyContext data not found: " + ParticipantAgent.class.getName()); + return false; + } + + var credentialResult = getCredentialList(participantAgent); + if (credentialResult.failed()) { + context.reportProblem(credentialResult.getFailureDetail()); + return false; + } + return credentialResult.getContent() + .stream() + .anyMatch(new CredentialTypePredicate(MEMBERSHIP_LITERAL + CREDENTIAL_LITERAL)); + } + + @Override + public boolean canHandle(Object leftOperand) { + return leftOperand instanceof String && MEMBERSHIP_LITERAL.equalsIgnoreCase(leftOperand.toString()); + } +} diff --git a/edc-extensions/cx-policy/src/test/java/org/eclipse/tractusx/edc/policy/cx/CredentialFunctions.java b/edc-extensions/cx-policy/src/test/java/org/eclipse/tractusx/edc/policy/cx/CredentialFunctions.java index 1d60aa3a1..48cb54a09 100644 --- a/edc-extensions/cx-policy/src/test/java/org/eclipse/tractusx/edc/policy/cx/CredentialFunctions.java +++ b/edc-extensions/cx-policy/src/test/java/org/eclipse/tractusx/edc/policy/cx/CredentialFunctions.java @@ -72,4 +72,17 @@ public static VerifiableCredential.Builder createDismantlerCredential(Collection .build()); } + public static VerifiableCredential.Builder createMembershipCredential() { + return VerifiableCredential.Builder.newInstance() + .types(List.of("VerifiableCredential", "MembershipCredential")) + .id(UUID.randomUUID().toString()) + .issuer(new Issuer(UUID.randomUUID().toString(), Map.of("prop1", "val1"))) + .expirationDate(Instant.now().plus(365, ChronoUnit.DAYS)) + .issuanceDate(Instant.now()) + .credentialSubject(CredentialSubject.Builder.newInstance() + .id("subject-id") + .claim("https://w3id.org/catenax/credentials/v1.0.0/holderIdentifier", "did:web:holder") + .build()); + } + } diff --git a/edc-extensions/cx-policy/src/test/java/org/eclipse/tractusx/edc/policy/cx/dismantler/DismantlerConstraintFunctionTest.java b/edc-extensions/cx-policy/src/test/java/org/eclipse/tractusx/edc/policy/cx/dismantler/DismantlerConstraintFunctionTest.java index 8462b40b8..a6dbbf2bd 100644 --- a/edc-extensions/cx-policy/src/test/java/org/eclipse/tractusx/edc/policy/cx/dismantler/DismantlerConstraintFunctionTest.java +++ b/edc-extensions/cx-policy/src/test/java/org/eclipse/tractusx/edc/policy/cx/dismantler/DismantlerConstraintFunctionTest.java @@ -47,7 +47,7 @@ class DismantlerConstraintFunctionTest { - private final DismantlerConstraintFunction function = new DismantlerConstraintFunction(); + private final DismantlerCredentialConstraintFunction function = new DismantlerCredentialConstraintFunction(); private final PolicyContext context = mock(); private ParticipantAgent participantAgent; diff --git a/edc-extensions/cx-policy/src/test/java/org/eclipse/tractusx/edc/policy/cx/framework/FrameworkAgreementConstraintFunctionTest.java b/edc-extensions/cx-policy/src/test/java/org/eclipse/tractusx/edc/policy/cx/framework/FrameworkAgreementConstraintFunctionTest.java index bfcd2513d..55b0a0789 100644 --- a/edc-extensions/cx-policy/src/test/java/org/eclipse/tractusx/edc/policy/cx/framework/FrameworkAgreementConstraintFunctionTest.java +++ b/edc-extensions/cx-policy/src/test/java/org/eclipse/tractusx/edc/policy/cx/framework/FrameworkAgreementConstraintFunctionTest.java @@ -43,7 +43,7 @@ import static org.mockito.Mockito.when; class FrameworkAgreementConstraintFunctionTest { - private final FrameworkAgreementConstraintFunction function = new FrameworkAgreementConstraintFunction(); + private final FrameworkAgreementCredentialConstraintFunction function = new FrameworkAgreementCredentialConstraintFunction(); private final PolicyContext context = mock(); private Permission permission; private ParticipantAgent participantAgent; diff --git a/edc-extensions/cx-policy/src/test/java/org/eclipse/tractusx/edc/policy/cx/membership/MembershipConstraintFunctionTest.java b/edc-extensions/cx-policy/src/test/java/org/eclipse/tractusx/edc/policy/cx/membership/MembershipConstraintFunctionTest.java new file mode 100644 index 000000000..e327f9b6b --- /dev/null +++ b/edc-extensions/cx-policy/src/test/java/org/eclipse/tractusx/edc/policy/cx/membership/MembershipConstraintFunctionTest.java @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.eclipse.tractusx.edc.policy.cx.membership; + +import org.eclipse.edc.policy.engine.spi.PolicyContext; +import org.eclipse.edc.policy.model.Operator; +import org.eclipse.edc.spi.agent.ParticipantAgent; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.util.List; +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.eclipse.tractusx.edc.policy.cx.CredentialFunctions.createMembershipCredential; +import static org.eclipse.tractusx.edc.policy.cx.CredentialFunctions.createPcfCredential; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +class MembershipConstraintFunctionTest { + + private final MembershipCredentialConstraintFunction function = new MembershipCredentialConstraintFunction(); + private final PolicyContext context = mock(); + private ParticipantAgent participantAgent; + + @BeforeEach + void setup() { + participantAgent = mock(ParticipantAgent.class); + when(context.getContextData(eq(ParticipantAgent.class))) + .thenReturn(participantAgent); + } + + @Test + void evaluate_leftOperandInvalid() { + when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createMembershipCredential().build()))); + assertThat(function.evaluate("foobar", Operator.EQ, "active", null, context)).isFalse(); + verify(context).reportProblem(eq("Invalid left-operand: must be 'Membership', but was 'foobar'")); + } + + @Test + void evaluate_noParticipantAgentOnContext() { + when(context.getContextData(eq(ParticipantAgent.class))).thenReturn(null); + assertThat(function.evaluate("Membership", Operator.EQ, "active", null, context)).isFalse(); + verify(context).reportProblem("Required PolicyContext data not found: org.eclipse.edc.spi.agent.ParticipantAgent"); + } + + @Test + void evaluate_noVcClaimOnParticipantAgent() { + assertThat(function.evaluate("Membership", Operator.EQ, "active", null, context)).isFalse(); + verify(context).reportProblem(eq("ParticipantAgent did not contain a 'vc' claim.")); + } + + @Test + void evaluate_vcClaimEmpty() { + when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of())); + assertThat(function.evaluate("Membership", Operator.EQ, "active", null, context)).isFalse(); + verify(context).reportProblem(eq("ParticipantAgent contains a 'vc' claim but it did not contain any VerifiableCredentials.")); + } + + @Test + void evaluate_vcClaimNotList() { + when(participantAgent.getClaims()).thenReturn(Map.of("vc", new Object())); + assertThat(function.evaluate("Membership", Operator.EQ, "active", null, context)).isFalse(); + verify(context).reportProblem(eq("ParticipantAgent contains a 'vc' claim, but the type is incorrect. Expected java.util.List, received java.lang.Object.")); + } + + @Test + void evaluate_rightOperandNotActive() { + when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createMembershipCredential().build()))); + assertThat(function.evaluate("Membership", Operator.EQ, "invalid", null, context)).isFalse(); + verify(context).reportProblem(eq("Right-operand must be equal to 'active', but was 'invalid'")); + } + + @Test + void evaluate_whenSingleCredentialFound() { + when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createMembershipCredential().build()))); + assertThat(function.evaluate("Membership", Operator.EQ, "active", null, context)).isTrue(); + } + + @Test + void evaluate_whenMultipleCredentialsFound() { + when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createMembershipCredential().build(), + createMembershipCredential().build(), + createPcfCredential().build()))); + assertThat(function.evaluate("Membership", Operator.EQ, "active", null, context)).isTrue(); + } + + @Test + void evaluate_whenCredentialNotFound() { + when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createPcfCredential().build()))); + assertThat(function.evaluate("Membership", Operator.EQ, "active", null, context)).isFalse(); + } +} \ No newline at end of file From d74b1ab4dd352931e11753930c5bf320f51baf12 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 19 Feb 2024 12:54:33 +0100 Subject: [PATCH 018/100] chore(deps): bump apache-sshd from 2.12.0 to 2.12.1 (#1063) Bumps `apache-sshd` from 2.12.0 to 2.12.1. Updates `org.apache.sshd:sshd-core` from 2.12.0 to 2.12.1 - [Release notes](https://github.com/apache/mina-sshd/releases) - [Changelog](https://github.com/apache/mina-sshd/blob/master/CHANGES.md) - [Commits](https://github.com/apache/mina-sshd/compare/sshd-2.12.0...sshd-2.12.1) Updates `org.apache.sshd:sshd-sftp` from 2.12.0 to 2.12.1 - [Release notes](https://github.com/apache/mina-sshd/releases) - [Changelog](https://github.com/apache/mina-sshd/blob/master/CHANGES.md) - [Commits](https://github.com/apache/mina-sshd/compare/sshd-2.12.0...sshd-2.12.1) --- updated-dependencies: - dependency-name: org.apache.sshd:sshd-core dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.apache.sshd:sshd-sftp dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index edbdfdc82..745fe6507 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -3,7 +3,7 @@ format.version = "1.1" [versions] edc = "0.5.2-20240219-SNAPSHOT" -apache-sshd = "2.12.0" +apache-sshd = "2.12.1" assertj = "3.25.3" awaitility = "4.2.0" aws = "2.24.1" From 9d221b7de9b68dda0eadfef84e39710fa595943a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 19 Feb 2024 13:00:34 +0100 Subject: [PATCH 019/100] chore(deps): bump flyway from 10.7.2 to 10.8.1 (#1066) Bumps `flyway` from 10.7.2 to 10.8.1. Updates `org.flywaydb:flyway-core` from 10.7.2 to 10.8.1 - [Release notes](https://github.com/flyway/flyway/releases) - [Commits](https://github.com/flyway/flyway/compare/flyway-10.7.2...flyway-10.8.1) Updates `org.flywaydb:flyway-database-postgresql` from 10.7.2 to 10.8.1 --- updated-dependencies: - dependency-name: org.flywaydb:flyway-core dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: org.flywaydb:flyway-database-postgresql dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 745fe6507..b0588d7dd 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -9,7 +9,7 @@ awaitility = "4.2.0" aws = "2.24.1" azure-identity = "1.11.2" bouncyCastle-jdk18on = "1.77" -flyway = "10.7.2" +flyway = "10.8.1" iron-vc = "0.8.1" jackson = "2.16.1" jakarta-json = "2.0.1" From 3a74bfa1c6a8a1c800e83da5a54ae3473fc5c66e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 19 Feb 2024 13:00:46 +0100 Subject: [PATCH 020/100] chore(deps): bump mikefarah/yq from 4.40.7 to 4.41.1 (#1064) Bumps [mikefarah/yq](https://github.com/mikefarah/yq) from 4.40.7 to 4.41.1. - [Release notes](https://github.com/mikefarah/yq/releases) - [Changelog](https://github.com/mikefarah/yq/blob/master/release_notes.txt) - [Commits](https://github.com/mikefarah/yq/compare/v4.40.7...v4.41.1) --- updated-dependencies: - dependency-name: mikefarah/yq dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/draft-new-release.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/draft-new-release.yaml b/.github/workflows/draft-new-release.yaml index 20f24c938..b6ce90acf 100644 --- a/.github/workflows/draft-new-release.yaml +++ b/.github/workflows/draft-new-release.yaml @@ -54,7 +54,7 @@ jobs: GITHUB_PACKAGE_USERNAME: ${{ github.actor }} GITHUB_PACKAGE_PASSWORD: ${{ secrets.GITHUB_TOKEN }} - name: Bump version in /charts - uses: mikefarah/yq@v4.40.7 + uses: mikefarah/yq@v4.41.1 with: cmd: |- find charts -name Chart.yaml -maxdepth 3 | xargs -n1 yq -i '.appVersion = "${{ github.event.inputs.version }}" | .version = "${{ github.event.inputs.version }}"' From d9fa0d4797d650f7c37be694086cc9c34c337e4c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 19 Feb 2024 13:54:07 +0100 Subject: [PATCH 021/100] chore(deps): bump aws from 2.24.1 to 2.24.5 (#1067) Bumps `aws` from 2.24.1 to 2.24.5. Updates `software.amazon.awssdk:s3` from 2.24.1 to 2.24.5 Updates `software.amazon.awssdk:s3-transfer-manager` from 2.24.1 to 2.24.5 --- updated-dependencies: - dependency-name: software.amazon.awssdk:s3 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:s3-transfer-manager dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index b0588d7dd..296eb57e4 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -6,7 +6,7 @@ edc = "0.5.2-20240219-SNAPSHOT" apache-sshd = "2.12.1" assertj = "3.25.3" awaitility = "4.2.0" -aws = "2.24.1" +aws = "2.24.5" azure-identity = "1.11.2" bouncyCastle-jdk18on = "1.77" flyway = "10.8.1" From 6dadb2d87e121718e38a06ef2be3132d34176d3a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 19 Feb 2024 14:05:52 +0100 Subject: [PATCH 022/100] chore(deps): bump com.apicatalog:iron-verifiable-credentials from 0.8.1 to 0.11.0 (#1065) * chore(deps): bump com.apicatalog:iron-verifiable-credentials Bumps [com.apicatalog:iron-verifiable-credentials](https://github.com/filip26/iron-verifiable-credentials) from 0.8.1 to 0.11.0. - [Release notes](https://github.com/filip26/iron-verifiable-credentials/releases) - [Commits](https://github.com/filip26/iron-verifiable-credentials/compare/v0.8.1...v0.11.0) --- updated-dependencies: - dependency-name: com.apicatalog:iron-verifiable-credentials dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * DEPENDENCIES --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Paul Latzelsperger --- DEPENDENCIES | 64 +++++++++++++++++++-------------------- gradle/libs.versions.toml | 2 +- 2 files changed, 33 insertions(+), 33 deletions(-) diff --git a/DEPENDENCIES b/DEPENDENCIES index caa417584..f32ca66ff 100644 --- a/DEPENDENCIES +++ b/DEPENDENCIES @@ -227,9 +227,9 @@ maven/mavencentral/org.apache.maven.doxia/doxia-core/1.12.0, Apache-2.0, approve maven/mavencentral/org.apache.maven.doxia/doxia-logging-api/1.12.0, Apache-2.0, approved, clearlydefined maven/mavencentral/org.apache.maven.doxia/doxia-module-xdoc/1.12.0, Apache-2.0, approved, clearlydefined maven/mavencentral/org.apache.maven.doxia/doxia-sink-api/1.12.0, Apache-2.0, approved, clearlydefined -maven/mavencentral/org.apache.sshd/sshd-common/2.12.0, Apache-2.0 AND ISC, approved, #12842 -maven/mavencentral/org.apache.sshd/sshd-core/2.12.0, Apache-2.0, approved, #12841 -maven/mavencentral/org.apache.sshd/sshd-sftp/2.12.0, Apache-2.0, approved, #12840 +maven/mavencentral/org.apache.sshd/sshd-common/2.12.1, Apache-2.0 AND ISC, approved, #12842 +maven/mavencentral/org.apache.sshd/sshd-core/2.12.1, Apache-2.0, approved, #12841 +maven/mavencentral/org.apache.sshd/sshd-sftp/2.12.1, Apache-2.0, approved, #12840 maven/mavencentral/org.apache.xbean/xbean-reflect/3.7, Apache-2.0, approved, clearlydefined maven/mavencentral/org.apiguardian/apiguardian-api/1.1.2, Apache-2.0, approved, clearlydefined maven/mavencentral/org.assertj/assertj-core/3.25.1, Apache-2.0, approved, #12585 @@ -418,8 +418,8 @@ maven/mavencentral/org.eclipse.jetty/jetty-servlet/11.0.20, EPL-2.0 OR Apache-2. maven/mavencentral/org.eclipse.jetty/jetty-util/11.0.20, EPL-2.0 OR Apache-2.0, approved, rt.jetty maven/mavencentral/org.eclipse.jetty/jetty-webapp/11.0.20, EPL-2.0 OR Apache-2.0, approved, rt.jetty maven/mavencentral/org.eclipse.jetty/jetty-xml/11.0.20, EPL-2.0 OR Apache-2.0, approved, rt.jetty -maven/mavencentral/org.flywaydb/flyway-core/10.7.2, Apache-2.0, approved, #13235 -maven/mavencentral/org.flywaydb/flyway-database-postgresql/10.7.2, Apache-2.0, approved, #13236 +maven/mavencentral/org.flywaydb/flyway-core/10.8.1, , restricted, clearlydefined +maven/mavencentral/org.flywaydb/flyway-database-postgresql/10.8.1, , restricted, clearlydefined maven/mavencentral/org.glassfish.hk2.external/aopalliance-repackaged/3.0.5, EPL-2.0 OR GPL-2.0-only with Classpath-exception-2.0, approved, ee4j.glassfish maven/mavencentral/org.glassfish.hk2/hk2-api/3.0.5, EPL-2.0 OR GPL-2.0-only with Classpath-exception-2.0, approved, ee4j.glassfish maven/mavencentral/org.glassfish.hk2/hk2-locator/3.0.5, EPL-2.0 OR GPL-2.0-only with Classpath-exception-2.0, approved, ee4j.glassfish @@ -515,58 +515,58 @@ maven/mavencentral/org.xmlresolver/xmlresolver/5.2.0, Apache-2.0, approved, clea maven/mavencentral/org.yaml/snakeyaml/2.0, Apache-2.0 AND (Apache-2.0 OR BSD-3-Clause OR EPL-1.0 OR GPL-2.0-or-later OR LGPL-2.1-or-later), approved, #7275 maven/mavencentral/org.yaml/snakeyaml/2.2, Apache-2.0 AND (Apache-2.0 OR BSD-3-Clause OR EPL-1.0 OR GPL-2.0-or-later OR LGPL-2.1-or-later), approved, #10232 maven/mavencentral/software.amazon.awssdk/annotations/2.22.9, Apache-2.0, approved, #12618 -maven/mavencentral/software.amazon.awssdk/annotations/2.24.1, Apache-2.0, approved, #13251 +maven/mavencentral/software.amazon.awssdk/annotations/2.24.5, Apache-2.0, approved, #13251 maven/mavencentral/software.amazon.awssdk/apache-client/2.22.9, Apache-2.0, approved, #12633 -maven/mavencentral/software.amazon.awssdk/apache-client/2.24.1, Apache-2.0, approved, #13257 +maven/mavencentral/software.amazon.awssdk/apache-client/2.24.5, Apache-2.0, approved, #13257 maven/mavencentral/software.amazon.awssdk/arns/2.22.9, Apache-2.0, approved, #12647 -maven/mavencentral/software.amazon.awssdk/arns/2.24.1, Apache-2.0, approved, #13243 +maven/mavencentral/software.amazon.awssdk/arns/2.24.5, Apache-2.0, approved, #13243 maven/mavencentral/software.amazon.awssdk/auth/2.22.9, Apache-2.0, approved, #12622 -maven/mavencentral/software.amazon.awssdk/auth/2.24.1, Apache-2.0, approved, #13256 +maven/mavencentral/software.amazon.awssdk/auth/2.24.5, Apache-2.0, approved, #13256 maven/mavencentral/software.amazon.awssdk/aws-core/2.22.9, Apache-2.0, approved, #12640 -maven/mavencentral/software.amazon.awssdk/aws-core/2.24.1, Apache-2.0, approved, #13240 +maven/mavencentral/software.amazon.awssdk/aws-core/2.24.5, Apache-2.0, approved, #13240 maven/mavencentral/software.amazon.awssdk/aws-query-protocol/2.22.9, Apache-2.0, approved, #12645 -maven/mavencentral/software.amazon.awssdk/aws-query-protocol/2.24.1, Apache-2.0, approved, #13262 +maven/mavencentral/software.amazon.awssdk/aws-query-protocol/2.24.5, Apache-2.0, approved, #13262 maven/mavencentral/software.amazon.awssdk/aws-xml-protocol/2.22.9, Apache-2.0, approved, #12628 -maven/mavencentral/software.amazon.awssdk/aws-xml-protocol/2.24.1, Apache-2.0, approved, #13247 +maven/mavencentral/software.amazon.awssdk/aws-xml-protocol/2.24.5, Apache-2.0, approved, #13247 maven/mavencentral/software.amazon.awssdk/checksums-spi/2.22.9, Apache-2.0, approved, #12642 -maven/mavencentral/software.amazon.awssdk/checksums-spi/2.24.1, Apache-2.0, approved, #13245 +maven/mavencentral/software.amazon.awssdk/checksums-spi/2.24.5, Apache-2.0, approved, #13245 maven/mavencentral/software.amazon.awssdk/checksums/2.22.9, Apache-2.0, approved, #12641 -maven/mavencentral/software.amazon.awssdk/checksums/2.24.1, Apache-2.0, approved, #13242 +maven/mavencentral/software.amazon.awssdk/checksums/2.24.5, Apache-2.0, approved, #13242 maven/mavencentral/software.amazon.awssdk/crt-core/2.22.9, Apache-2.0, approved, #12635 -maven/mavencentral/software.amazon.awssdk/crt-core/2.24.1, Apache-2.0, approved, #13252 +maven/mavencentral/software.amazon.awssdk/crt-core/2.24.5, Apache-2.0, approved, #13252 maven/mavencentral/software.amazon.awssdk/endpoints-spi/2.22.9, Apache-2.0, approved, #12624 -maven/mavencentral/software.amazon.awssdk/endpoints-spi/2.24.1, Apache-2.0, approved, #13246 +maven/mavencentral/software.amazon.awssdk/endpoints-spi/2.24.5, Apache-2.0, approved, #13246 maven/mavencentral/software.amazon.awssdk/http-auth-aws/2.22.9, Apache-2.0, approved, #12637 -maven/mavencentral/software.amazon.awssdk/http-auth-aws/2.24.1, Apache-2.0, approved, #13253 +maven/mavencentral/software.amazon.awssdk/http-auth-aws/2.24.5, Apache-2.0, approved, #13253 maven/mavencentral/software.amazon.awssdk/http-auth-spi/2.22.9, Apache-2.0, approved, #12638 -maven/mavencentral/software.amazon.awssdk/http-auth-spi/2.24.1, Apache-2.0, approved, #13264 +maven/mavencentral/software.amazon.awssdk/http-auth-spi/2.24.5, Apache-2.0, approved, #13264 maven/mavencentral/software.amazon.awssdk/http-auth/2.22.9, Apache-2.0, approved, #12626 -maven/mavencentral/software.amazon.awssdk/http-auth/2.24.1, Apache-2.0, approved, #13248 +maven/mavencentral/software.amazon.awssdk/http-auth/2.24.5, Apache-2.0, approved, #13248 maven/mavencentral/software.amazon.awssdk/http-client-spi/2.22.9, Apache-2.0, approved, #12627 -maven/mavencentral/software.amazon.awssdk/http-client-spi/2.24.1, Apache-2.0, approved, #13259 +maven/mavencentral/software.amazon.awssdk/http-client-spi/2.24.5, Apache-2.0, approved, #13259 maven/mavencentral/software.amazon.awssdk/iam/2.22.9, Apache-2.0, approved, clearlydefined maven/mavencentral/software.amazon.awssdk/identity-spi/2.22.9, Apache-2.0, approved, #12636 -maven/mavencentral/software.amazon.awssdk/identity-spi/2.24.1, Apache-2.0, approved, #13244 +maven/mavencentral/software.amazon.awssdk/identity-spi/2.24.5, Apache-2.0, approved, #13244 maven/mavencentral/software.amazon.awssdk/json-utils/2.22.9, Apache-2.0, approved, #12646 -maven/mavencentral/software.amazon.awssdk/json-utils/2.24.1, Apache-2.0, approved, #13261 +maven/mavencentral/software.amazon.awssdk/json-utils/2.24.5, Apache-2.0, approved, #13261 maven/mavencentral/software.amazon.awssdk/metrics-spi/2.22.9, Apache-2.0, approved, #12649 -maven/mavencentral/software.amazon.awssdk/metrics-spi/2.24.1, Apache-2.0, approved, #13239 +maven/mavencentral/software.amazon.awssdk/metrics-spi/2.24.5, Apache-2.0, approved, #13239 maven/mavencentral/software.amazon.awssdk/netty-nio-client/2.22.9, Apache-2.0, approved, #12644 -maven/mavencentral/software.amazon.awssdk/netty-nio-client/2.24.1, Apache-2.0, approved, #13260 +maven/mavencentral/software.amazon.awssdk/netty-nio-client/2.24.5, Apache-2.0, approved, #13260 maven/mavencentral/software.amazon.awssdk/profiles/2.22.9, Apache-2.0, approved, #12620 -maven/mavencentral/software.amazon.awssdk/profiles/2.24.1, Apache-2.0, approved, #13258 +maven/mavencentral/software.amazon.awssdk/profiles/2.24.5, Apache-2.0, approved, #13258 maven/mavencentral/software.amazon.awssdk/protocol-core/2.22.9, Apache-2.0, approved, #12648 -maven/mavencentral/software.amazon.awssdk/protocol-core/2.24.1, Apache-2.0, approved, #13241 +maven/mavencentral/software.amazon.awssdk/protocol-core/2.24.5, Apache-2.0, approved, #13241 maven/mavencentral/software.amazon.awssdk/regions/2.22.9, Apache-2.0, approved, #12643 -maven/mavencentral/software.amazon.awssdk/regions/2.24.1, Apache-2.0, approved, #13255 -maven/mavencentral/software.amazon.awssdk/s3-transfer-manager/2.24.1, Apache-2.0, approved, #13263 +maven/mavencentral/software.amazon.awssdk/regions/2.24.5, Apache-2.0, approved, #13255 +maven/mavencentral/software.amazon.awssdk/s3-transfer-manager/2.24.5, Apache-2.0, approved, #13263 maven/mavencentral/software.amazon.awssdk/s3/2.22.9, Apache-2.0, approved, #12630 -maven/mavencentral/software.amazon.awssdk/s3/2.24.1, Apache-2.0, approved, #13254 +maven/mavencentral/software.amazon.awssdk/s3/2.24.5, Apache-2.0, approved, #13254 maven/mavencentral/software.amazon.awssdk/sdk-core/2.22.9, Apache-2.0, approved, #12639 -maven/mavencentral/software.amazon.awssdk/sdk-core/2.24.1, Apache-2.0, approved, #13265 +maven/mavencentral/software.amazon.awssdk/sdk-core/2.24.5, Apache-2.0, approved, #13265 maven/mavencentral/software.amazon.awssdk/sts/2.22.9, Apache-2.0, approved, clearlydefined maven/mavencentral/software.amazon.awssdk/third-party-jackson-core/2.22.9, Apache-2.0, approved, #12629 -maven/mavencentral/software.amazon.awssdk/third-party-jackson-core/2.24.1, Apache-2.0, approved, #13249 +maven/mavencentral/software.amazon.awssdk/third-party-jackson-core/2.24.5, Apache-2.0, approved, #13249 maven/mavencentral/software.amazon.awssdk/utils/2.22.9, Apache-2.0, approved, #12631 -maven/mavencentral/software.amazon.awssdk/utils/2.24.1, Apache-2.0, approved, #13250 +maven/mavencentral/software.amazon.awssdk/utils/2.24.5, Apache-2.0, approved, #13250 maven/mavencentral/software.amazon.eventstream/eventstream/1.0.1, Apache-2.0, approved, clearlydefined diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 296eb57e4..3dfe3e9ad 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -10,7 +10,7 @@ aws = "2.24.5" azure-identity = "1.11.2" bouncyCastle-jdk18on = "1.77" flyway = "10.8.1" -iron-vc = "0.8.1" +iron-vc = "0.11.0" jackson = "2.16.1" jakarta-json = "2.0.1" jupiter = "5.10.2" From 2c28cf575f2fdc865d63704a0728140e156a68f9 Mon Sep 17 00:00:00 2001 From: Enrico Risa Date: Tue, 20 Feb 2024 10:21:08 +0100 Subject: [PATCH 023/100] feat: dast scan integration (#1072) * feat: dast scan integration * chore: dependencies file --- .../actions/setup-memory-runtime/action.yml | 73 +++++++++++ .github/workflows/dast-scan.yaml | 123 ++++++++++++++++++ DEPENDENCIES | 4 +- dast/docker-compose.yaml | 50 +++++++ dast/fetch-token.sh | 37 ++++++ 5 files changed, 285 insertions(+), 2 deletions(-) create mode 100644 .github/actions/setup-memory-runtime/action.yml create mode 100644 .github/workflows/dast-scan.yaml create mode 100644 dast/docker-compose.yaml create mode 100755 dast/fetch-token.sh diff --git a/.github/actions/setup-memory-runtime/action.yml b/.github/actions/setup-memory-runtime/action.yml new file mode 100644 index 000000000..3de89f767 --- /dev/null +++ b/.github/actions/setup-memory-runtime/action.yml @@ -0,0 +1,73 @@ +################################################################################# +# Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License, Version 2.0 which is available at +# https://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. +# +# SPDX-License-Identifier: Apache-2.0 +################################################################################# + + +--- +name: "Setup TractusX EDC in memory runtime" +description: "Setup TractusX EDC in memory runtime" +runs: + using: "composite" + steps: + - uses: actions/checkout@v4 + - uses: ./.github/actions/setup-java + + - uses: actions/checkout@v4 + + - name: Dockerize TractusX EDC in memory distribution + shell: bash + run: | + ./gradlew :edc-controlplane:edc-runtime-memory:dockerize + + - name: Starting MIW, Keycloak and Postgres Servers + shell: bash + run: | + cd edc-tests/miw-tests/src/test/resources/docker-environment + docker compose up -d --wait + + - uses: nick-fields/retry@v3 + name: Wait for MIW + with: + timeout_minutes: 5 + max_attempts: 3 + command: | + code=$(curl -IL -sw "%{http_code}" http://localhost:8000/api/actuator/health -o /dev/null) + if [ "$code" -ne "401" ]; then + echo "MIW not ready yet, status = $code" + exit 1; + fi + + - name: Starting in memory TractusX EDC + shell: bash + run: | + cd dast + docker compose up -d + + + - uses: nick-fields/retry@v3 + name: Wait for TractusX EDC + with: + timeout_minutes: 5 + max_attempts: 3 + command: | + code=$(curl -IL -sw "%{http_code}" http://localhost:8181/api/check/health -o /dev/null) + if [ "$code" -ne "401" ]; then + echo "TractusX EDC not ready yet, status = $code" + docker logs dast-edc-runtime-1 + exit 1; + fi \ No newline at end of file diff --git a/.github/workflows/dast-scan.yaml b/.github/workflows/dast-scan.yaml new file mode 100644 index 000000000..ab993e800 --- /dev/null +++ b/.github/workflows/dast-scan.yaml @@ -0,0 +1,123 @@ +################################################################################# +# Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License, Version 2.0 which is available at +# https://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. +# +# SPDX-License-Identifier: Apache-2.0 +################################################################################# + +name: ZAP_ALL + +on: + schedule: + - cron: '0 0 * * *' + workflow_dispatch: + +jobs: + zap_scan: + runs-on: ubuntu-latest + name: OWASP ZAP API Scan + + steps: + - uses: actions/checkout@v4 + - uses: ./.github/actions/setup-memory-runtime + + - name: Fetch MIW VP token + run: ./dast/fetch-token.sh + + - name: API Catalog Request Test + id: catalog_request + run: | + dsp_response=$(curl -w "%{http_code}" --request POST \ + --url http://localhost:8282/api/v1/dsp/catalog/request \ + --header "Authorization: $VP_TOKEN" \ + --header 'Content-Type: application/json' \ + --data '{ + "@type": "dspace:CatalogRequestMessage", + "dspace:filter": { + "@type": "QuerySpec", + "limit": 50, + "offset": 0, + "sortOrder": "ASC", + "filterExpression": [] + }, + "@context": { + "@vocab": "https://w3id.org/edc/v0.0.1/ns/", + "edc": "https://w3id.org/edc/v0.0.1/ns/", + "tx": "https://w3id.org/tractusx/v0.0.1/ns/", + "dcat": "http://www.w3.org/ns/dcat#", + "dct": "https://purl.org/dc/terms/", + "odrl": "http://www.w3.org/ns/odrl/2/", + "dspace": "https://w3id.org/dspace/v0.8/" + } + }') + + echo "Response: $dsp_response" + + - name: Generating report skeletons + if: success() || failure() + run: | + touch API_report.html + chmod a+w API_report.html + ls -lrt + + - name: Run ZAP API scan + run: | + set +e + + echo "Pulling ZAP image..." + docker pull ghcr.io/zaproxy/zaproxy:stable -q + echo "Starting ZAP Docker container..." + docker run --network miw-net -v ${GITHUB_WORKSPACE}:/zap/wrk/:rw ghcr.io/zaproxy/zaproxy:stable zap-api-scan.py -t http://edc-runtime:8282/api/v1/dsp -f openapi -r API_report.html -T 1 + + echo "... done." + + - name: Upload HTML report + if: success() || failure() + uses: actions/upload-artifact@v3 + with: + name: ZAP_API scan report + path: ./API_report.html + + zap_scan2: + runs-on: ubuntu-latest + name: OWASP ZAP FULL Scan + steps: + - uses: actions/checkout@v4 + - uses: ./.github/actions/setup-memory-runtime + + - name: Generating report skeletons + if: success() || failure() + run: | + touch fullscan_report.html + chmod a+w fullscan_report.html + ls -lrt + + - name: Perform ZAP FULL scan + run: | + set +e + + echo "Pulling ZAP image..." + docker pull ghcr.io/zaproxy/zaproxy:stable -q + echo "Starting ZAP Docker container..." + docker run --network miw-net -v ${GITHUB_WORKSPACE}:/zap/wrk/:rw ghcr.io/zaproxy/zaproxy:stable zap-full-scan.py -t http://edc-runtime:8282/api/v1/dsp -r fullscan_report.html -T 1 + + echo "... done." + + - name: Upload HTML report + if: success() || failure() + uses: actions/upload-artifact@v3 + with: + name: ZAP_FULL scan report + path: ./fullscan_report.html \ No newline at end of file diff --git a/DEPENDENCIES b/DEPENDENCIES index f32ca66ff..1e7db5335 100644 --- a/DEPENDENCIES +++ b/DEPENDENCIES @@ -418,8 +418,8 @@ maven/mavencentral/org.eclipse.jetty/jetty-servlet/11.0.20, EPL-2.0 OR Apache-2. maven/mavencentral/org.eclipse.jetty/jetty-util/11.0.20, EPL-2.0 OR Apache-2.0, approved, rt.jetty maven/mavencentral/org.eclipse.jetty/jetty-webapp/11.0.20, EPL-2.0 OR Apache-2.0, approved, rt.jetty maven/mavencentral/org.eclipse.jetty/jetty-xml/11.0.20, EPL-2.0 OR Apache-2.0, approved, rt.jetty -maven/mavencentral/org.flywaydb/flyway-core/10.8.1, , restricted, clearlydefined -maven/mavencentral/org.flywaydb/flyway-database-postgresql/10.8.1, , restricted, clearlydefined +maven/mavencentral/org.flywaydb/flyway-core/10.8.1, Apache-2.0, approved, #13291 +maven/mavencentral/org.flywaydb/flyway-database-postgresql/10.8.1, Apache-2.0, approved, #13290 maven/mavencentral/org.glassfish.hk2.external/aopalliance-repackaged/3.0.5, EPL-2.0 OR GPL-2.0-only with Classpath-exception-2.0, approved, ee4j.glassfish maven/mavencentral/org.glassfish.hk2/hk2-api/3.0.5, EPL-2.0 OR GPL-2.0-only with Classpath-exception-2.0, approved, ee4j.glassfish maven/mavencentral/org.glassfish.hk2/hk2-locator/3.0.5, EPL-2.0 OR GPL-2.0-only with Classpath-exception-2.0, approved, ee4j.glassfish diff --git a/dast/docker-compose.yaml b/dast/docker-compose.yaml new file mode 100644 index 000000000..e8b3ddef7 --- /dev/null +++ b/dast/docker-compose.yaml @@ -0,0 +1,50 @@ +################################################################################# +# Copyright (c) 2021,2023 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License, Version 2.0 which is available at +# https://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. +# +# SPDX-License-Identifier: Apache-2.0 +################################################################################# + + +version: '3' + +services: + edc-runtime: + image: edc-runtime-memory:latest + environment: + TX_SSI_OAUTH_TOKEN_URL: http://keycloak:8080/realms/miw_test/protocol/openid-connect/token + TX_SSI_OAUTH_CLIENT_ID: miw_private_client + TX_SSI_OAUTH_CLIENT_SECRET_ALIAS: client-alias + EDC_VAULT_SECRETS: "client-alias:miw_private_client" + TX_SSI_MIW_URL: http://miw:8000 + TX_SSI_MIW_AUTHORITY_ID: BPNL000000000000 + TX_SSI_MIW_AUTHORITY_ISSUER: did:web:localhost%3A8000:BPNL000000000000 + TX_SSI_ENDPOINT_AUDIENCE: "http://test" + EDC_DATAPLANE_TOKEN_VALIDATION_ENDPOINT: "http://validate" + EDC_API_AUTH_KEY: password + + networks: + - miw-net + ports: + - "8282:8282" + - "8181:8181" + +volumes: + postgres_data: + driver: local + +networks: + miw-net: + external: true diff --git a/dast/fetch-token.sh b/dast/fetch-token.sh new file mode 100755 index 000000000..1ca198dab --- /dev/null +++ b/dast/fetch-token.sh @@ -0,0 +1,37 @@ +################################################################################# +# Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License, Version 2.0 which is available at +# https://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. +# +# SPDX-License-Identifier: Apache-2.0 +################################################################################# + +#!/bin/bash + +response=$(curl -X POST -d 'client_id=miw_private_client&grant_type=client_credentials&client_secret=miw_private_client&scope=openid' http://localhost:8080/realms/miw_test/protocol/openid-connect/token) +token=$(echo "$response" | jq -r '.access_token') + +credentials=$(curl --url 'http://localhost:8000/api/credentials?type=SummaryCredential' --header "Authorization: Bearer $token" --header 'Content-Type: application/json' | jq -r '.content') + + +vp_token=$(curl --request POST \ + --url 'http://localhost:8000/api/presentations?asJwt=true&audience=http://test' \ + --header "Authorization: Bearer $token" \ + --header 'Content-Type: application/json' \ + --data "{ \"verifiableCredentials\": $credentials }" \ + | jq -r '.vp') + +echo "VP_TOKEN=$vp_token" >> "$GITHUB_ENV" + + From c99a8eb4da3078eedace72c9cfa228f6b1b4c0ea Mon Sep 17 00:00:00 2001 From: Enrico Risa Date: Tue, 20 Feb 2024 15:06:02 +0100 Subject: [PATCH 024/100] chore: Refactor BPN evaluation function (#1074) * chore: BPN number policy function refactor * Update edc-extensions/bpn-validation/bpn-validation-core/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/BusinessPartnerNumberPermissionFunction.java Co-authored-by: Jim Marino --------- Co-authored-by: Jim Marino --- ...nessPartnerNumberValidationExtension.java} | 63 ++---- .../BusinessPartnerGroupFunction.java | 20 +- ...sinessPartnerNumberPermissionFunction.java | 76 +++++++ .../AbstractBusinessPartnerValidation.java | 171 -------------- .../legacy/BusinessPartnerDutyFunction.java | 45 ---- .../BusinessPartnerPermissionFunction.java | 45 ---- .../BusinessPartnerProhibitionFunction.java | 45 ---- ...rg.eclipse.edc.spi.system.ServiceExtension | 2 +- ...sPartnerNumberValidationExtensionTest.java | 83 +++++++ ...usinessPartnerValidationExtensionTest.java | 130 ----------- ...AbstractBusinessPartnerValidationTest.java | 210 ------------------ .../BusinessPartnerGroupFunctionTest.java | 10 +- ...ssPartnerNumberPermissionFunctionTest.java | 111 +++++++++ 13 files changed, 293 insertions(+), 718 deletions(-) rename edc-extensions/bpn-validation/bpn-validation-core/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/{LegacyBusinessPartnerValidationExtension.java => BusinessPartnerNumberValidationExtension.java} (52%) create mode 100644 edc-extensions/bpn-validation/bpn-validation-core/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/BusinessPartnerNumberPermissionFunction.java delete mode 100644 edc-extensions/bpn-validation/bpn-validation-core/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/legacy/AbstractBusinessPartnerValidation.java delete mode 100644 edc-extensions/bpn-validation/bpn-validation-core/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/legacy/BusinessPartnerDutyFunction.java delete mode 100644 edc-extensions/bpn-validation/bpn-validation-core/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/legacy/BusinessPartnerPermissionFunction.java delete mode 100644 edc-extensions/bpn-validation/bpn-validation-core/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/legacy/BusinessPartnerProhibitionFunction.java create mode 100644 edc-extensions/bpn-validation/bpn-validation-core/src/test/java/org/eclipse/tractusx/edc/validation/businesspartner/BusinessPartnerNumberValidationExtensionTest.java delete mode 100644 edc-extensions/bpn-validation/bpn-validation-core/src/test/java/org/eclipse/tractusx/edc/validation/businesspartner/LegacyBusinessPartnerValidationExtensionTest.java delete mode 100644 edc-extensions/bpn-validation/bpn-validation-core/src/test/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/AbstractBusinessPartnerValidationTest.java create mode 100644 edc-extensions/bpn-validation/bpn-validation-core/src/test/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/BusinessPartnerNumberPermissionFunctionTest.java diff --git a/edc-extensions/bpn-validation/bpn-validation-core/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/LegacyBusinessPartnerValidationExtension.java b/edc-extensions/bpn-validation/bpn-validation-core/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/BusinessPartnerNumberValidationExtension.java similarity index 52% rename from edc-extensions/bpn-validation/bpn-validation-core/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/LegacyBusinessPartnerValidationExtension.java rename to edc-extensions/bpn-validation/bpn-validation-core/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/BusinessPartnerNumberValidationExtension.java index 0d6cfbe2a..8776044f1 100644 --- a/edc-extensions/bpn-validation/bpn-validation-core/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/LegacyBusinessPartnerValidationExtension.java +++ b/edc-extensions/bpn-validation/bpn-validation-core/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/BusinessPartnerNumberValidationExtension.java @@ -21,29 +21,25 @@ import org.eclipse.edc.policy.engine.spi.PolicyEngine; import org.eclipse.edc.policy.engine.spi.RuleBindingRegistry; -import org.eclipse.edc.policy.model.Duty; import org.eclipse.edc.policy.model.Permission; -import org.eclipse.edc.policy.model.Prohibition; +import org.eclipse.edc.runtime.metamodel.annotation.Extension; import org.eclipse.edc.runtime.metamodel.annotation.Inject; -import org.eclipse.edc.runtime.metamodel.annotation.Setting; import org.eclipse.edc.spi.system.ServiceExtension; import org.eclipse.edc.spi.system.ServiceExtensionContext; -import org.eclipse.tractusx.edc.validation.businesspartner.functions.legacy.BusinessPartnerDutyFunction; -import org.eclipse.tractusx.edc.validation.businesspartner.functions.legacy.BusinessPartnerPermissionFunction; -import org.eclipse.tractusx.edc.validation.businesspartner.functions.legacy.BusinessPartnerProhibitionFunction; +import org.eclipse.tractusx.edc.validation.businesspartner.functions.BusinessPartnerNumberPermissionFunction; import static org.eclipse.edc.connector.contract.spi.offer.ContractDefinitionResolver.CATALOGING_SCOPE; import static org.eclipse.edc.connector.contract.spi.validation.ContractValidationService.NEGOTIATION_SCOPE; import static org.eclipse.edc.connector.contract.spi.validation.ContractValidationService.TRANSFER_SCOPE; +import static org.eclipse.edc.policy.model.OdrlNamespace.ODRL_SCHEMA; import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.TX_NAMESPACE; +import static org.eclipse.tractusx.edc.validation.businesspartner.BusinessPartnerNumberValidationExtension.NAME; /** * Business partner number evaluation function. - * - * @deprecated Please use {@code BusinessPartnerEvaluationExtension} instead. */ -@Deprecated(forRemoval = true, since = "0.5.0") -public class LegacyBusinessPartnerValidationExtension implements ServiceExtension { +@Extension(NAME) +public class BusinessPartnerNumberValidationExtension implements ServiceExtension { /** * The key for business partner numbers constraints. Must be used as left operand when declaring constraints. @@ -60,66 +56,37 @@ public class LegacyBusinessPartnerValidationExtension implements ServiceExtensio * */ public static final String BUSINESS_PARTNER_CONSTRAINT_KEY = "BusinessPartnerNumber"; - public static final String TX_BUSINESS_PARTNER_CONSTRAINT_KEY = TX_NAMESPACE + BUSINESS_PARTNER_CONSTRAINT_KEY; - - - public static final String DEFAULT_LOG_AGREEMENT_EVALUATION = "true"; - - - @Setting(value = "Enable logging when evaluating the business partner constraints in the agreement validation", type = "boolean", defaultValue = DEFAULT_LOG_AGREEMENT_EVALUATION) - public static final String BUSINESS_PARTNER_VALIDATION_LOG_AGREEMENT_VALIDATION = "tractusx.businesspartnervalidation.log.agreement.validation"; + protected static final String NAME = "Business Partner Validation Extension"; @Inject private RuleBindingRegistry ruleBindingRegistry; @Inject private PolicyEngine policyEngine; - - public LegacyBusinessPartnerValidationExtension() { - } - - public LegacyBusinessPartnerValidationExtension( - final RuleBindingRegistry ruleBindingRegistry, final PolicyEngine policyEngine) { - this.ruleBindingRegistry = ruleBindingRegistry; - this.policyEngine = policyEngine; - } - + @Override public String name() { - return "Business Partner Validation Extension"; + return NAME; } @Override public void initialize(ServiceExtensionContext context) { - var monitor = context.getMonitor(); - - var logAgreementEvaluation = logAgreementEvaluationSetting(context); + var permissionFunction = new BusinessPartnerNumberPermissionFunction(); - var dutyFunction = new BusinessPartnerDutyFunction(monitor, logAgreementEvaluation); - var permissionFunction = new BusinessPartnerPermissionFunction(monitor, logAgreementEvaluation); - var prohibitionFunction = new BusinessPartnerProhibitionFunction(monitor, logAgreementEvaluation); + bindToScope(permissionFunction, TRANSFER_SCOPE); + bindToScope(permissionFunction, NEGOTIATION_SCOPE); + bindToScope(permissionFunction, CATALOGING_SCOPE); - bindToScope(dutyFunction, permissionFunction, prohibitionFunction, TRANSFER_SCOPE); - bindToScope(dutyFunction, permissionFunction, prohibitionFunction, NEGOTIATION_SCOPE); - bindToScope(dutyFunction, permissionFunction, prohibitionFunction, CATALOGING_SCOPE); - - monitor.warning("This extension was deprecated and is scheduled for removal in version 0.6.0 of Tractus-X EDC"); } - private void bindToScope(BusinessPartnerDutyFunction dutyFunction, BusinessPartnerPermissionFunction permissionFunction, BusinessPartnerProhibitionFunction prohibitionFunction, String scope) { + private void bindToScope(BusinessPartnerNumberPermissionFunction permissionFunction, String scope) { ruleBindingRegistry.bind("USE", scope); + ruleBindingRegistry.bind(ODRL_SCHEMA + "use", scope); ruleBindingRegistry.bind(BUSINESS_PARTNER_CONSTRAINT_KEY, scope); ruleBindingRegistry.bind(TX_BUSINESS_PARTNER_CONSTRAINT_KEY, scope); - - policyEngine.registerFunction(scope, Duty.class, BUSINESS_PARTNER_CONSTRAINT_KEY, dutyFunction); policyEngine.registerFunction(scope, Permission.class, BUSINESS_PARTNER_CONSTRAINT_KEY, permissionFunction); - policyEngine.registerFunction(scope, Prohibition.class, BUSINESS_PARTNER_CONSTRAINT_KEY, prohibitionFunction); - policyEngine.registerFunction(scope, Permission.class, TX_BUSINESS_PARTNER_CONSTRAINT_KEY, permissionFunction); } - private boolean logAgreementEvaluationSetting(ServiceExtensionContext context) { - return Boolean.parseBoolean(context.getSetting(BUSINESS_PARTNER_VALIDATION_LOG_AGREEMENT_VALIDATION, DEFAULT_LOG_AGREEMENT_EVALUATION)); - } } diff --git a/edc-extensions/bpn-validation/bpn-validation-core/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/BusinessPartnerGroupFunction.java b/edc-extensions/bpn-validation/bpn-validation-core/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/BusinessPartnerGroupFunction.java index 5167d899e..5ad1154ab 100644 --- a/edc-extensions/bpn-validation/bpn-validation-core/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/BusinessPartnerGroupFunction.java +++ b/edc-extensions/bpn-validation/bpn-validation-core/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/BusinessPartnerGroupFunction.java @@ -76,7 +76,6 @@ * @see BusinessPartnerStore */ public class BusinessPartnerGroupFunction implements AtomicConstraintFunction { - public static final String REFERRING_CONNECTOR_CLAIM = "referringConnector"; public static final String BUSINESS_PARTNER_CONSTRAINT_KEY = TX_NAMESPACE + "BusinessPartnerGroup"; private static final List ALLOWED_OPERATORS = List.of(EQ, NEQ, IN, IS_ALL_OF, IS_ANY_OF, IS_NONE_OF); private static final Map> OPERATOR_EVALUATOR_MAP = new HashMap<>(); @@ -122,7 +121,7 @@ public boolean evaluate(Operator operator, Object rightValue, Permission rule, P } - var bpn = getBpnClaim(participantAgent); + var bpn = participantAgent.getIdentity(); var groups = store.resolveForBpn(bpn); // BPN not found in database @@ -160,22 +159,7 @@ private List parseRightOperand(Object rightValue, PolicyContext context) context.reportProblem(format("Right operand expected to be either String or a Collection, but was " + rightValue.getClass())); return null; } - - private String getBpnClaim(ParticipantAgent participantAgent) { - String bpnClaim = null; - var claims = participantAgent.getClaims(); - - var bpnClaimObject = claims.get(REFERRING_CONNECTOR_CLAIM); - - if (bpnClaimObject instanceof String) { - bpnClaim = (String) bpnClaimObject; - } - if (bpnClaim == null) { - bpnClaim = participantAgent.getIdentity(); - } - return bpnClaim; - } - + private Boolean evaluateIn(BpnGroupHolder bpnGroupHolder) { var assigned = bpnGroupHolder.assignedGroups; // checks whether both lists overlap diff --git a/edc-extensions/bpn-validation/bpn-validation-core/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/BusinessPartnerNumberPermissionFunction.java b/edc-extensions/bpn-validation/bpn-validation-core/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/BusinessPartnerNumberPermissionFunction.java new file mode 100644 index 000000000..a7339c16a --- /dev/null +++ b/edc-extensions/bpn-validation/bpn-validation-core/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/BusinessPartnerNumberPermissionFunction.java @@ -0,0 +1,76 @@ +/******************************************************************************** + * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +package org.eclipse.tractusx.edc.validation.businesspartner.functions; + +import org.eclipse.edc.policy.engine.spi.AtomicConstraintFunction; +import org.eclipse.edc.policy.engine.spi.PolicyContext; +import org.eclipse.edc.policy.model.Operator; +import org.eclipse.edc.policy.model.Permission; +import org.eclipse.edc.spi.agent.ParticipantAgent; + +import java.util.Optional; + +import static java.lang.String.format; + +/** + * AtomicConstraintFunction to validate business partner numbers for edc permissions. + */ +public class BusinessPartnerNumberPermissionFunction implements AtomicConstraintFunction { + + public BusinessPartnerNumberPermissionFunction() { + } + + @Override + public boolean evaluate(Operator operator, Object rightValue, Permission rule, PolicyContext context) { + + if (operator != Operator.EQ) { + var message = format("As operator only 'EQ' is supported. Unsupported operator: '%s'", operator); + context.reportProblem(message); + return false; + } + + var participantAgent = context.getContextData(ParticipantAgent.class); + if (participantAgent == null) { + context.reportProblem("Required PolicyContext data not found: " + ParticipantAgent.class.getName()); + return false; + } + + var identity = participantAgent.getIdentity(); + if (identity == null) { + context.reportProblem("Identity of the participant agent cannot be null"); + return false; + } + + if ((rightValue instanceof String businessPartnerNumberStr)) { + if (businessPartnerNumberStr.equals(identity)) { + return true; + } else { + context.reportProblem("Identity of the participant not matching the expected one: " + businessPartnerNumberStr); + return false; + } + } else { + var message = format("Invalid right operand value: expected 'String' but got '%s'", + Optional.of(rightValue).map(Object::getClass).map(Class::getName).orElse(null)); + context.reportProblem(message); + return false; + } + + } +} diff --git a/edc-extensions/bpn-validation/bpn-validation-core/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/legacy/AbstractBusinessPartnerValidation.java b/edc-extensions/bpn-validation/bpn-validation-core/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/legacy/AbstractBusinessPartnerValidation.java deleted file mode 100644 index 93525a0da..000000000 --- a/edc-extensions/bpn-validation/bpn-validation-core/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/legacy/AbstractBusinessPartnerValidation.java +++ /dev/null @@ -1,171 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.validation.businesspartner.functions.legacy; - -import org.eclipse.edc.policy.engine.spi.PolicyContext; -import org.eclipse.edc.policy.model.Operator; -import org.eclipse.edc.spi.agent.ParticipantAgent; -import org.eclipse.edc.spi.monitor.Monitor; -import org.eclipse.edc.spi.types.domain.agreement.ContractAgreement; -import org.jetbrains.annotations.Nullable; - -import java.util.Objects; - -import static java.lang.String.format; - -/** - * Abstract class for BusinessPartnerNumber validation. This class may be inherited from the EDC - * policy enforcing functions for duties, permissions and prohibitions. - * - * @deprecated Please use {@code BusinessPartnerGroupFunction} instead - */ -@Deprecated(forRemoval = true, since = "0.5.0") -public abstract class AbstractBusinessPartnerValidation { - - // Developer Note: - // Problems reported to the policy context are not logged. Therefore, everything - // that is reported to the policy context should be logged, too. - - private static final String FAIL_EVALUATION_BECAUSE_RIGHT_VALUE_NOT_STRING = - "Failing evaluation because of invalid BusinessPartnerNumber constraint. For operator 'EQ' right value must be of type 'String'. Unsupported type: '%s'"; - private static final String FAIL_EVALUATION_BECAUSE_UNSUPPORTED_OPERATOR = - "Failing evaluation because of invalid BusinessPartnerNumber constraint. As operator only 'EQ' is supported. Unsupported operator: '%s'"; - /** - * Name of the claim that contains the Business Partner Number. - * - *

    Please note: At the time of writing (April 2022) the business partner - * number is part of the 'referringConnector' claim in the IDS DAT token. This will probably - * change for the next release. - */ - private static final String REFERRING_CONNECTOR_CLAIM = "referringConnector"; - private final Monitor monitor; - private final boolean logAgreementEvaluation; - - protected AbstractBusinessPartnerValidation(Monitor monitor, boolean logAgreementEvaluation) { - this.monitor = Objects.requireNonNull(monitor); - this.logAgreementEvaluation = logAgreementEvaluation; - } - - public boolean isLogAgreementEvaluation() { - return logAgreementEvaluation; - } - - /** - * Evaluation funtion to decide whether a claim belongs to a specific business partner. - * - * @param operator operator of the constraint - * @param rightValue right value fo the constraint, that contains the business partner number - * (e.g. BPNLCDQ90000X42KU) - * @param policyContext context of the policy with claims - * @return true if claims are from the constrained business partner - */ - public boolean evaluate(Operator operator, Object rightValue, PolicyContext policyContext) { - - monitor.warning("This policy evaluation function (class [%s]) was deprecated and is scheduled for removal in version 0.6.0 of Tractus-X EDC".formatted(getClass().getSimpleName())); - - if (policyContext.hasProblems() && !policyContext.getProblems().isEmpty()) { - var problems = String.join(", ", policyContext.getProblems()); - var message = - format( - "BusinessPartnerNumberValidation: Rejecting PolicyContext with problems. Problems: %s", - problems); - monitor.debug(message); - return false; - } - - var participantAgent = policyContext.getContextData(ParticipantAgent.class); - - if (participantAgent == null) { - return false; - } - var referringConnectorClaim = getReferringConnectorClaim(participantAgent); - - if (referringConnectorClaim == null || referringConnectorClaim.isEmpty()) { - return false; - } - - if (operator == Operator.EQ) { - return isBusinessPartnerNumber(referringConnectorClaim, rightValue, policyContext); - } else { - var message = format(FAIL_EVALUATION_BECAUSE_UNSUPPORTED_OPERATOR, operator); - monitor.warning(message); - policyContext.reportProblem(message); - return false; - } - } - - /** - * At the time of writing (11. April 2022) the business partner number is part of the - * 'referringConnector' claim, which contains a connector URL. As the CX projects are not further - * aligned about the URL formatting, the enforcement can only be done by checking whether the URL - * _contains_ the number. As this introduces some insecurities when validation business partner - * numbers, this should be addresses in the long term. - * - * @param referringConnectorClaim describing URL with business partner number - * @param businessPartnerNumber of the constraint - * @return true if claim contains the business partner number - */ - private static boolean isCorrectBusinessPartner(String referringConnectorClaim, String businessPartnerNumber) { - return referringConnectorClaim.contains(businessPartnerNumber); - } - - @Nullable - private String getReferringConnectorClaim(ParticipantAgent participantAgent) { - String referringConnectorClaim = null; - var claims = participantAgent.getClaims(); - - var referringConnectorClaimObject = claims.get(REFERRING_CONNECTOR_CLAIM); - - if (referringConnectorClaimObject instanceof String) { - referringConnectorClaim = (String) referringConnectorClaimObject; - } - if (referringConnectorClaim == null) { - referringConnectorClaim = participantAgent.getIdentity(); - } - - return referringConnectorClaim; - } - - private boolean isBusinessPartnerNumber(String referringConnectorClaim, Object businessPartnerNumber, PolicyContext policyContext) { - if (businessPartnerNumber == null) { - var message = format(FAIL_EVALUATION_BECAUSE_RIGHT_VALUE_NOT_STRING, "null"); - monitor.warning(message); - policyContext.reportProblem(message); - return false; - } - if (!(businessPartnerNumber instanceof String businessPartnerNumberStr)) { - var message = - format( - FAIL_EVALUATION_BECAUSE_RIGHT_VALUE_NOT_STRING, - businessPartnerNumber.getClass().getName()); - monitor.warning(message); - policyContext.reportProblem(message); - return false; - } - - var agreement = policyContext.getContextData(ContractAgreement.class); - var isCorrectBusinessPartner = isCorrectBusinessPartner(referringConnectorClaim, businessPartnerNumberStr); - - if (agreement != null && logAgreementEvaluation) { - monitor.info(format("Evaluated policy access for referringConnectorClaim: %s and contract id: %s with result: %s", referringConnectorClaim, agreement.getId(), isCorrectBusinessPartner)); - } - return isCorrectBusinessPartner; - } -} diff --git a/edc-extensions/bpn-validation/bpn-validation-core/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/legacy/BusinessPartnerDutyFunction.java b/edc-extensions/bpn-validation/bpn-validation-core/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/legacy/BusinessPartnerDutyFunction.java deleted file mode 100644 index 1b8377809..000000000 --- a/edc-extensions/bpn-validation/bpn-validation-core/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/legacy/BusinessPartnerDutyFunction.java +++ /dev/null @@ -1,45 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.validation.businesspartner.functions.legacy; - -import org.eclipse.edc.policy.engine.spi.AtomicConstraintFunction; -import org.eclipse.edc.policy.engine.spi.PolicyContext; -import org.eclipse.edc.policy.model.Duty; -import org.eclipse.edc.policy.model.Operator; -import org.eclipse.edc.spi.monitor.Monitor; - -/** - * AtomicConstraintFunction to validate business partner numbers for edc duties. - * - * @deprecated Please use {@code BusinessPartnerGroupFunction} instead - */ -@Deprecated(forRemoval = true, since = "0.5.0") -public class BusinessPartnerDutyFunction extends AbstractBusinessPartnerValidation - implements AtomicConstraintFunction { - - public BusinessPartnerDutyFunction(Monitor monitor, boolean shouldLogOnAgreementEvaluation) { - super(monitor, shouldLogOnAgreementEvaluation); - } - - @Override - public boolean evaluate(Operator operator, Object rightValue, Duty rule, PolicyContext context) { - return evaluate(operator, rightValue, context); - } -} diff --git a/edc-extensions/bpn-validation/bpn-validation-core/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/legacy/BusinessPartnerPermissionFunction.java b/edc-extensions/bpn-validation/bpn-validation-core/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/legacy/BusinessPartnerPermissionFunction.java deleted file mode 100644 index c357af43c..000000000 --- a/edc-extensions/bpn-validation/bpn-validation-core/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/legacy/BusinessPartnerPermissionFunction.java +++ /dev/null @@ -1,45 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.validation.businesspartner.functions.legacy; - -import org.eclipse.edc.policy.engine.spi.AtomicConstraintFunction; -import org.eclipse.edc.policy.engine.spi.PolicyContext; -import org.eclipse.edc.policy.model.Operator; -import org.eclipse.edc.policy.model.Permission; -import org.eclipse.edc.spi.monitor.Monitor; - -/** - * AtomicConstraintFunction to validate business partner numbers for edc permissions. - * - * @deprecated Please use {@code BusinessPartnerGroupFunction} instead - */ -@Deprecated(forRemoval = true, since = "0.5.0") -public class BusinessPartnerPermissionFunction extends AbstractBusinessPartnerValidation - implements AtomicConstraintFunction { - - public BusinessPartnerPermissionFunction(Monitor monitor, boolean shouldLogOnAgreementEvaluation) { - super(monitor, shouldLogOnAgreementEvaluation); - } - - @Override - public boolean evaluate(Operator operator, Object rightValue, Permission rule, PolicyContext context) { - return evaluate(operator, rightValue, context); - } -} diff --git a/edc-extensions/bpn-validation/bpn-validation-core/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/legacy/BusinessPartnerProhibitionFunction.java b/edc-extensions/bpn-validation/bpn-validation-core/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/legacy/BusinessPartnerProhibitionFunction.java deleted file mode 100644 index cc9b4ac8a..000000000 --- a/edc-extensions/bpn-validation/bpn-validation-core/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/legacy/BusinessPartnerProhibitionFunction.java +++ /dev/null @@ -1,45 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.validation.businesspartner.functions.legacy; - -import org.eclipse.edc.policy.engine.spi.AtomicConstraintFunction; -import org.eclipse.edc.policy.engine.spi.PolicyContext; -import org.eclipse.edc.policy.model.Operator; -import org.eclipse.edc.policy.model.Prohibition; -import org.eclipse.edc.spi.monitor.Monitor; - -/** - * AtomicConstraintFunction to validate business partner numbers for edc prohibitions. - * - * @deprecated Please use {@code BusinessPartnerGroupFunction} instead - */ -@Deprecated(forRemoval = true, since = "0.5.0") -public class BusinessPartnerProhibitionFunction extends AbstractBusinessPartnerValidation - implements AtomicConstraintFunction { - - public BusinessPartnerProhibitionFunction(Monitor monitor, boolean shouldLogOnAgreementEvaluation) { - super(monitor, shouldLogOnAgreementEvaluation); - } - - @Override - public boolean evaluate(Operator operator, Object rightValue, Prohibition rule, PolicyContext context) { - return evaluate(operator, rightValue, context); - } -} diff --git a/edc-extensions/bpn-validation/bpn-validation-core/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension b/edc-extensions/bpn-validation/bpn-validation-core/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension index e741abd6a..f3e2b4cbc 100644 --- a/edc-extensions/bpn-validation/bpn-validation-core/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension +++ b/edc-extensions/bpn-validation/bpn-validation-core/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension @@ -20,4 +20,4 @@ org.eclipse.tractusx.edc.validation.businesspartner.BusinessPartnerValidationExtension org.eclipse.tractusx.edc.validation.businesspartner.defaults.DefaultStoreProviderExtension -org.eclipse.tractusx.edc.validation.businesspartner.LegacyBusinessPartnerValidationExtension +org.eclipse.tractusx.edc.validation.businesspartner.BusinessPartnerNumberValidationExtension diff --git a/edc-extensions/bpn-validation/bpn-validation-core/src/test/java/org/eclipse/tractusx/edc/validation/businesspartner/BusinessPartnerNumberValidationExtensionTest.java b/edc-extensions/bpn-validation/bpn-validation-core/src/test/java/org/eclipse/tractusx/edc/validation/businesspartner/BusinessPartnerNumberValidationExtensionTest.java new file mode 100644 index 000000000..f3d6fa3a8 --- /dev/null +++ b/edc-extensions/bpn-validation/bpn-validation-core/src/test/java/org/eclipse/tractusx/edc/validation/businesspartner/BusinessPartnerNumberValidationExtensionTest.java @@ -0,0 +1,83 @@ +/******************************************************************************** + * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +package org.eclipse.tractusx.edc.validation.businesspartner; + +import org.eclipse.edc.junit.extensions.DependencyInjectionExtension; +import org.eclipse.edc.policy.engine.spi.PolicyEngine; +import org.eclipse.edc.policy.engine.spi.RuleBindingRegistry; +import org.eclipse.edc.policy.model.Permission; +import org.eclipse.edc.spi.system.ServiceExtensionContext; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; + +import static org.eclipse.tractusx.edc.validation.businesspartner.BusinessPartnerNumberValidationExtension.BUSINESS_PARTNER_CONSTRAINT_KEY; +import static org.eclipse.tractusx.edc.validation.businesspartner.BusinessPartnerNumberValidationExtension.TX_BUSINESS_PARTNER_CONSTRAINT_KEY; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +@ExtendWith(DependencyInjectionExtension.class) +class BusinessPartnerNumberValidationExtensionTest { + + private final PolicyEngine policyEngine = mock(); + private final RuleBindingRegistry ruleBindingRegistry = mock(); + + @BeforeEach + void setup(ServiceExtensionContext context) { + context.registerService(PolicyEngine.class, policyEngine); + context.registerService(RuleBindingRegistry.class, ruleBindingRegistry); + } + + @Test + void testRegisterPermissionFunction(ServiceExtensionContext context, BusinessPartnerNumberValidationExtension extension) { + + // invoke + extension.initialize(context); + + // verify + verify(policyEngine, times(3)) + .registerFunction( + anyString(), + eq(Permission.class), + eq(BUSINESS_PARTNER_CONSTRAINT_KEY), + any()); + + // verify + verify(policyEngine, times(3)) + .registerFunction( + anyString(), + eq(Permission.class), + eq(TX_BUSINESS_PARTNER_CONSTRAINT_KEY), + any()); + + verify(ruleBindingRegistry, times(3)) + .bind(eq(BUSINESS_PARTNER_CONSTRAINT_KEY), + anyString()); + + verify(ruleBindingRegistry, times(3)) + .bind(eq(TX_BUSINESS_PARTNER_CONSTRAINT_KEY), + anyString()); + } + +} diff --git a/edc-extensions/bpn-validation/bpn-validation-core/src/test/java/org/eclipse/tractusx/edc/validation/businesspartner/LegacyBusinessPartnerValidationExtensionTest.java b/edc-extensions/bpn-validation/bpn-validation-core/src/test/java/org/eclipse/tractusx/edc/validation/businesspartner/LegacyBusinessPartnerValidationExtensionTest.java deleted file mode 100644 index 1ffdf61c4..000000000 --- a/edc-extensions/bpn-validation/bpn-validation-core/src/test/java/org/eclipse/tractusx/edc/validation/businesspartner/LegacyBusinessPartnerValidationExtensionTest.java +++ /dev/null @@ -1,130 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.validation.businesspartner; - -import org.eclipse.edc.policy.engine.spi.PolicyEngine; -import org.eclipse.edc.policy.engine.spi.RuleBindingRegistry; -import org.eclipse.edc.policy.model.Duty; -import org.eclipse.edc.policy.model.Permission; -import org.eclipse.edc.policy.model.Prohibition; -import org.eclipse.edc.spi.monitor.Monitor; -import org.eclipse.edc.spi.system.ServiceExtensionContext; -import org.eclipse.tractusx.edc.validation.businesspartner.functions.legacy.BusinessPartnerPermissionFunction; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.mockito.ArgumentCaptor; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -class LegacyBusinessPartnerValidationExtensionTest { - - private LegacyBusinessPartnerValidationExtension extension; - - // mocks - private ServiceExtensionContext serviceExtensionContext; - private PolicyEngine policyEngine; - private RuleBindingRegistry ruleBindingRegistry; - - @BeforeEach - void setup() { - - policyEngine = mock(PolicyEngine.class); - ruleBindingRegistry = mock(RuleBindingRegistry.class); - - var monitor = mock(Monitor.class); - serviceExtensionContext = mock(ServiceExtensionContext.class); - - when(serviceExtensionContext.getMonitor()).thenReturn(monitor); - - extension = new LegacyBusinessPartnerValidationExtension(ruleBindingRegistry, policyEngine); - } - - @Test - void testRegisterDutyFunction() { - - // invoke - extension.initialize(serviceExtensionContext); - - // verify - verify(policyEngine, times(3)) - .registerFunction( - anyString(), - eq(Duty.class), - eq(LegacyBusinessPartnerValidationExtension.BUSINESS_PARTNER_CONSTRAINT_KEY), - any()); - } - - @Test - void testRegisterPermissionFunction() { - - // invoke - extension.initialize(serviceExtensionContext); - - // verify - verify(policyEngine, times(3)) - .registerFunction( - anyString(), - eq(Permission.class), - eq(LegacyBusinessPartnerValidationExtension.BUSINESS_PARTNER_CONSTRAINT_KEY), - any()); - } - - @Test - void testRegisterProhibitionFunction() { - - // invoke - extension.initialize(serviceExtensionContext); - - // verify - verify(policyEngine, times(3)) - .registerFunction( - anyString(), - eq(Prohibition.class), - eq(LegacyBusinessPartnerValidationExtension.BUSINESS_PARTNER_CONSTRAINT_KEY), - any()); - } - - @Test - void testLogConfiguration() { - - when(serviceExtensionContext.getSetting(LegacyBusinessPartnerValidationExtension.BUSINESS_PARTNER_VALIDATION_LOG_AGREEMENT_VALIDATION, "true")).thenReturn("false"); - - var captor = ArgumentCaptor.forClass(BusinessPartnerPermissionFunction.class); - // invoke - extension.initialize(serviceExtensionContext); - - // verify - verify(policyEngine, times(3)) - .registerFunction( - anyString(), - eq(Permission.class), - eq(LegacyBusinessPartnerValidationExtension.BUSINESS_PARTNER_CONSTRAINT_KEY), - captor.capture()); - - assertThat(captor.getValue().isLogAgreementEvaluation()).isFalse(); - } -} diff --git a/edc-extensions/bpn-validation/bpn-validation-core/src/test/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/AbstractBusinessPartnerValidationTest.java b/edc-extensions/bpn-validation/bpn-validation-core/src/test/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/AbstractBusinessPartnerValidationTest.java deleted file mode 100644 index b330f1074..000000000 --- a/edc-extensions/bpn-validation/bpn-validation-core/src/test/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/AbstractBusinessPartnerValidationTest.java +++ /dev/null @@ -1,210 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.validation.businesspartner.functions; - -import org.eclipse.edc.policy.engine.spi.PolicyContext; -import org.eclipse.edc.policy.model.Operator; -import org.eclipse.edc.policy.model.Policy; -import org.eclipse.edc.spi.agent.ParticipantAgent; -import org.eclipse.edc.spi.monitor.Monitor; -import org.eclipse.edc.spi.types.domain.agreement.ContractAgreement; -import org.eclipse.tractusx.edc.validation.businesspartner.functions.legacy.AbstractBusinessPartnerValidation; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.EnumSource; -import org.mockito.ArgumentCaptor; -import org.mockito.Mockito; - -import java.util.Collections; -import java.util.List; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.eq; - -class AbstractBusinessPartnerValidationTest { - - private AbstractBusinessPartnerValidation validation; - - // mocks - private Monitor monitor; - private PolicyContext policyContext; - private ParticipantAgent participantAgent; - - @BeforeEach - void beforeEach() { - this.monitor = Mockito.mock(Monitor.class); - this.policyContext = Mockito.mock(PolicyContext.class); - this.participantAgent = Mockito.mock(ParticipantAgent.class); - - Mockito.when(policyContext.getContextData(eq(ParticipantAgent.class))).thenReturn(participantAgent); - - validation = new AbstractBusinessPartnerValidation(monitor, true) { - }; - } - - @ParameterizedTest - @EnumSource(Operator.class) - void testFailsOnUnsupportedOperations(Operator operator) { - - if (operator == Operator.EQ) { // only allowed operator - return; - } - - // prepare - prepareContextProblems(null); - prepareBusinessPartnerClaim("yes"); - - // invoke & assert - Assertions.assertFalse(validation.evaluate(operator, "foo", policyContext)); - } - - @Test - void testFailsOnUnsupportedRightValue() { - - // prepare - prepareContextProblems(null); - prepareBusinessPartnerClaim("yes"); - - // invoke & assert - Assertions.assertFalse(validation.evaluate(Operator.EQ, 1, policyContext)); - } - - @Test - void testValidationFailsWhenClaimMissing() { - - // prepare - prepareContextProblems(null); - - // invoke - final boolean isValid = validation.evaluate(Operator.EQ, "foo", policyContext); - - // assert - Assertions.assertFalse(isValid); - } - - @Test - void testValidationSucceedsWhenClaimContainsValue() { - - // prepare - prepareContextProblems(null); - - // prepare equals - prepareBusinessPartnerClaim("foo"); - final boolean isEqualsTrue = validation.evaluate(Operator.EQ, "foo", policyContext); - - // prepare contains - prepareBusinessPartnerClaim("foobar"); - final boolean isContainedTrue = validation.evaluate(Operator.EQ, "foo", policyContext); - - // assert - Assertions.assertTrue(isEqualsTrue); - Assertions.assertTrue(isContainedTrue); - } - - @Test - void testValidationWhenParticipantHasProblems() { - - // prepare - prepareContextProblems(Collections.singletonList("big problem")); - prepareBusinessPartnerClaim("foo"); - - // invoke - final boolean isValid = validation.evaluate(Operator.EQ, "foo", policyContext); - - // Mockito.verify(monitor.debug(Mockito.anyString()); - Assertions.assertFalse(isValid); - } - - @Test - void testValidationWhenSingleParticipantIsValid() { - - // prepare - prepareContextProblems(null); - prepareBusinessPartnerClaim("foo"); - - // invoke - final boolean isContainedTrue = validation.evaluate(Operator.EQ, "foo", policyContext); - - // Mockito.verify(monitor.debug(Mockito.anyString()); - Assertions.assertTrue(isContainedTrue); - } - - @Test - void testValidationWhenSingleParticipantIsValidWithAgreement() { - - // prepare - prepareContextProblems(null); - prepareBusinessPartnerClaim("foo"); - - var captor = ArgumentCaptor.forClass(String.class); - - var agreement = ContractAgreement.Builder.newInstance() - .id("agreementId") - .providerId("provider") - .consumerId("consumer") - .assetId("assetId") - .policy(Policy.Builder.newInstance().build()) - .build(); - - Mockito.when(policyContext.getContextData(eq(ContractAgreement.class))).thenReturn(agreement); - - // invoke - final boolean isContainedTrue = validation.evaluate(Operator.EQ, "foo", policyContext); - - Assertions.assertTrue(isContainedTrue); - - Mockito.verify(monitor).info(captor.capture()); - - assertThat(captor.getValue()).contains(agreement.getId()).contains("foo"); - } - - // In the past it was possible to use the 'IN' constraint with multiple BPNs as - // a list. This is no longer supported. - // The EDC must now always decline this kind of BPN format. - @Test - void testValidationForMultipleParticipants() { - - // prepare - prepareContextProblems(null); - prepareBusinessPartnerClaim("foo"); - - // invoke & verify - Assertions.assertFalse(validation.evaluate(Operator.IN, List.of("foo", "bar"), policyContext)); - Assertions.assertFalse(validation.evaluate(Operator.IN, List.of(1, "foo"), policyContext)); - Assertions.assertFalse(validation.evaluate(Operator.IN, List.of("bar", "bar"), policyContext)); - } - - private void prepareContextProblems(List problems) { - Mockito.when(policyContext.getProblems()).thenReturn(problems); - - if (problems == null || problems.isEmpty()) { - Mockito.when(policyContext.hasProblems()).thenReturn(false); - } else { - Mockito.when(policyContext.hasProblems()).thenReturn(true); - } - } - - private void prepareBusinessPartnerClaim(String businessPartnerNumber) { - Mockito.when(participantAgent.getClaims()) - .thenReturn(Collections.singletonMap("referringConnector", businessPartnerNumber)); - } -} diff --git a/edc-extensions/bpn-validation/bpn-validation-core/src/test/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/BusinessPartnerGroupFunctionTest.java b/edc-extensions/bpn-validation/bpn-validation-core/src/test/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/BusinessPartnerGroupFunctionTest.java index c318ca7ee..0d982037c 100644 --- a/edc-extensions/bpn-validation/bpn-validation-core/src/test/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/BusinessPartnerGroupFunctionTest.java +++ b/edc-extensions/bpn-validation/bpn-validation-core/src/test/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/BusinessPartnerGroupFunctionTest.java @@ -53,8 +53,8 @@ import static org.eclipse.edc.policy.model.Operator.LEQ; import static org.eclipse.edc.policy.model.Operator.LT; import static org.eclipse.edc.policy.model.Operator.NEQ; +import static org.eclipse.edc.spi.agent.ParticipantAgent.PARTICIPANT_IDENTITY; import static org.eclipse.tractusx.edc.validation.businesspartner.functions.BusinessPartnerGroupFunction.BUSINESS_PARTNER_CONSTRAINT_KEY; -import static org.eclipse.tractusx.edc.validation.businesspartner.functions.BusinessPartnerGroupFunction.REFERRING_CONNECTOR_CLAIM; import static org.mockito.ArgumentMatchers.endsWith; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; @@ -97,8 +97,8 @@ void evaluate_invalidOperator(Operator invalidOperator) { @Test @DisplayName("Right-hand operand is not String or Collection") void evaluate_rightOperandNotStringOrCollection() { - when(context.getContextData(eq(ParticipantAgent.class))).thenReturn(new ParticipantAgent(Map.of(REFERRING_CONNECTOR_CLAIM, TEST_BPN), Map.of())); when(store.resolveForBpn(TEST_BPN)).thenReturn(StoreResult.success(List.of("test-group"))); + when(context.getContextData(eq(ParticipantAgent.class))).thenReturn(new ParticipantAgent(Map.of(), Map.of(PARTICIPANT_IDENTITY, TEST_BPN))); assertThat(function.evaluate(EQ, 42, createPermission(EQ, List.of("test-group")), context)).isFalse(); assertThat(function.evaluate(EQ, 42L, createPermission(EQ, List.of("test-group")), context)).isFalse(); @@ -117,7 +117,7 @@ void evaluate_rightOperandNotStringOrCollection() { void evaluate_validOperator(String ignored, Operator operator, List assignedBpn, boolean expectedOutcome) { var allowedGroups = List.of(TEST_GROUP_1, TEST_GROUP_2); - when(context.getContextData(eq(ParticipantAgent.class))).thenReturn(new ParticipantAgent(Map.of(REFERRING_CONNECTOR_CLAIM, TEST_BPN), Map.of())); + when(context.getContextData(eq(ParticipantAgent.class))).thenReturn(new ParticipantAgent(Map.of(), Map.of(PARTICIPANT_IDENTITY, TEST_BPN))); when(store.resolveForBpn(TEST_BPN)).thenReturn(StoreResult.success(assignedBpn)); assertThat(function.evaluate(operator, allowedGroups, createPermission(operator, allowedGroups), context)).isEqualTo(expectedOutcome); } @@ -126,7 +126,7 @@ void evaluate_validOperator(String ignored, Operator operator, List assi void evaluate_noEntryForBpn() { var operator = NEQ; var allowedGroups = List.of(TEST_GROUP_1, TEST_GROUP_2); - when(context.getContextData(eq(ParticipantAgent.class))).thenReturn(new ParticipantAgent(Map.of(REFERRING_CONNECTOR_CLAIM, TEST_BPN), Map.of())); + when(context.getContextData(eq(ParticipantAgent.class))).thenReturn(new ParticipantAgent(Map.of(), Map.of(PARTICIPANT_IDENTITY, TEST_BPN))); when(store.resolveForBpn(TEST_BPN)).thenReturn(StoreResult.notFound("foobar")); assertThat(function.evaluate(operator, allowedGroups, createPermission(operator, allowedGroups), context)).isFalse(); @@ -136,7 +136,7 @@ void evaluate_noEntryForBpn() { void evaluate_noGroupsAssignedToBpn() { var operator = NEQ; var allowedGroups = List.of(TEST_GROUP_1, TEST_GROUP_2); - when(context.getContextData(eq(ParticipantAgent.class))).thenReturn(new ParticipantAgent(Map.of(REFERRING_CONNECTOR_CLAIM, TEST_BPN), Map.of())); + when(context.getContextData(eq(ParticipantAgent.class))).thenReturn(new ParticipantAgent(Map.of(), Map.of(PARTICIPANT_IDENTITY, TEST_BPN))); when(store.resolveForBpn(TEST_BPN)).thenReturn(StoreResult.success(Collections.emptyList())); assertThat(function.evaluate(operator, allowedGroups, createPermission(operator, allowedGroups), context)).isFalse(); diff --git a/edc-extensions/bpn-validation/bpn-validation-core/src/test/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/BusinessPartnerNumberPermissionFunctionTest.java b/edc-extensions/bpn-validation/bpn-validation-core/src/test/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/BusinessPartnerNumberPermissionFunctionTest.java new file mode 100644 index 000000000..67cff19fa --- /dev/null +++ b/edc-extensions/bpn-validation/bpn-validation-core/src/test/java/org/eclipse/tractusx/edc/validation/businesspartner/functions/BusinessPartnerNumberPermissionFunctionTest.java @@ -0,0 +1,111 @@ +/******************************************************************************** + * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +package org.eclipse.tractusx.edc.validation.businesspartner.functions; + +import org.eclipse.edc.policy.engine.spi.PolicyContext; +import org.eclipse.edc.policy.model.Operator; +import org.eclipse.edc.policy.model.Permission; +import org.eclipse.edc.spi.agent.ParticipantAgent; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.EnumSource; + +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.mockito.ArgumentMatchers.argThat; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +class BusinessPartnerNumberPermissionFunctionTest { + + private BusinessPartnerNumberPermissionFunction validation; + + private PolicyContext policyContext; + private ParticipantAgent participantAgent; + + private Permission permission = mock(); + + @BeforeEach + void beforeEach() { + this.policyContext = mock(PolicyContext.class); + this.participantAgent = mock(ParticipantAgent.class); + + when(policyContext.getContextData(eq(ParticipantAgent.class))).thenReturn(participantAgent); + + validation = new BusinessPartnerNumberPermissionFunction() { + }; + } + + @ParameterizedTest + @EnumSource(Operator.class) + void testFailsOnUnsupportedOperations(Operator operator) { + if (operator == Operator.EQ) { // only allowed operator + return; + } + assertFalse(validation.evaluate(operator, "foo", permission, policyContext)); + verify(policyContext).reportProblem(argThat(message -> message.contains("As operator only 'EQ' is supported"))); + } + + @Test + void testFailsOnUnsupportedRightValue() { + when(participantAgent.getIdentity()).thenReturn("foo"); + assertFalse(validation.evaluate(Operator.EQ, 1, permission, policyContext)); + verify(policyContext).reportProblem(argThat(message -> message.contains("Invalid right operand value: expected 'String' but got"))); + } + + @Test + void testValidationFailsIdentityIsMissing() { + assertThat(validation.evaluate(Operator.EQ, "foo", permission, policyContext)).isFalse(); + verify(policyContext).reportProblem(argThat(message -> message.contains("Identity of the participant agent cannot be null"))); + } + + @Test + void testValidationFailsParticipantAgentMissing() { + var context = mock(PolicyContext.class); + assertThat(validation.evaluate(Operator.EQ, "foo", permission, context)).isFalse(); + verify(context).reportProblem(argThat(message -> message.contains("Required PolicyContext data not found"))); + } + + @Test + void testValidationWhenSingleParticipantIsValid() { + when(participantAgent.getIdentity()).thenReturn("foo"); + assertThat(validation.evaluate(Operator.EQ, "foo", permission, policyContext)).isTrue(); + } + + @Test + void testValidationFailsInvalidIdentity() { + when(participantAgent.getIdentity()).thenReturn("bar"); + assertThat(validation.evaluate(Operator.EQ, "foo", permission, policyContext)).isFalse(); + verify(policyContext).reportProblem(argThat(message -> message.contains("Identity of the participant not matching the expected one: foo"))); + } + + @Test + void testValidationForMultipleParticipants() { + + assertFalse(validation.evaluate(Operator.IN, List.of("foo", "bar"), permission, policyContext)); + assertFalse(validation.evaluate(Operator.IN, List.of(1, "foo"), permission, policyContext)); + assertFalse(validation.evaluate(Operator.IN, List.of("bar", "bar"), permission, policyContext)); + } +} From 08bd745a4d1da3d1b6364c93a076871c6ff06ee6 Mon Sep 17 00:00:00 2001 From: Paul Latzelsperger <43503240+paullatzelsperger@users.noreply.github.com> Date: Wed, 21 Feb 2024 14:24:37 +0100 Subject: [PATCH 025/100] feat: register CX Policy Functions (#1075) * register new policy eval functions + e2e tests * register new policy eval functions + e2e tests * add e2e tests * add negative tests * fix tests * DEPENDENCIES * fixed test * revert policy helper fct * DEPENDENCIES, disabled MIW e2e tests * disable tests involving MIW * re-enable MIW tests * rename cx-policy -> cx-policy-legacy * add new module for new CX policy functions --- .github/workflows/verify.yaml | 4 +- DEPENDENCIES | 340 ++++++++---------- .../edc-controlplane-base/build.gradle.kts | 2 +- .../cx-policy-legacy/build.gradle.kts | 33 ++ .../edc/policy/cx/CxPolicyExtension.java | 55 +++ ...ctDynamicCredentialConstraintFunction.java | 80 +++++ .../common/AbstractVpConstraintFunction.java | 0 .../cx/common/CredentialTypePredicate.java | 21 +- .../edc/policy/cx/common/PolicyScopes.java | 33 ++ .../cx/summary/SummaryConstraintFunction.java | 0 .../SummaryConstraintFunctionsProvider.java | 0 .../summary/SummaryTokenPolicyFunction.java | 0 ...rg.eclipse.edc.spi.system.ServiceExtension | 21 ++ .../edc/policy/cx/CredentialFunctions.java | 90 +++++ .../AbstractVpConstraintFunctionTest.java | 0 .../SummaryConstraintFunctionTest.java | 0 ...ummaryConstraintFunctionsProviderTest.java | 0 .../SummaryTokenPolicyFunctionTest.java | 0 .../edc/policy/cx/CxPolicyExtension.java | 5 +- .../edc/policy/cx/CxPolicyRegistration.java | 68 ++++ .../cx/common/CredentialTypePredicate.java | 2 +- ...ismantlerCredentialConstraintFunction.java | 54 ++- ...AgreementCredentialConstraintFunction.java | 23 +- ...embershipCredentialConstraintFunction.java | 12 +- .../edc/policy/cx/CredentialFunctions.java | 22 +- .../DismantlerConstraintFunctionTest.java | 105 +++--- ...meworkAgreementConstraintFunctionTest.java | 51 +-- .../MembershipConstraintFunctionTest.java | 22 +- .../iatp/scope/CredentialScopeExtractor.java | 42 ++- .../scope/CredentialScopeExtractorTest.java | 2 +- edc-tests/e2e-tests/build.gradle.kts | 1 + .../edc/helpers/IatpHelperFunctions.java | 7 +- .../edc/helpers/PolicyHelperFunctions.java | 91 +++-- .../lifecycle/tx/iatp/DataspaceIssuer.java | 23 +- ...AbstractHttpConsumerPullWithProxyTest.java | 2 +- ...HttpConsumerPullWithProxyInMemoryTest.java | 4 +- ...HttpConsumerPullWithProxyInMemoryTest.java | 144 +++++++- .../dataplane/transfer/test/S3ToS3Test.java | 4 +- .../edc/iatp/CredentialsJsonLdExtension.java | 4 +- .../edc/iatp/ih/IdentityHubExtension.java | 4 +- .../ih/TxScopeToCriterionTransformer.java | 16 +- .../edc/iatp/policy/IdentityExtractor.java | 2 +- .../resources/cx-credentials-context.json | 88 +++-- .../build.gradle.kts | 2 +- .../runtime-memory-iatp-ih/build.gradle.kts | 3 +- .../iatp/runtime-memory-sts/build.gradle.kts | 2 +- .../runtime-memory-ssi/build.gradle.kts | 2 +- .../runtime/runtime-memory/build.gradle.kts | 2 +- .../build.gradle.kts | 2 +- .../runtime-postgresql/build.gradle.kts | 2 +- gradle/libs.versions.toml | 2 +- settings.gradle.kts | 1 + .../tractusx/edc/edr/spi/CoreConstants.java | 6 +- .../ssi/spi/jsonld/CredentialsNamespaces.java | 2 +- 54 files changed, 1032 insertions(+), 471 deletions(-) create mode 100644 edc-extensions/cx-policy-legacy/build.gradle.kts create mode 100644 edc-extensions/cx-policy-legacy/src/main/java/org/eclipse/tractusx/edc/policy/cx/CxPolicyExtension.java create mode 100644 edc-extensions/cx-policy-legacy/src/main/java/org/eclipse/tractusx/edc/policy/cx/common/AbstractDynamicCredentialConstraintFunction.java rename edc-extensions/{cx-policy => cx-policy-legacy}/src/main/java/org/eclipse/tractusx/edc/policy/cx/common/AbstractVpConstraintFunction.java (100%) rename edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/IatpFrameworkAgreementHttpConsumerPullWithProxyInMemoryTest.java => edc-extensions/cx-policy-legacy/src/main/java/org/eclipse/tractusx/edc/policy/cx/common/CredentialTypePredicate.java (59%) create mode 100644 edc-extensions/cx-policy-legacy/src/main/java/org/eclipse/tractusx/edc/policy/cx/common/PolicyScopes.java rename edc-extensions/{cx-policy => cx-policy-legacy}/src/main/java/org/eclipse/tractusx/edc/policy/cx/summary/SummaryConstraintFunction.java (100%) rename edc-extensions/{cx-policy => cx-policy-legacy}/src/main/java/org/eclipse/tractusx/edc/policy/cx/summary/SummaryConstraintFunctionsProvider.java (100%) rename edc-extensions/{cx-policy => cx-policy-legacy}/src/main/java/org/eclipse/tractusx/edc/policy/cx/summary/SummaryTokenPolicyFunction.java (100%) create mode 100644 edc-extensions/cx-policy-legacy/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension create mode 100644 edc-extensions/cx-policy-legacy/src/test/java/org/eclipse/tractusx/edc/policy/cx/CredentialFunctions.java rename edc-extensions/{cx-policy => cx-policy-legacy}/src/test/java/org/eclipse/tractusx/edc/policy/cx/common/AbstractVpConstraintFunctionTest.java (100%) rename edc-extensions/{cx-policy => cx-policy-legacy}/src/test/java/org/eclipse/tractusx/edc/policy/cx/summary/SummaryConstraintFunctionTest.java (100%) rename edc-extensions/{cx-policy => cx-policy-legacy}/src/test/java/org/eclipse/tractusx/edc/policy/cx/summary/SummaryConstraintFunctionsProviderTest.java (100%) rename edc-extensions/{cx-policy => cx-policy-legacy}/src/test/java/org/eclipse/tractusx/edc/policy/cx/summary/SummaryTokenPolicyFunctionTest.java (100%) create mode 100644 edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/CxPolicyRegistration.java diff --git a/.github/workflows/verify.yaml b/.github/workflows/verify.yaml index 27510f350..c2d7ff1cd 100644 --- a/.github/workflows/verify.yaml +++ b/.github/workflows/verify.yaml @@ -155,11 +155,9 @@ jobs: miw-integration-tests: runs-on: ubuntu-latest needs: [ verify-formatting, verify-license-headers ] - steps: - uses: actions/checkout@v4 - uses: ./.github/actions/setup-java - - uses: actions/checkout@v4 - name: Starting MIW, Keycloak and Postgres Servers run: | @@ -172,7 +170,7 @@ jobs: timeout_minutes: 5 max_attempts: 3 command: | - code=$(curl -IL -sw "%{http_code}" http://localhost:8000/api/actuator/health -o /dev/null) + code=$(curl -IL -sw "%{http_code}" http://localhost:8000/api/actuator/health -o /dev/null) if [ "$code" -ne "401" ]; then echo "MIW not ready yet, status = $code" exit 1; diff --git a/DEPENDENCIES b/DEPENDENCIES index 1e7db5335..ea2c16354 100644 --- a/DEPENDENCIES +++ b/DEPENDENCIES @@ -101,9 +101,9 @@ maven/mavencentral/dev.failsafe/failsafe/3.3.2, Apache-2.0, approved, #9268 maven/mavencentral/info.picocli/picocli/4.7.4, Apache-2.0, approved, #4365 maven/mavencentral/io.github.classgraph/classgraph/4.8.154, MIT, approved, CQ22530 maven/mavencentral/io.github.classgraph/classgraph/4.8.162, MIT, approved, CQ22530 -maven/mavencentral/io.micrometer/micrometer-commons/1.12.2, Apache-2.0 AND (Apache-2.0 AND MIT), approved, #11679 -maven/mavencentral/io.micrometer/micrometer-core/1.12.2, Apache-2.0 AND (Apache-2.0 AND MIT), approved, #11678 -maven/mavencentral/io.micrometer/micrometer-observation/1.12.2, Apache-2.0, approved, #11680 +maven/mavencentral/io.micrometer/micrometer-commons/1.12.3, Apache-2.0 AND (Apache-2.0 AND MIT), approved, #11679 +maven/mavencentral/io.micrometer/micrometer-core/1.12.3, Apache-2.0 AND (Apache-2.0 AND MIT), approved, #11678 +maven/mavencentral/io.micrometer/micrometer-observation/1.12.3, Apache-2.0, approved, #11680 maven/mavencentral/io.netty/netty-buffer/4.1.100.Final, Apache-2.0, approved, CQ21842 maven/mavencentral/io.netty/netty-buffer/4.1.101.Final, Apache-2.0, approved, CQ21842 maven/mavencentral/io.netty/netty-codec-dns/4.1.100.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 @@ -204,7 +204,6 @@ maven/mavencentral/net.minidev/json-smart/2.5.0, Apache-2.0, approved, clearlyde maven/mavencentral/net.sf.saxon/Saxon-HE/12.3, MPL-2.0-no-copyleft-exception AND (LicenseRef-scancode-proprietary-license AND MPL-2.0-no-copyleft-exception) AND (MPL-2.0-no-copyleft-exception AND X11) AND (MIT AND MPL-2.0-no-copyleft-exception) AND (MPL-1.0 AND MPL-2.0-no-copyleft-exception) AND (Apache-2.0 AND MPL-2.0-no-copyleft-exception) AND MPL-1.0, restricted, #13191 maven/mavencentral/org.antlr/antlr4-runtime/4.11.1, BSD-3-Clause, approved, clearlydefined maven/mavencentral/org.apache.commons/commons-compress/1.24.0, Apache-2.0 AND BSD-3-Clause AND bzip2-1.0.6 AND LicenseRef-Public-Domain, approved, #10368 -maven/mavencentral/org.apache.commons/commons-compress/1.25.0, Apache-2.0, approved, #11600 maven/mavencentral/org.apache.commons/commons-lang3/3.11, Apache-2.0, approved, CQ22642 maven/mavencentral/org.apache.commons/commons-lang3/3.12.0, Apache-2.0, approved, clearlydefined maven/mavencentral/org.apache.commons/commons-lang3/3.13.0, Apache-2.0, approved, #9820 @@ -248,154 +247,154 @@ maven/mavencentral/org.codehaus.plexus/plexus-container-default/2.1.0, Apache-2. maven/mavencentral/org.codehaus.plexus/plexus-utils/3.1.1, , approved, CQ16492 maven/mavencentral/org.codehaus.plexus/plexus-utils/3.3.0, , approved, CQ21066 maven/mavencentral/org.codehaus.woodstox/stax2-api/4.2.1, BSD-2-Clause, approved, #2670 -maven/mavencentral/org.eclipse.edc/api-core/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/api-observability/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/asset-api/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/asset-index-sql/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/asset-spi/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/auth-spi/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/auth-tokenbased/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/autodoc-processor/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/aws-s3-core/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/aws-s3-test/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/azure-blob-core/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/azure-test/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/boot/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/callback-event-dispatcher/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/callback-http-dispatcher/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/catalog-api/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/catalog-core/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/catalog-spi/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/configuration-filesystem/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/connector-core/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/contract-agreement-api/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/contract-core/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/contract-definition-api/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/contract-definition-store-sql/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/contract-negotiation-api/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/contract-negotiation-store-sql/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/contract-spi/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/control-api-configuration/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/control-plane-aggregate-services/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/control-plane-api-client-spi/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/control-plane-api-client/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/control-plane-api/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/control-plane-core/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/control-plane-spi/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/core-spi/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/crypto-common/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-address-http-data-spi/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-plane-aws-s3/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-plane-azure-storage/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-plane-client/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-plane-control-api/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-plane-core/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-plane-http-oauth2-core/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-plane-http-oauth2/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-plane-http-spi/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-plane-http/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-plane-public-api/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-plane-selector-core/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-plane-selector-spi/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-plane-spi/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-plane-util/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-api-configuration/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-catalog-api/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-catalog-http-dispatcher/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-catalog-transform/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-catalog/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-http-core/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-http-spi/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-negotiation-api/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-negotiation-http-dispatcher/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-negotiation-transform/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-negotiation/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-spi/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-transfer-process-api/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-transfer-process-http-dispatcher/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-transfer-process-transform/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-transfer-process/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/http-spi/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/http/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/iam-mock/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-did-core/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-did-spi/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-hub-api/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-hub-credentials/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-hub-did-spi/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-hub-did/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-hub-keypairs/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-hub-participants/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-hub-spi/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-hub-store-spi/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-trust-core/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-trust-issuers-configuration/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-trust-service/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-trust-spi/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-trust-sts-api/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-trust-sts-client-configuration/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-trust-sts-core/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-trust-sts-embedded/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-trust-sts-remote-core/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-trust-sts-remote/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-trust-sts-spi/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-trust-transform/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/jersey-core/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/jersey-micrometer/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/jersey-providers/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/jetty-core/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/jetty-micrometer/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/json-ld-spi/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/json-ld/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/junit/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/jws2020/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/jwt-spi/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/jwt-verifiable-credentials/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/ldp-verifiable-credentials/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/management-api-configuration/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/management-api-test-fixtures/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/management-api/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/micrometer-core/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/oauth2-client/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/oauth2-spi/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/policy-definition-api/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/policy-definition-store-sql/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/policy-engine-spi/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/policy-engine/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/policy-evaluator/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/policy-model/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/policy-monitor-core/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/policy-monitor-spi/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/policy-monitor-store-sql/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/policy-spi/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/runtime-metamodel/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/security/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/sql-core/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/sql-lease/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/sql-pool-apache-commons/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/state-machine/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/token-core/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/token-spi/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/transaction-datasource-spi/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/transaction-local/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/transaction-spi/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/transfer-core/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/transfer-data-plane-spi/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/transfer-data-plane/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/transfer-process-api/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/transfer-process-store-sql/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/transfer-pull-http-dynamic-receiver/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/transfer-spi/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/transform-core/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/transform-spi/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/util/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/validator-core/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/validator-data-address-http-data/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/validator-spi/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/vault-azure/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/vault-hashicorp/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/web-spi/0.5.2-20240219-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/api-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/api-observability/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/asset-api/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/asset-index-sql/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/asset-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/auth-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/auth-tokenbased/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/autodoc-processor/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/aws-s3-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/aws-s3-test/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/azure-blob-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/azure-test/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/boot/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/callback-event-dispatcher/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/callback-http-dispatcher/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/catalog-api/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/catalog-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/catalog-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/configuration-filesystem/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/connector-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/contract-agreement-api/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/contract-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/contract-definition-api/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/contract-definition-store-sql/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/contract-negotiation-api/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/contract-negotiation-store-sql/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/contract-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/control-api-configuration/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/control-plane-aggregate-services/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/control-plane-api-client-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/control-plane-api-client/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/control-plane-api/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/control-plane-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/control-plane-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/core-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/crypto-common/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-address-http-data-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-aws-s3/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-azure-storage/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-client/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-control-api/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-http-oauth2-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-http-oauth2/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-http-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-http/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-public-api/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-selector-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-selector-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-util/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-api-configuration/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-catalog-api/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-catalog-http-dispatcher/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-catalog-transform/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-catalog/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-http-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-http-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-negotiation-api/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-negotiation-http-dispatcher/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-negotiation-transform/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-negotiation/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-transfer-process-api/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-transfer-process-http-dispatcher/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-transfer-process-transform/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-transfer-process/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/http-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/http/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/iam-mock/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-did-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-did-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-hub-api/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-hub-credentials/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-hub-did-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-hub-did/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-hub-keypairs/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-hub-participants/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-hub-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-hub-store-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-trust-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-trust-issuers-configuration/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-trust-service/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-trust-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-trust-sts-api/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-trust-sts-client-configuration/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-trust-sts-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-trust-sts-embedded/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-trust-sts-remote-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-trust-sts-remote/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-trust-sts-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-trust-transform/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/jersey-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/jersey-micrometer/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/jersey-providers/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/jetty-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/jetty-micrometer/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/json-ld-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/json-ld/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/junit/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/jws2020/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/jwt-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/jwt-verifiable-credentials/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/ldp-verifiable-credentials/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/management-api-configuration/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/management-api-test-fixtures/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/management-api/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/micrometer-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/oauth2-client/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/oauth2-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/policy-definition-api/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/policy-definition-store-sql/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/policy-engine-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/policy-engine/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/policy-evaluator/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/policy-model/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/policy-monitor-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/policy-monitor-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/policy-monitor-store-sql/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/policy-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/runtime-metamodel/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/security/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/sql-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/sql-lease/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/sql-pool-apache-commons/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/state-machine/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/token-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/token-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/transaction-datasource-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/transaction-local/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/transaction-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/transfer-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/transfer-data-plane-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/transfer-data-plane/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/transfer-process-api/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/transfer-process-store-sql/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/transfer-pull-http-dynamic-receiver/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/transfer-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/transform-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/transform-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/util/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/validator-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/validator-data-address-http-data/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/validator-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/vault-azure/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/vault-hashicorp/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/web-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.jetty.toolchain/jetty-jakarta-servlet-api/5.0.2, EPL-2.0 OR Apache-2.0, approved, rt.jetty maven/mavencentral/org.eclipse.jetty.toolchain/jetty-jakarta-websocket-api/2.0.0, EPL-2.0 OR Apache-2.0, approved, rt.jetty maven/mavencentral/org.eclipse.jetty.websocket/websocket-core-client/11.0.20, EPL-2.0 OR Apache-2.0, approved, rt.jetty @@ -461,10 +460,8 @@ maven/mavencentral/org.jetbrains/annotations/24.1.0, Apache-2.0, approved, clear maven/mavencentral/org.junit-pioneer/junit-pioneer/2.2.0, EPL-2.0, approved, #11857 maven/mavencentral/org.junit.jupiter/junit-jupiter-api/5.10.1, EPL-2.0, approved, #9714 maven/mavencentral/org.junit.jupiter/junit-jupiter-api/5.10.2, EPL-2.0, approved, #9714 -maven/mavencentral/org.junit.jupiter/junit-jupiter-api/5.9.3, EPL-2.0, approved, #3133 maven/mavencentral/org.junit.jupiter/junit-jupiter-engine/5.10.1, EPL-2.0, approved, #9711 maven/mavencentral/org.junit.jupiter/junit-jupiter-engine/5.10.2, EPL-2.0, approved, #9711 -maven/mavencentral/org.junit.jupiter/junit-jupiter-engine/5.9.3, EPL-2.0, approved, #3125 maven/mavencentral/org.junit.jupiter/junit-jupiter-params/5.10.1, EPL-2.0, approved, #9708 maven/mavencentral/org.junit.jupiter/junit-jupiter-params/5.10.2, EPL-2.0, approved, #9708 maven/mavencentral/org.junit.platform/junit-platform-commons/1.10.2, EPL-2.0, approved, #9715 @@ -499,74 +496,43 @@ maven/mavencentral/org.slf4j/slf4j-api/1.7.36, MIT, approved, CQ13368 maven/mavencentral/org.slf4j/slf4j-api/1.7.7, MIT, approved, CQ9827 maven/mavencentral/org.slf4j/slf4j-api/2.0.12, MIT, approved, #5915 maven/mavencentral/org.slf4j/slf4j-api/2.0.9, MIT, approved, #5915 -maven/mavencentral/org.testcontainers/database-commons/1.19.4, Apache-2.0, approved, #10345 maven/mavencentral/org.testcontainers/database-commons/1.19.5, Apache-2.0, approved, #10345 -maven/mavencentral/org.testcontainers/jdbc/1.19.4, Apache-2.0, approved, #10348 maven/mavencentral/org.testcontainers/jdbc/1.19.5, Apache-2.0, approved, #10348 maven/mavencentral/org.testcontainers/junit-jupiter/1.19.3, MIT, approved, #10344 -maven/mavencentral/org.testcontainers/junit-jupiter/1.19.4, MIT, approved, #10344 maven/mavencentral/org.testcontainers/junit-jupiter/1.19.5, MIT, approved, #10344 -maven/mavencentral/org.testcontainers/postgresql/1.19.4, MIT, approved, #10350 maven/mavencentral/org.testcontainers/postgresql/1.19.5, MIT, approved, #10350 -maven/mavencentral/org.testcontainers/testcontainers/1.19.4, Apache-2.0 AND MIT, approved, #10347 maven/mavencentral/org.testcontainers/testcontainers/1.19.5, Apache-2.0 AND MIT, approved, #10347 maven/mavencentral/org.testcontainers/vault/1.19.5, MIT, approved, #10852 maven/mavencentral/org.xmlresolver/xmlresolver/5.2.0, Apache-2.0, approved, clearlydefined maven/mavencentral/org.yaml/snakeyaml/2.0, Apache-2.0 AND (Apache-2.0 OR BSD-3-Clause OR EPL-1.0 OR GPL-2.0-or-later OR LGPL-2.1-or-later), approved, #7275 maven/mavencentral/org.yaml/snakeyaml/2.2, Apache-2.0 AND (Apache-2.0 OR BSD-3-Clause OR EPL-1.0 OR GPL-2.0-or-later OR LGPL-2.1-or-later), approved, #10232 -maven/mavencentral/software.amazon.awssdk/annotations/2.22.9, Apache-2.0, approved, #12618 maven/mavencentral/software.amazon.awssdk/annotations/2.24.5, Apache-2.0, approved, #13251 -maven/mavencentral/software.amazon.awssdk/apache-client/2.22.9, Apache-2.0, approved, #12633 maven/mavencentral/software.amazon.awssdk/apache-client/2.24.5, Apache-2.0, approved, #13257 -maven/mavencentral/software.amazon.awssdk/arns/2.22.9, Apache-2.0, approved, #12647 maven/mavencentral/software.amazon.awssdk/arns/2.24.5, Apache-2.0, approved, #13243 -maven/mavencentral/software.amazon.awssdk/auth/2.22.9, Apache-2.0, approved, #12622 maven/mavencentral/software.amazon.awssdk/auth/2.24.5, Apache-2.0, approved, #13256 -maven/mavencentral/software.amazon.awssdk/aws-core/2.22.9, Apache-2.0, approved, #12640 maven/mavencentral/software.amazon.awssdk/aws-core/2.24.5, Apache-2.0, approved, #13240 -maven/mavencentral/software.amazon.awssdk/aws-query-protocol/2.22.9, Apache-2.0, approved, #12645 maven/mavencentral/software.amazon.awssdk/aws-query-protocol/2.24.5, Apache-2.0, approved, #13262 -maven/mavencentral/software.amazon.awssdk/aws-xml-protocol/2.22.9, Apache-2.0, approved, #12628 maven/mavencentral/software.amazon.awssdk/aws-xml-protocol/2.24.5, Apache-2.0, approved, #13247 -maven/mavencentral/software.amazon.awssdk/checksums-spi/2.22.9, Apache-2.0, approved, #12642 maven/mavencentral/software.amazon.awssdk/checksums-spi/2.24.5, Apache-2.0, approved, #13245 -maven/mavencentral/software.amazon.awssdk/checksums/2.22.9, Apache-2.0, approved, #12641 maven/mavencentral/software.amazon.awssdk/checksums/2.24.5, Apache-2.0, approved, #13242 -maven/mavencentral/software.amazon.awssdk/crt-core/2.22.9, Apache-2.0, approved, #12635 maven/mavencentral/software.amazon.awssdk/crt-core/2.24.5, Apache-2.0, approved, #13252 -maven/mavencentral/software.amazon.awssdk/endpoints-spi/2.22.9, Apache-2.0, approved, #12624 maven/mavencentral/software.amazon.awssdk/endpoints-spi/2.24.5, Apache-2.0, approved, #13246 -maven/mavencentral/software.amazon.awssdk/http-auth-aws/2.22.9, Apache-2.0, approved, #12637 maven/mavencentral/software.amazon.awssdk/http-auth-aws/2.24.5, Apache-2.0, approved, #13253 -maven/mavencentral/software.amazon.awssdk/http-auth-spi/2.22.9, Apache-2.0, approved, #12638 maven/mavencentral/software.amazon.awssdk/http-auth-spi/2.24.5, Apache-2.0, approved, #13264 -maven/mavencentral/software.amazon.awssdk/http-auth/2.22.9, Apache-2.0, approved, #12626 maven/mavencentral/software.amazon.awssdk/http-auth/2.24.5, Apache-2.0, approved, #13248 -maven/mavencentral/software.amazon.awssdk/http-client-spi/2.22.9, Apache-2.0, approved, #12627 maven/mavencentral/software.amazon.awssdk/http-client-spi/2.24.5, Apache-2.0, approved, #13259 -maven/mavencentral/software.amazon.awssdk/iam/2.22.9, Apache-2.0, approved, clearlydefined -maven/mavencentral/software.amazon.awssdk/identity-spi/2.22.9, Apache-2.0, approved, #12636 +maven/mavencentral/software.amazon.awssdk/iam/2.24.5, , restricted, clearlydefined maven/mavencentral/software.amazon.awssdk/identity-spi/2.24.5, Apache-2.0, approved, #13244 -maven/mavencentral/software.amazon.awssdk/json-utils/2.22.9, Apache-2.0, approved, #12646 maven/mavencentral/software.amazon.awssdk/json-utils/2.24.5, Apache-2.0, approved, #13261 -maven/mavencentral/software.amazon.awssdk/metrics-spi/2.22.9, Apache-2.0, approved, #12649 maven/mavencentral/software.amazon.awssdk/metrics-spi/2.24.5, Apache-2.0, approved, #13239 -maven/mavencentral/software.amazon.awssdk/netty-nio-client/2.22.9, Apache-2.0, approved, #12644 maven/mavencentral/software.amazon.awssdk/netty-nio-client/2.24.5, Apache-2.0, approved, #13260 -maven/mavencentral/software.amazon.awssdk/profiles/2.22.9, Apache-2.0, approved, #12620 maven/mavencentral/software.amazon.awssdk/profiles/2.24.5, Apache-2.0, approved, #13258 -maven/mavencentral/software.amazon.awssdk/protocol-core/2.22.9, Apache-2.0, approved, #12648 maven/mavencentral/software.amazon.awssdk/protocol-core/2.24.5, Apache-2.0, approved, #13241 -maven/mavencentral/software.amazon.awssdk/regions/2.22.9, Apache-2.0, approved, #12643 maven/mavencentral/software.amazon.awssdk/regions/2.24.5, Apache-2.0, approved, #13255 maven/mavencentral/software.amazon.awssdk/s3-transfer-manager/2.24.5, Apache-2.0, approved, #13263 -maven/mavencentral/software.amazon.awssdk/s3/2.22.9, Apache-2.0, approved, #12630 maven/mavencentral/software.amazon.awssdk/s3/2.24.5, Apache-2.0, approved, #13254 -maven/mavencentral/software.amazon.awssdk/sdk-core/2.22.9, Apache-2.0, approved, #12639 maven/mavencentral/software.amazon.awssdk/sdk-core/2.24.5, Apache-2.0, approved, #13265 -maven/mavencentral/software.amazon.awssdk/sts/2.22.9, Apache-2.0, approved, clearlydefined -maven/mavencentral/software.amazon.awssdk/third-party-jackson-core/2.22.9, Apache-2.0, approved, #12629 +maven/mavencentral/software.amazon.awssdk/sts/2.24.5, , restricted, clearlydefined maven/mavencentral/software.amazon.awssdk/third-party-jackson-core/2.24.5, Apache-2.0, approved, #13249 -maven/mavencentral/software.amazon.awssdk/utils/2.22.9, Apache-2.0, approved, #12631 maven/mavencentral/software.amazon.awssdk/utils/2.24.5, Apache-2.0, approved, #13250 maven/mavencentral/software.amazon.eventstream/eventstream/1.0.1, Apache-2.0, approved, clearlydefined diff --git a/edc-controlplane/edc-controlplane-base/build.gradle.kts b/edc-controlplane/edc-controlplane-base/build.gradle.kts index fd7a31c80..b4584ccc6 100644 --- a/edc-controlplane/edc-controlplane-base/build.gradle.kts +++ b/edc-controlplane/edc-controlplane-base/build.gradle.kts @@ -40,7 +40,7 @@ dependencies { runtimeOnly(project(":edc-extensions:ssi:ssi-identity-core")) runtimeOnly(project(":edc-extensions:ssi:ssi-miw-credential-client")) runtimeOnly(project(":edc-extensions:ssi:ssi-identity-extractor")) - runtimeOnly(project(":edc-extensions:cx-policy")) + runtimeOnly(project(":edc-extensions:cx-policy-legacy")) runtimeOnly(libs.edc.core.controlplane) runtimeOnly(libs.edc.core.policy.monitor) diff --git a/edc-extensions/cx-policy-legacy/build.gradle.kts b/edc-extensions/cx-policy-legacy/build.gradle.kts new file mode 100644 index 000000000..def8283d6 --- /dev/null +++ b/edc-extensions/cx-policy-legacy/build.gradle.kts @@ -0,0 +1,33 @@ +/******************************************************************************** + * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +plugins { + `java-library` +} + +dependencies { + implementation(project(":spi:core-spi")) + implementation(project(":spi:ssi-spi")) + implementation(libs.edc.spi.policyengine) + implementation(libs.jakartaJson) + implementation(libs.edc.spi.identitytrust) + testImplementation(libs.jacksonJsonP) + testImplementation(libs.titaniumJsonLd) + testImplementation(testFixtures(project(":spi:ssi-spi"))) +} diff --git a/edc-extensions/cx-policy-legacy/src/main/java/org/eclipse/tractusx/edc/policy/cx/CxPolicyExtension.java b/edc-extensions/cx-policy-legacy/src/main/java/org/eclipse/tractusx/edc/policy/cx/CxPolicyExtension.java new file mode 100644 index 000000000..a47c8b169 --- /dev/null +++ b/edc-extensions/cx-policy-legacy/src/main/java/org/eclipse/tractusx/edc/policy/cx/CxPolicyExtension.java @@ -0,0 +1,55 @@ +/******************************************************************************** + * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +package org.eclipse.tractusx.edc.policy.cx; + +import org.eclipse.edc.policy.engine.spi.PolicyEngine; +import org.eclipse.edc.policy.engine.spi.RuleBindingRegistry; +import org.eclipse.edc.runtime.metamodel.annotation.Inject; +import org.eclipse.edc.spi.system.ServiceExtension; +import org.eclipse.edc.spi.system.ServiceExtensionContext; + +import static org.eclipse.tractusx.edc.policy.cx.summary.SummaryConstraintFunctionsProvider.registerBindings; +import static org.eclipse.tractusx.edc.policy.cx.summary.SummaryConstraintFunctionsProvider.registerFunctions; + + +/** + * Provides implementations of standard CX usage policies. + */ +public class CxPolicyExtension implements ServiceExtension { + private static final String NAME = "CX Policy"; + + @Inject + private PolicyEngine policyEngine; + + @Inject + private RuleBindingRegistry bindingRegistry; + + @Override + public String name() { + return NAME; + } + + @Override + public void initialize(ServiceExtensionContext context) { + + registerBindings(bindingRegistry); + registerFunctions(policyEngine); + } +} diff --git a/edc-extensions/cx-policy-legacy/src/main/java/org/eclipse/tractusx/edc/policy/cx/common/AbstractDynamicCredentialConstraintFunction.java b/edc-extensions/cx-policy-legacy/src/main/java/org/eclipse/tractusx/edc/policy/cx/common/AbstractDynamicCredentialConstraintFunction.java new file mode 100644 index 000000000..164744403 --- /dev/null +++ b/edc-extensions/cx-policy-legacy/src/main/java/org/eclipse/tractusx/edc/policy/cx/common/AbstractDynamicCredentialConstraintFunction.java @@ -0,0 +1,80 @@ +/******************************************************************************** + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +package org.eclipse.tractusx.edc.policy.cx.common; + +import org.eclipse.edc.identitytrust.model.VerifiableCredential; +import org.eclipse.edc.policy.engine.spi.DynamicAtomicConstraintFunction; +import org.eclipse.edc.policy.engine.spi.PolicyContext; +import org.eclipse.edc.policy.model.Operator; +import org.eclipse.edc.policy.model.Permission; +import org.eclipse.edc.spi.agent.ParticipantAgent; +import org.eclipse.edc.spi.result.Result; + +import java.util.Collection; +import java.util.List; + +/** + * This is a base class for dynamically bound Tractus-X constraint evaluation functions that implements some basic common functionality and defines some + * common constants + */ +public abstract class AbstractDynamicCredentialConstraintFunction implements DynamicAtomicConstraintFunction { + public static final String VC_CLAIM = "vc"; + public static final String ACTIVE = "active"; + public static final String CREDENTIAL_LITERAL = "Credential"; + protected static final Collection EQUALITY_OPERATORS = List.of(Operator.EQ, Operator.NEQ); + + protected boolean checkOperator(Operator actual, PolicyContext context, Collection expectedOperators) { + if (!expectedOperators.contains(actual)) { + context.reportProblem("Invalid operator: this constraint only allows the following operators: %s, but received '%s'.".formatted(EQUALITY_OPERATORS, actual)); + return false; + } + return true; + } + + protected Result extractParticipantAgent(PolicyContext context) { + // make sure the ParticipantAgent is there + var participantAgent = context.getContextData(ParticipantAgent.class); + if (participantAgent == null) { + return Result.failure("Required PolicyContext data not found: " + ParticipantAgent.class.getName()); + } + return Result.success(participantAgent); + } + + /** + * Extracts a {@link List} of {@link VerifiableCredential} objects from the {@link ParticipantAgent}. Credentials must be + * stored in the agent's claims map using the "vc" key. + */ + protected Result> getCredentialList(ParticipantAgent agent) { + var vcListClaim = agent.getClaims().get(VC_CLAIM); + + if (vcListClaim == null) { + return Result.failure("ParticipantAgent did not contain a '%s' claim.".formatted(VC_CLAIM)); + } + if (!(vcListClaim instanceof List)) { + return Result.failure("ParticipantAgent contains a '%s' claim, but the type is incorrect. Expected %s, received %s.".formatted(VC_CLAIM, List.class.getName(), vcListClaim.getClass().getName())); + } + var vcList = (List) vcListClaim; + if (vcList.isEmpty()) { + return Result.failure("ParticipantAgent contains a '%s' claim but it did not contain any VerifiableCredentials.".formatted(VC_CLAIM)); + } + return Result.success(vcList); + } + +} diff --git a/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/common/AbstractVpConstraintFunction.java b/edc-extensions/cx-policy-legacy/src/main/java/org/eclipse/tractusx/edc/policy/cx/common/AbstractVpConstraintFunction.java similarity index 100% rename from edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/common/AbstractVpConstraintFunction.java rename to edc-extensions/cx-policy-legacy/src/main/java/org/eclipse/tractusx/edc/policy/cx/common/AbstractVpConstraintFunction.java diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/IatpFrameworkAgreementHttpConsumerPullWithProxyInMemoryTest.java b/edc-extensions/cx-policy-legacy/src/main/java/org/eclipse/tractusx/edc/policy/cx/common/CredentialTypePredicate.java similarity index 59% rename from edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/IatpFrameworkAgreementHttpConsumerPullWithProxyInMemoryTest.java rename to edc-extensions/cx-policy-legacy/src/main/java/org/eclipse/tractusx/edc/policy/cx/common/CredentialTypePredicate.java index aa786c40d..4a33eeeca 100644 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/IatpFrameworkAgreementHttpConsumerPullWithProxyInMemoryTest.java +++ b/edc-extensions/cx-policy-legacy/src/main/java/org/eclipse/tractusx/edc/policy/cx/common/CredentialTypePredicate.java @@ -17,22 +17,21 @@ * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ -package org.eclipse.tractusx.edc.tests.transfer; +package org.eclipse.tractusx.edc.policy.cx.common; -import jakarta.json.JsonObject; -import org.eclipse.edc.junit.annotations.EndToEndTest; +import org.eclipse.edc.identitytrust.model.VerifiableCredential; -import java.util.Map; +import java.util.function.Predicate; -import static org.eclipse.tractusx.edc.helpers.PolicyHelperFunctions.TX_CREDENTIAL_NAMESPACE; -import static org.eclipse.tractusx.edc.helpers.PolicyHelperFunctions.frameworkPolicy; +public class CredentialTypePredicate implements Predicate { + private final String expectedType; -@EndToEndTest -public class IatpFrameworkAgreementHttpConsumerPullWithProxyInMemoryTest extends IatpHttpConsumerPullWithProxyInMemoryTest { + public CredentialTypePredicate(String expectedType) { + this.expectedType = expectedType; + } @Override - protected JsonObject createContractPolicy(String bpn) { - return frameworkPolicy(Map.of(TX_CREDENTIAL_NAMESPACE + "FrameworkAgreement.pcf", "active")); + public boolean test(VerifiableCredential credential) { + return credential.getType().contains(expectedType); } - } diff --git a/edc-extensions/cx-policy-legacy/src/main/java/org/eclipse/tractusx/edc/policy/cx/common/PolicyScopes.java b/edc-extensions/cx-policy-legacy/src/main/java/org/eclipse/tractusx/edc/policy/cx/common/PolicyScopes.java new file mode 100644 index 000000000..84311bf4c --- /dev/null +++ b/edc-extensions/cx-policy-legacy/src/main/java/org/eclipse/tractusx/edc/policy/cx/common/PolicyScopes.java @@ -0,0 +1,33 @@ +/******************************************************************************** + * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +package org.eclipse.tractusx.edc.policy.cx.common; + +/** + * Defines standard EDC policy scopes. + */ +public interface PolicyScopes { + String CATALOG_REQUEST_SCOPE = "request.catalog"; + String NEGOTIATION_REQUEST_SCOPE = "request.contract.negotiation"; + String TRANSFER_PROCESS_REQUEST_SCOPE = "request.transfer.process"; + + String CATALOG_SCOPE = "catalog"; + String NEGOTIATION_SCOPE = "contract.negotiation"; + String TRANSFER_PROCESS_SCOPE = "transfer.process"; +} diff --git a/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/summary/SummaryConstraintFunction.java b/edc-extensions/cx-policy-legacy/src/main/java/org/eclipse/tractusx/edc/policy/cx/summary/SummaryConstraintFunction.java similarity index 100% rename from edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/summary/SummaryConstraintFunction.java rename to edc-extensions/cx-policy-legacy/src/main/java/org/eclipse/tractusx/edc/policy/cx/summary/SummaryConstraintFunction.java diff --git a/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/summary/SummaryConstraintFunctionsProvider.java b/edc-extensions/cx-policy-legacy/src/main/java/org/eclipse/tractusx/edc/policy/cx/summary/SummaryConstraintFunctionsProvider.java similarity index 100% rename from edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/summary/SummaryConstraintFunctionsProvider.java rename to edc-extensions/cx-policy-legacy/src/main/java/org/eclipse/tractusx/edc/policy/cx/summary/SummaryConstraintFunctionsProvider.java diff --git a/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/summary/SummaryTokenPolicyFunction.java b/edc-extensions/cx-policy-legacy/src/main/java/org/eclipse/tractusx/edc/policy/cx/summary/SummaryTokenPolicyFunction.java similarity index 100% rename from edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/summary/SummaryTokenPolicyFunction.java rename to edc-extensions/cx-policy-legacy/src/main/java/org/eclipse/tractusx/edc/policy/cx/summary/SummaryTokenPolicyFunction.java diff --git a/edc-extensions/cx-policy-legacy/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension b/edc-extensions/cx-policy-legacy/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension new file mode 100644 index 000000000..3b058563d --- /dev/null +++ b/edc-extensions/cx-policy-legacy/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension @@ -0,0 +1,21 @@ +################################################################################# +# Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License, Version 2.0 which is available at +# https://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. +# +# SPDX-License-Identifier: Apache-2.0 +################################################################################# + +org.eclipse.tractusx.edc.policy.cx.CxPolicyExtension + diff --git a/edc-extensions/cx-policy-legacy/src/test/java/org/eclipse/tractusx/edc/policy/cx/CredentialFunctions.java b/edc-extensions/cx-policy-legacy/src/test/java/org/eclipse/tractusx/edc/policy/cx/CredentialFunctions.java new file mode 100644 index 000000000..d562863d5 --- /dev/null +++ b/edc-extensions/cx-policy-legacy/src/test/java/org/eclipse/tractusx/edc/policy/cx/CredentialFunctions.java @@ -0,0 +1,90 @@ +/******************************************************************************** + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +package org.eclipse.tractusx.edc.policy.cx; + +import org.eclipse.edc.identitytrust.model.CredentialSubject; +import org.eclipse.edc.identitytrust.model.Issuer; +import org.eclipse.edc.identitytrust.model.VerifiableCredential; + +import java.time.Instant; +import java.time.temporal.ChronoUnit; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.CX_CREDENTIAL_NS; + +public class CredentialFunctions { + + public static VerifiableCredential.Builder createCredential(String type, String version) { + return VerifiableCredential.Builder.newInstance() + .types(List.of(CX_CREDENTIAL_NS + "VerifiableCredential", CX_CREDENTIAL_NS + type)) + .id(UUID.randomUUID().toString()) + .issuer(new Issuer(UUID.randomUUID().toString(), Map.of("prop1", "val1"))) + .expirationDate(Instant.now().plus(365, ChronoUnit.DAYS)) + .issuanceDate(Instant.now()) + .credentialSubject(CredentialSubject.Builder.newInstance() + .id("subject-id") + .claim(CX_CREDENTIAL_NS + "holderIdentifier", "did:web:holder") + .claim(CX_CREDENTIAL_NS + "contractVersion", version) + .claim(CX_CREDENTIAL_NS + "contractTemplate", "https://public.catena-x.org/contracts/pcf.v1.pdf") + .build()); + } + + public static VerifiableCredential.Builder createPcfCredential() { + return createCredential("PcfCredential", "1.0.0"); + } + + public static VerifiableCredential.Builder createDismantlerCredential(String... brands) { + return createDismantlerCredential(Arrays.asList(brands), "vehicleDismantle"); + } + + public static VerifiableCredential.Builder createDismantlerCredential(Collection brands, String... activityType) { + var at = activityType.length == 1 ? activityType[0] : List.of(activityType); + return VerifiableCredential.Builder.newInstance() + .types(List.of("VerifiableCredential", CX_CREDENTIAL_NS + "DismantlerCredential")) + .id(UUID.randomUUID().toString()) + .issuer(new Issuer(UUID.randomUUID().toString(), Map.of("prop1", "val1"))) + .expirationDate(Instant.now().plus(365, ChronoUnit.DAYS)) + .issuanceDate(Instant.now()) + .credentialSubject(CredentialSubject.Builder.newInstance() + .id("subject-id") + .claim(CX_CREDENTIAL_NS + "holderIdentifier", "did:web:holder") + .claim(CX_CREDENTIAL_NS + "allowedVehicleBrands", brands) + .claim(CX_CREDENTIAL_NS + "activityType", at) + .build()); + } + + public static VerifiableCredential.Builder createMembershipCredential() { + return VerifiableCredential.Builder.newInstance() + .types(List.of(CX_CREDENTIAL_NS + "VerifiableCredential", CX_CREDENTIAL_NS + "MembershipCredential")) + .id(UUID.randomUUID().toString()) + .issuer(new Issuer(UUID.randomUUID().toString(), Map.of("prop1", "val1"))) + .expirationDate(Instant.now().plus(365, ChronoUnit.DAYS)) + .issuanceDate(Instant.now()) + .credentialSubject(CredentialSubject.Builder.newInstance() + .id("subject-id") + .claim(CX_CREDENTIAL_NS + "holderIdentifier", "did:web:holder") + .build()); + } + +} diff --git a/edc-extensions/cx-policy/src/test/java/org/eclipse/tractusx/edc/policy/cx/common/AbstractVpConstraintFunctionTest.java b/edc-extensions/cx-policy-legacy/src/test/java/org/eclipse/tractusx/edc/policy/cx/common/AbstractVpConstraintFunctionTest.java similarity index 100% rename from edc-extensions/cx-policy/src/test/java/org/eclipse/tractusx/edc/policy/cx/common/AbstractVpConstraintFunctionTest.java rename to edc-extensions/cx-policy-legacy/src/test/java/org/eclipse/tractusx/edc/policy/cx/common/AbstractVpConstraintFunctionTest.java diff --git a/edc-extensions/cx-policy/src/test/java/org/eclipse/tractusx/edc/policy/cx/summary/SummaryConstraintFunctionTest.java b/edc-extensions/cx-policy-legacy/src/test/java/org/eclipse/tractusx/edc/policy/cx/summary/SummaryConstraintFunctionTest.java similarity index 100% rename from edc-extensions/cx-policy/src/test/java/org/eclipse/tractusx/edc/policy/cx/summary/SummaryConstraintFunctionTest.java rename to edc-extensions/cx-policy-legacy/src/test/java/org/eclipse/tractusx/edc/policy/cx/summary/SummaryConstraintFunctionTest.java diff --git a/edc-extensions/cx-policy/src/test/java/org/eclipse/tractusx/edc/policy/cx/summary/SummaryConstraintFunctionsProviderTest.java b/edc-extensions/cx-policy-legacy/src/test/java/org/eclipse/tractusx/edc/policy/cx/summary/SummaryConstraintFunctionsProviderTest.java similarity index 100% rename from edc-extensions/cx-policy/src/test/java/org/eclipse/tractusx/edc/policy/cx/summary/SummaryConstraintFunctionsProviderTest.java rename to edc-extensions/cx-policy-legacy/src/test/java/org/eclipse/tractusx/edc/policy/cx/summary/SummaryConstraintFunctionsProviderTest.java diff --git a/edc-extensions/cx-policy/src/test/java/org/eclipse/tractusx/edc/policy/cx/summary/SummaryTokenPolicyFunctionTest.java b/edc-extensions/cx-policy-legacy/src/test/java/org/eclipse/tractusx/edc/policy/cx/summary/SummaryTokenPolicyFunctionTest.java similarity index 100% rename from edc-extensions/cx-policy/src/test/java/org/eclipse/tractusx/edc/policy/cx/summary/SummaryTokenPolicyFunctionTest.java rename to edc-extensions/cx-policy-legacy/src/test/java/org/eclipse/tractusx/edc/policy/cx/summary/SummaryTokenPolicyFunctionTest.java diff --git a/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/CxPolicyExtension.java b/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/CxPolicyExtension.java index d36664024..c8e93c4ed 100644 --- a/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/CxPolicyExtension.java +++ b/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/CxPolicyExtension.java @@ -25,8 +25,9 @@ import org.eclipse.edc.spi.system.ServiceExtension; import org.eclipse.edc.spi.system.ServiceExtensionContext; -import static org.eclipse.tractusx.edc.policy.cx.summary.SummaryConstraintFunctionsProvider.registerBindings; -import static org.eclipse.tractusx.edc.policy.cx.summary.SummaryConstraintFunctionsProvider.registerFunctions; +import static org.eclipse.tractusx.edc.policy.cx.CxPolicyRegistration.registerBindings; +import static org.eclipse.tractusx.edc.policy.cx.CxPolicyRegistration.registerFunctions; + /** * Provides implementations of standard CX usage policies. diff --git a/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/CxPolicyRegistration.java b/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/CxPolicyRegistration.java new file mode 100644 index 000000000..70c2a6960 --- /dev/null +++ b/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/CxPolicyRegistration.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.eclipse.tractusx.edc.policy.cx; + +import org.eclipse.edc.policy.engine.spi.PolicyEngine; +import org.eclipse.edc.policy.engine.spi.RuleBindingRegistry; +import org.eclipse.edc.policy.model.Permission; +import org.eclipse.tractusx.edc.policy.cx.dismantler.DismantlerCredentialConstraintFunction; +import org.eclipse.tractusx.edc.policy.cx.framework.FrameworkAgreementCredentialConstraintFunction; +import org.eclipse.tractusx.edc.policy.cx.membership.MembershipCredentialConstraintFunction; + +import java.util.Set; +import java.util.stream.Stream; + +import static org.eclipse.edc.policy.model.OdrlNamespace.ODRL_SCHEMA; +import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.CX_POLICY_NS; +import static org.eclipse.tractusx.edc.policy.cx.common.PolicyScopes.CATALOG_REQUEST_SCOPE; +import static org.eclipse.tractusx.edc.policy.cx.common.PolicyScopes.CATALOG_SCOPE; +import static org.eclipse.tractusx.edc.policy.cx.common.PolicyScopes.NEGOTIATION_REQUEST_SCOPE; +import static org.eclipse.tractusx.edc.policy.cx.common.PolicyScopes.NEGOTIATION_SCOPE; +import static org.eclipse.tractusx.edc.policy.cx.common.PolicyScopes.TRANSFER_PROCESS_REQUEST_SCOPE; +import static org.eclipse.tractusx.edc.policy.cx.common.PolicyScopes.TRANSFER_PROCESS_SCOPE; +import static org.eclipse.tractusx.edc.policy.cx.dismantler.DismantlerCredentialConstraintFunction.DISMANTLER_LITERAL; +import static org.eclipse.tractusx.edc.policy.cx.framework.FrameworkAgreementCredentialConstraintFunction.FRAMEWORK_AGREEMENT_LITERAL; +import static org.eclipse.tractusx.edc.policy.cx.membership.MembershipCredentialConstraintFunction.MEMBERSHIP_LITERAL; + +public class CxPolicyRegistration { + private static final Set FUNCTION_SCOPES = Set.of(CATALOG_SCOPE, NEGOTIATION_SCOPE, TRANSFER_PROCESS_SCOPE); + private static final Set RULE_SCOPES = Set.of(CATALOG_REQUEST_SCOPE, NEGOTIATION_REQUEST_SCOPE, TRANSFER_PROCESS_REQUEST_SCOPE, CATALOG_SCOPE, NEGOTIATION_SCOPE, TRANSFER_PROCESS_SCOPE); + + public static void registerFunctions(PolicyEngine engine) { + FUNCTION_SCOPES.forEach(scope -> { + engine.registerFunction(scope, Permission.class, new DismantlerCredentialConstraintFunction()); + engine.registerFunction(scope, Permission.class, new MembershipCredentialConstraintFunction()); + engine.registerFunction(scope, Permission.class, new FrameworkAgreementCredentialConstraintFunction()); + }); + } + + public static void registerBindings(RuleBindingRegistry registry) { + registry.dynamicBind(s -> { + if (Stream.of(FRAMEWORK_AGREEMENT_LITERAL, DISMANTLER_LITERAL, MEMBERSHIP_LITERAL).anyMatch(postfix -> s.startsWith(CX_POLICY_NS + postfix))) { + return RULE_SCOPES; + } + return Set.of(); + }); + + registry.bind(ODRL_SCHEMA + "use", CATALOG_SCOPE); + registry.bind(ODRL_SCHEMA + "use", NEGOTIATION_SCOPE); + registry.bind(ODRL_SCHEMA + "use", TRANSFER_PROCESS_SCOPE); + } +} diff --git a/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/common/CredentialTypePredicate.java b/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/common/CredentialTypePredicate.java index 0fc858efd..4a33eeeca 100644 --- a/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/common/CredentialTypePredicate.java +++ b/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/common/CredentialTypePredicate.java @@ -32,6 +32,6 @@ public CredentialTypePredicate(String expectedType) { @Override public boolean test(VerifiableCredential credential) { - return credential.getTypes().contains(expectedType); + return credential.getType().contains(expectedType); } } diff --git a/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/dismantler/DismantlerCredentialConstraintFunction.java b/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/dismantler/DismantlerCredentialConstraintFunction.java index 9991309f3..aee4d12c8 100644 --- a/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/dismantler/DismantlerCredentialConstraintFunction.java +++ b/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/dismantler/DismantlerCredentialConstraintFunction.java @@ -19,6 +19,7 @@ package org.eclipse.tractusx.edc.policy.cx.dismantler; +import jakarta.json.JsonObject; import org.eclipse.edc.identitytrust.model.VerifiableCredential; import org.eclipse.edc.policy.engine.spi.PolicyContext; import org.eclipse.edc.policy.model.Operator; @@ -37,7 +38,8 @@ import static org.eclipse.edc.policy.model.Operator.IS_ANY_OF; import static org.eclipse.edc.policy.model.Operator.IS_NONE_OF; import static org.eclipse.edc.policy.model.Operator.NEQ; -import static org.eclipse.tractusx.edc.iam.ssi.spi.jsonld.CredentialsNamespaces.CX_NS_1_0; +import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.CX_CREDENTIAL_NS; +import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.CX_POLICY_NS; /** * Enforces a Dismantler constraint. This function can check for these properties: @@ -49,13 +51,15 @@ */ public class DismantlerCredentialConstraintFunction extends AbstractDynamicCredentialConstraintFunction { - public static final String ALLOWED_VEHICLE_BRANDS = CX_NS_1_0 + "allowedVehicleBrands"; - private static final String DISMANTLER_LITERAL = "Dismantler"; - private static final String ALLOWED_ACTIVITIES = CX_NS_1_0 + "activityType"; + public static final String ALLOWED_VEHICLE_BRANDS = CX_CREDENTIAL_NS + "allowedVehicleBrands"; + public static final String DISMANTLER_LITERAL = "Dismantler"; + // allows to encode multiple values in a single string in the right-operand. Policies don't handle list-type right-operands well. + public static final String RIGHT_OPERAND_LIST_SEPARATOR = ","; + private static final String ALLOWED_ACTIVITIES = CX_CREDENTIAL_NS + "activityType"; @Override public boolean evaluate(Object leftOperand, Operator operator, Object rightOperand, Permission permission, PolicyContext context) { - Predicate predicate = c -> false; + Predicate predicate; // make sure the ParticipantAgent is there var participantAgent = extractParticipantAgent(context); @@ -71,7 +75,15 @@ public boolean evaluate(Object leftOperand, Operator operator, Object rightOpera return false; } - if (leftOperand.equals(DISMANTLER_LITERAL)) { // only checks for presence + // always filter for DismantlerCredential type + predicate = new CredentialTypePredicate(CX_CREDENTIAL_NS + DISMANTLER_LITERAL + CREDENTIAL_LITERAL); + + + if (rightOperand.toString().contains(RIGHT_OPERAND_LIST_SEPARATOR)) { + rightOperand = getList(rightOperand); + } + + if (leftOperand.equals(CX_POLICY_NS + DISMANTLER_LITERAL)) { // only checks for presence if (!checkOperator(operator, context, EQUALITY_OPERATORS)) { return false; } @@ -79,28 +91,27 @@ public boolean evaluate(Object leftOperand, Operator operator, Object rightOpera context.reportProblem("Right-operand must be equal to '%s', but was '%s'".formatted(ACTIVE, rightOperand)); return false; } - predicate = new CredentialTypePredicate(DISMANTLER_LITERAL + CREDENTIAL_LITERAL); if (operator == NEQ) { predicate = predicate.negate(); } - } else if (leftOperand.equals(DISMANTLER_LITERAL + ".activityType")) { + + } else if (leftOperand.equals(CX_POLICY_NS + DISMANTLER_LITERAL + ".activityType")) { if (hasInvalidOperand(operator, rightOperand, context)) return false; - predicate = getCredentialPredicate(ALLOWED_ACTIVITIES, operator, rightOperand); - } else if (leftOperand.equals(DISMANTLER_LITERAL + ".allowedBrands")) { + predicate = predicate.and(getCredentialPredicate(ALLOWED_ACTIVITIES, operator, rightOperand)); + } else if (leftOperand.equals(CX_POLICY_NS + DISMANTLER_LITERAL + ".allowedBrands")) { if (hasInvalidOperand(operator, rightOperand, context)) return false; - predicate = getCredentialPredicate(ALLOWED_VEHICLE_BRANDS, operator, rightOperand); + predicate = predicate.and(getCredentialPredicate(ALLOWED_VEHICLE_BRANDS, operator, rightOperand)); } else { context.reportProblem("Invalid left-operand: must be 'Dismantler[.activityType | .allowedBrands ], but was '%s'".formatted(leftOperand)); return false; } - return !vcListResult.getContent().stream().filter(predicate) - .toList().isEmpty(); + return vcListResult.getContent().stream().anyMatch(predicate); } @Override public boolean canHandle(Object leftOperand) { - return leftOperand instanceof String && ((String) leftOperand).startsWith(DISMANTLER_LITERAL); + return leftOperand instanceof String && ((String) leftOperand).startsWith(CX_POLICY_NS + DISMANTLER_LITERAL); } /** @@ -115,10 +126,9 @@ public boolean canHandle(Object leftOperand) { */ @NotNull private Predicate getCredentialPredicate(String credentialSubjectProperty, Operator operator, Object rightOperand) { - Predicate predicate; var allowedValues = getList(rightOperand); // the filter predicate is determined by the operator - predicate = credential -> credential.getCredentialSubject().stream().anyMatch(subject -> { + return credential -> credential.getCredentialSubject().stream().anyMatch(subject -> { var claimsFromCredential = getList(subject.getClaims().getOrDefault(credentialSubjectProperty, List.of())); return switch (operator) { case EQ -> claimsFromCredential.equals(allowedValues); @@ -130,7 +140,6 @@ private Predicate getCredentialPredicate(String credential default -> false; }; }); - return predicate; } /** @@ -160,9 +169,16 @@ private List intersect(List list1, List list2) { private List getList(Object object) { if (object instanceof Iterable iterable) { var list = new ArrayList<>(); - iterable.iterator().forEachRemaining(list::add); + + iterable.iterator().forEachRemaining(element -> { + if (element instanceof JsonObject jo) { // workaround: lists in policy right-operands are not properly deserialized + list.add(jo.getString("@value")); + } else { + list.add(element); + } + }); return list; } - return List.of(object); + return List.of(object.toString().split(RIGHT_OPERAND_LIST_SEPARATOR)); // in case multiple values are encoded in a single string } } diff --git a/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/framework/FrameworkAgreementCredentialConstraintFunction.java b/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/framework/FrameworkAgreementCredentialConstraintFunction.java index 3ef30ee30..65ee08856 100644 --- a/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/framework/FrameworkAgreementCredentialConstraintFunction.java +++ b/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/framework/FrameworkAgreementCredentialConstraintFunction.java @@ -34,7 +34,8 @@ import java.util.List; import java.util.function.Predicate; -import static org.eclipse.tractusx.edc.iam.ssi.spi.jsonld.CredentialsNamespaces.CX_NS_1_0; +import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.CX_CREDENTIAL_NS; +import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.CX_POLICY_NS; /** @@ -53,11 +54,8 @@ * credential that satisfies the {@code subtype} requirement. */ public class FrameworkAgreementCredentialConstraintFunction extends AbstractDynamicCredentialConstraintFunction { - public static final String CONTRACT_VERSION_PROPERTY = CX_NS_1_0 + "contractVersion"; - private static final String FRAMEWORK_AGREEMENT_LITERAL = "FrameworkAgreement"; - - public FrameworkAgreementCredentialConstraintFunction() { - } + public static final String CONTRACT_VERSION_PROPERTY = CX_CREDENTIAL_NS + "contractVersion"; + public static final String FRAMEWORK_AGREEMENT_LITERAL = "FrameworkAgreement"; /** * Evaluates the constraint's left-operand and right-operand against a list of {@link VerifiableCredential} objects. @@ -93,10 +91,10 @@ public boolean evaluate(Object leftValue, Operator operator, Object rightValue, var rightOperand = rightValue.toString(); Result>> predicateResult; - if (leftOperand.startsWith(FRAMEWORK_AGREEMENT_LITERAL + ".")) { // legacy notation + if (leftOperand.startsWith(CX_POLICY_NS + FRAMEWORK_AGREEMENT_LITERAL + ".")) { // legacy notation predicateResult = getFilterPredicateLegacy(leftOperand, rightOperand); - } else if (leftOperand.startsWith(FRAMEWORK_AGREEMENT_LITERAL)) { // new notation + } else if (leftOperand.startsWith(CX_POLICY_NS + FRAMEWORK_AGREEMENT_LITERAL)) { // new notation predicateResult = getFilterPredicate(rightOperand); } else { //invalid notation context.reportProblem("Constraint left-operand must start with '%s' but was '%s'.".formatted(FRAMEWORK_AGREEMENT_LITERAL, leftValue)); @@ -129,7 +127,7 @@ public boolean evaluate(Object leftValue, Operator operator, Object rightValue, */ @Override public boolean canHandle(Object leftValue) { - return leftValue instanceof String && leftValue.toString().startsWith(FRAMEWORK_AGREEMENT_LITERAL); + return leftValue instanceof String && leftValue.toString().startsWith(CX_POLICY_NS + FRAMEWORK_AGREEMENT_LITERAL); } @NotNull @@ -157,7 +155,7 @@ private Result>> getFilterPredicate(String * Converts the left- and right-operand (legacy notation) into either 1 or 2 predicates, depending on whether the version was encoded or not. */ private Result>> getFilterPredicateLegacy(String leftOperand, String rightOperand) { - var subType = leftOperand.replace(FRAMEWORK_AGREEMENT_LITERAL + ".", ""); + var subType = leftOperand.replace(CX_POLICY_NS + FRAMEWORK_AGREEMENT_LITERAL + ".", ""); if (subType.isEmpty()) { return Result.failure("Left-operand must contain the sub-type 'FrameworkAgreement.'."); } @@ -175,9 +173,10 @@ private Result>> getFilterPredicateLegacy(S @NotNull private List> createPredicates(String subtype, @Nullable String version) { var list = new ArrayList>(); - list.add(new CredentialTypePredicate(capitalize(subtype) + CREDENTIAL_LITERAL)); + list.add(new CredentialTypePredicate(CX_CREDENTIAL_NS + capitalize(subtype) + CREDENTIAL_LITERAL)); + if (version != null) { - list.add(credential -> credential.getCredentialSubject().stream().anyMatch(cs -> cs.getClaims().get(CONTRACT_VERSION_PROPERTY).equals(version))); + list.add(credential -> credential.getCredentialSubject().stream().anyMatch(cs -> version.equals(cs.getClaims().getOrDefault(CONTRACT_VERSION_PROPERTY, null)))); } return list; } diff --git a/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/membership/MembershipCredentialConstraintFunction.java b/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/membership/MembershipCredentialConstraintFunction.java index 2866eb49c..43325bf73 100644 --- a/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/membership/MembershipCredentialConstraintFunction.java +++ b/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/membership/MembershipCredentialConstraintFunction.java @@ -26,12 +26,16 @@ import org.eclipse.tractusx.edc.policy.cx.common.AbstractDynamicCredentialConstraintFunction; import org.eclipse.tractusx.edc.policy.cx.common.CredentialTypePredicate; +import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.CX_CREDENTIAL_NS; +import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.CX_POLICY_NS; + + /** * This constraint function checks that a MembershipCredential is present in a list of {@link org.eclipse.edc.identitytrust.model.VerifiableCredential} * objects extracted from a {@link ParticipantAgent} which is expected to be present on the {@link PolicyContext}. */ public class MembershipCredentialConstraintFunction extends AbstractDynamicCredentialConstraintFunction { - private static final String MEMBERSHIP_LITERAL = "Membership"; + public static final String MEMBERSHIP_LITERAL = "Membership"; @Override public boolean evaluate(Object leftOperand, Operator operator, Object rightOperand, Permission permission, PolicyContext context) { @@ -39,7 +43,7 @@ public boolean evaluate(Object leftOperand, Operator operator, Object rightOpera context.reportProblem("Right-operand must be equal to '%s', but was '%s'".formatted(ACTIVE, rightOperand)); return false; } - if (!MEMBERSHIP_LITERAL.equalsIgnoreCase(leftOperand.toString())) { + if (!(CX_POLICY_NS + MEMBERSHIP_LITERAL).equalsIgnoreCase(leftOperand.toString())) { context.reportProblem("Invalid left-operand: must be 'Membership', but was '%s'".formatted(leftOperand)); return false; } @@ -57,11 +61,11 @@ public boolean evaluate(Object leftOperand, Operator operator, Object rightOpera } return credentialResult.getContent() .stream() - .anyMatch(new CredentialTypePredicate(MEMBERSHIP_LITERAL + CREDENTIAL_LITERAL)); + .anyMatch(new CredentialTypePredicate(CX_CREDENTIAL_NS + MEMBERSHIP_LITERAL + CREDENTIAL_LITERAL)); } @Override public boolean canHandle(Object leftOperand) { - return leftOperand instanceof String && MEMBERSHIP_LITERAL.equalsIgnoreCase(leftOperand.toString()); + return leftOperand instanceof String && (CX_POLICY_NS + MEMBERSHIP_LITERAL).equalsIgnoreCase(leftOperand.toString()); } } diff --git a/edc-extensions/cx-policy/src/test/java/org/eclipse/tractusx/edc/policy/cx/CredentialFunctions.java b/edc-extensions/cx-policy/src/test/java/org/eclipse/tractusx/edc/policy/cx/CredentialFunctions.java index 48cb54a09..d562863d5 100644 --- a/edc-extensions/cx-policy/src/test/java/org/eclipse/tractusx/edc/policy/cx/CredentialFunctions.java +++ b/edc-extensions/cx-policy/src/test/java/org/eclipse/tractusx/edc/policy/cx/CredentialFunctions.java @@ -31,20 +31,22 @@ import java.util.Map; import java.util.UUID; +import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.CX_CREDENTIAL_NS; + public class CredentialFunctions { public static VerifiableCredential.Builder createCredential(String type, String version) { return VerifiableCredential.Builder.newInstance() - .types(List.of("VerifiableCredential", type)) + .types(List.of(CX_CREDENTIAL_NS + "VerifiableCredential", CX_CREDENTIAL_NS + type)) .id(UUID.randomUUID().toString()) .issuer(new Issuer(UUID.randomUUID().toString(), Map.of("prop1", "val1"))) .expirationDate(Instant.now().plus(365, ChronoUnit.DAYS)) .issuanceDate(Instant.now()) .credentialSubject(CredentialSubject.Builder.newInstance() .id("subject-id") - .claim("https://w3id.org/catenax/credentials/v1.0.0/holderIdentifier", "did:web:holder") - .claim("https://w3id.org/catenax/credentials/v1.0.0/contractVersion", version) - .claim("https://w3id.org/catenax/credentials/v1.0.0/contractTemplate", "https://public.catena-x.org/contracts/pcf.v1.pdf") + .claim(CX_CREDENTIAL_NS + "holderIdentifier", "did:web:holder") + .claim(CX_CREDENTIAL_NS + "contractVersion", version) + .claim(CX_CREDENTIAL_NS + "contractTemplate", "https://public.catena-x.org/contracts/pcf.v1.pdf") .build()); } @@ -59,29 +61,29 @@ public static VerifiableCredential.Builder createDismantlerCredential(String... public static VerifiableCredential.Builder createDismantlerCredential(Collection brands, String... activityType) { var at = activityType.length == 1 ? activityType[0] : List.of(activityType); return VerifiableCredential.Builder.newInstance() - .types(List.of("VerifiableCredential", "DismantlerCredential")) + .types(List.of("VerifiableCredential", CX_CREDENTIAL_NS + "DismantlerCredential")) .id(UUID.randomUUID().toString()) .issuer(new Issuer(UUID.randomUUID().toString(), Map.of("prop1", "val1"))) .expirationDate(Instant.now().plus(365, ChronoUnit.DAYS)) .issuanceDate(Instant.now()) .credentialSubject(CredentialSubject.Builder.newInstance() .id("subject-id") - .claim("https://w3id.org/catenax/credentials/v1.0.0/holderIdentifier", "did:web:holder") - .claim("https://w3id.org/catenax/credentials/v1.0.0/allowedVehicleBrands", brands) - .claim("https://w3id.org/catenax/credentials/v1.0.0/activityType", at) + .claim(CX_CREDENTIAL_NS + "holderIdentifier", "did:web:holder") + .claim(CX_CREDENTIAL_NS + "allowedVehicleBrands", brands) + .claim(CX_CREDENTIAL_NS + "activityType", at) .build()); } public static VerifiableCredential.Builder createMembershipCredential() { return VerifiableCredential.Builder.newInstance() - .types(List.of("VerifiableCredential", "MembershipCredential")) + .types(List.of(CX_CREDENTIAL_NS + "VerifiableCredential", CX_CREDENTIAL_NS + "MembershipCredential")) .id(UUID.randomUUID().toString()) .issuer(new Issuer(UUID.randomUUID().toString(), Map.of("prop1", "val1"))) .expirationDate(Instant.now().plus(365, ChronoUnit.DAYS)) .issuanceDate(Instant.now()) .credentialSubject(CredentialSubject.Builder.newInstance() .id("subject-id") - .claim("https://w3id.org/catenax/credentials/v1.0.0/holderIdentifier", "did:web:holder") + .claim(CX_CREDENTIAL_NS + "holderIdentifier", "did:web:holder") .build()); } diff --git a/edc-extensions/cx-policy/src/test/java/org/eclipse/tractusx/edc/policy/cx/dismantler/DismantlerConstraintFunctionTest.java b/edc-extensions/cx-policy/src/test/java/org/eclipse/tractusx/edc/policy/cx/dismantler/DismantlerConstraintFunctionTest.java index a6dbbf2bd..2dfce69fa 100644 --- a/edc-extensions/cx-policy/src/test/java/org/eclipse/tractusx/edc/policy/cx/dismantler/DismantlerConstraintFunctionTest.java +++ b/edc-extensions/cx-policy/src/test/java/org/eclipse/tractusx/edc/policy/cx/dismantler/DismantlerConstraintFunctionTest.java @@ -35,6 +35,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.eclipse.edc.policy.model.Operator.IN; +import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.CX_POLICY_NS; import static org.eclipse.tractusx.edc.policy.cx.CredentialFunctions.createDismantlerCredential; import static org.eclipse.tractusx.edc.policy.cx.CredentialFunctions.createPcfCredential; import static org.mockito.ArgumentMatchers.anyString; @@ -97,25 +98,25 @@ class Active { @Test void evaluate_eq_satisfied() { when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createDismantlerCredential("Tatra", "Moskvich").build()))); - assertThat(function.evaluate("Dismantler", Operator.EQ, "active", null, context)).isTrue(); + assertThat(function.evaluate(CX_POLICY_NS + "Dismantler", Operator.EQ, "active", null, context)).isTrue(); } @Test void evaluate_eq_notSatisfied() { when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createPcfCredential().build()))); - assertThat(function.evaluate("Dismantler", Operator.EQ, "active", null, context)).isFalse(); + assertThat(function.evaluate(CX_POLICY_NS + "Dismantler", Operator.EQ, "active", null, context)).isFalse(); } @Test void evaluate_neq_satisfied() { when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createPcfCredential().build()))); - assertThat(function.evaluate("Dismantler", Operator.NEQ, "active", null, context)).isTrue(); + assertThat(function.evaluate(CX_POLICY_NS + "Dismantler", Operator.NEQ, "active", null, context)).isTrue(); } @Test void evaluate_neq_notSatisfied() { when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createDismantlerCredential("Yugo", "Tatra").build()))); - assertThat(function.evaluate("Dismantler", Operator.NEQ, "active", null, context)).isFalse(); + assertThat(function.evaluate(CX_POLICY_NS + "Dismantler", Operator.NEQ, "active", null, context)).isFalse(); } @Test @@ -125,14 +126,14 @@ void evaluate_invalidOperators() { invalidOperators.remove(Operator.NEQ); when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createPcfCredential().build()))); - assertThat(invalidOperators).allSatisfy(invalidOperator -> assertThat(function.evaluate("Dismantler", invalidOperator, "active", null, context)).isFalse()); + assertThat(invalidOperators).allSatisfy(invalidOperator -> assertThat(function.evaluate(CX_POLICY_NS + "Dismantler", invalidOperator, "active", null, context)).isFalse()); } @Test void evaluate_rightOperandInvalid() { when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createPcfCredential().build()))); - assertThat(function.evaluate("Dismantler", Operator.EQ, "invalid", null, context)).isFalse(); + assertThat(function.evaluate(CX_POLICY_NS + "Dismantler", Operator.EQ, "invalid", null, context)).isFalse(); verify(context).reportProblem("Right-operand must be equal to 'active', but was 'invalid'"); } } @@ -144,14 +145,14 @@ class AllowedBrands { @Test void evaluate_eq_list() { when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createDismantlerCredential("Tatra", "Moskvich").build()))); - assertThat(function.evaluate("Dismantler.allowedBrands", Operator.EQ, List.of("Tatra", "Moskvich"), null, context)).isTrue(); + assertThat(function.evaluate(CX_POLICY_NS + "Dismantler.allowedBrands", Operator.EQ, List.of("Tatra", "Moskvich"), null, context)).isTrue(); } @DisplayName("Constraint (list) must credential EXACTLY - failure") @Test void evaluate_eq_list_notSatisfied() { when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createDismantlerCredential("Tatra", "Moskvich", "Lada").build()))); - assertThat(function.evaluate("Dismantler.allowedBrands", Operator.EQ, List.of("Tatra", "Moskvich"), null, context)).isFalse(); + assertThat(function.evaluate(CX_POLICY_NS + "Dismantler.allowedBrands", Operator.EQ, List.of("Tatra", "Moskvich"), null, context)).isFalse(); verify(context, never()).reportProblem(anyString()); } @@ -159,14 +160,14 @@ void evaluate_eq_list_notSatisfied() { @Test void evaluate_eq_scalar() { when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createDismantlerCredential("Yugo").build()))); - assertThat(function.evaluate("Dismantler.allowedBrands", Operator.EQ, "Yugo", null, context)).isTrue(); + assertThat(function.evaluate(CX_POLICY_NS + "Dismantler.allowedBrands", Operator.EQ, "Yugo", null, context)).isTrue(); } @DisplayName("Constraint (scalar) must credential EXACTLY - failure") @Test void evaluate_eq_scalar_notSatisfied() { when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createDismantlerCredential("Tatra").build()))); - assertThat(function.evaluate("Dismantler.allowedBrands", Operator.EQ, "Yugo", null, context)).isFalse(); + assertThat(function.evaluate(CX_POLICY_NS + "Dismantler.allowedBrands", Operator.EQ, "Yugo", null, context)).isFalse(); verify(context, never()).reportProblem(anyString()); } @@ -174,63 +175,63 @@ void evaluate_eq_scalar_notSatisfied() { @Test void evaluate_neq_satisfied() { when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createDismantlerCredential("Tatra", "Moskvich").build()))); - assertThat(function.evaluate("Dismantler.allowedBrands", Operator.NEQ, List.of("Lada", "Yugo"), null, context)).isTrue(); + assertThat(function.evaluate(CX_POLICY_NS + "Dismantler.allowedBrands", Operator.NEQ, List.of("Lada", "Yugo"), null, context)).isTrue(); when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createDismantlerCredential("Tatra", "Moskvich", "Yugo", "Lada").build()))); - assertThat(function.evaluate("Dismantler.allowedBrands", Operator.NEQ, List.of("Lada", "Yugo"), null, context)).isTrue(); + assertThat(function.evaluate(CX_POLICY_NS + "Dismantler.allowedBrands", Operator.NEQ, List.of("Lada", "Yugo"), null, context)).isTrue(); } @DisplayName("Constraint and credential must be DISJOINT - failure") @Test void evaluate_neq_notSatisfied() { when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createDismantlerCredential("Lada", "Yugo").build()))); - assertThat(function.evaluate("Dismantler.allowedBrands", Operator.NEQ, List.of("Lada", "Yugo"), null, context)).isFalse(); + assertThat(function.evaluate(CX_POLICY_NS + "Dismantler.allowedBrands", Operator.NEQ, List.of("Lada", "Yugo"), null, context)).isFalse(); } @DisplayName("Constraint and credential must INTERSECT") @Test void evaluate_isAnyOf_satisfied() { when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createDismantlerCredential("Lada").build()))); - assertThat(function.evaluate("Dismantler.allowedBrands", Operator.IS_ANY_OF, List.of("Tatra", "Moskvich", "Lada"), null, context)).isTrue(); + assertThat(function.evaluate(CX_POLICY_NS + "Dismantler.allowedBrands", Operator.IS_ANY_OF, List.of("Tatra", "Moskvich", "Lada"), null, context)).isTrue(); when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createDismantlerCredential("Moskvich", "Tatra").build()))); - assertThat(function.evaluate("Dismantler.allowedBrands", Operator.IS_ANY_OF, List.of("Lada", "Moskvich"), null, context)).isTrue(); + assertThat(function.evaluate(CX_POLICY_NS + "Dismantler.allowedBrands", Operator.IS_ANY_OF, List.of("Lada", "Moskvich"), null, context)).isTrue(); } @DisplayName("Constraint and credential must INTERSECT - failure") @Test void evaluate_isAnyOf_notSatisfied() { when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createDismantlerCredential("Gaz").build()))); - assertThat(function.evaluate("Dismantler.allowedBrands", Operator.IS_ANY_OF, List.of("Tatra", "Moskvich", "Lada"), null, context)).isFalse(); + assertThat(function.evaluate(CX_POLICY_NS + "Dismantler.allowedBrands", Operator.IS_ANY_OF, List.of("Tatra", "Moskvich", "Lada"), null, context)).isFalse(); when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createDismantlerCredential("Gaz", "Yugo").build()))); - assertThat(function.evaluate("Dismantler.allowedBrands", Operator.IS_ANY_OF, List.of("Tatra", "Moskvich", "Lada"), null, context)).isFalse(); + assertThat(function.evaluate(CX_POLICY_NS + "Dismantler.allowedBrands", Operator.IS_ANY_OF, List.of("Tatra", "Moskvich", "Lada"), null, context)).isFalse(); when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createDismantlerCredential().build()))); - assertThat(function.evaluate("Dismantler.allowedBrands", Operator.IS_ANY_OF, List.of("Tatra", "Moskvich", "Lada"), null, context)).isFalse(); + assertThat(function.evaluate(CX_POLICY_NS + "Dismantler.allowedBrands", Operator.IS_ANY_OF, List.of("Tatra", "Moskvich", "Lada"), null, context)).isFalse(); when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createDismantlerCredential("Moskvich", "Tatra").build()))); - assertThat(function.evaluate("Dismantler.allowedBrands", Operator.IS_ANY_OF, List.of(), null, context)).isFalse(); + assertThat(function.evaluate(CX_POLICY_NS + "Dismantler.allowedBrands", Operator.IS_ANY_OF, List.of(), null, context)).isFalse(); } @DisplayName("Constraint and credential must NOT INTERSECT") @Test void evaluate_isNoneOf_satisfied() { when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createDismantlerCredential("Gaz", "Yugo").build()))); - assertThat(function.evaluate("Dismantler.allowedBrands", Operator.IS_NONE_OF, List.of("Tatra", "Moskvich", "Lada"), null, context)).isTrue(); + assertThat(function.evaluate(CX_POLICY_NS + "Dismantler.allowedBrands", Operator.IS_NONE_OF, List.of("Tatra", "Moskvich", "Lada"), null, context)).isTrue(); when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createDismantlerCredential("Gaz", "Yugo").build()))); - assertThat(function.evaluate("Dismantler.allowedBrands", Operator.IS_NONE_OF, List.of(), null, context)).isTrue(); + assertThat(function.evaluate(CX_POLICY_NS + "Dismantler.allowedBrands", Operator.IS_NONE_OF, List.of(), null, context)).isTrue(); when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createDismantlerCredential().build()))); - assertThat(function.evaluate("Dismantler.allowedBrands", Operator.IS_NONE_OF, List.of("Tatra", "Moskvich", "Lada"), null, context)).isTrue(); + assertThat(function.evaluate(CX_POLICY_NS + "Dismantler.allowedBrands", Operator.IS_NONE_OF, List.of("Tatra", "Moskvich", "Lada"), null, context)).isTrue(); } @DisplayName("Constraint and credential must NOT INTERSECT - failure") @Test void evaluate_isNoneOf_notSatisfied() { when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createDismantlerCredential("Gaz", "Yugo").build()))); - assertThat(function.evaluate("Dismantler.allowedBrands", Operator.IS_NONE_OF, List.of("Tatra", "Moskvich", "Yugo"), null, context)).isFalse(); + assertThat(function.evaluate(CX_POLICY_NS + "Dismantler.allowedBrands", Operator.IS_NONE_OF, List.of("Tatra", "Moskvich", "Yugo"), null, context)).isFalse(); } @@ -238,17 +239,17 @@ void evaluate_isNoneOf_notSatisfied() { @Test void evaluate_in_satisfied() { when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createDismantlerCredential("Gaz", "Yugo").build()))); - assertThat(function.evaluate("Dismantler.allowedBrands", IN, List.of("Gaz", "Moskvich", "Yugo", "Lada"), null, context)).isTrue(); + assertThat(function.evaluate(CX_POLICY_NS + "Dismantler.allowedBrands", IN, List.of("Gaz", "Moskvich", "Yugo", "Lada"), null, context)).isTrue(); when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createDismantlerCredential("Gaz").build()))); - assertThat(function.evaluate("Dismantler.allowedBrands", IN, List.of("Gaz"), null, context)).isTrue(); + assertThat(function.evaluate(CX_POLICY_NS + "Dismantler.allowedBrands", IN, List.of("Gaz"), null, context)).isTrue(); } @DisplayName("Brand list from credential must be FULLY CONTAINED within constraint - failure") @Test void evaluate_in_notSatisfied() { when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createDismantlerCredential("Gaz", "Yugo").build()))); - assertThat(function.evaluate("Dismantler.allowedBrands", IN, List.of("Gaz", "Moskvich", "Yugo", "Lada"), null, context)).isTrue(); + assertThat(function.evaluate(CX_POLICY_NS + "Dismantler.allowedBrands", IN, List.of("Gaz", "Moskvich", "Yugo", "Lada"), null, context)).isTrue(); } @DisplayName("Illegal operator when constraint contains a list value") @@ -258,7 +259,7 @@ void evaluate_illegalOperator_constraintIsList() { var illegalOp = List.of(Operator.HAS_PART, Operator.GEQ, Operator.LEQ, Operator.GT, Operator.LT, Operator.IS_ALL_OF); assertThat(illegalOp).allSatisfy(op -> { - assertThat(function.evaluate("Dismantler.allowedBrands", op, List.of("Gaz", "Moskvich"), null, context)).isFalse(); + assertThat(function.evaluate(CX_POLICY_NS + "Dismantler.allowedBrands", op, List.of("Gaz", "Moskvich"), null, context)).isFalse(); verify(context).reportProblem("Invalid operator: this constraint only allows the following operators: [EQ, NEQ], but received '%s'.".formatted(op)); }); } @@ -273,7 +274,7 @@ void evaluate_illegalOperator_constraintIsScalar() { invalidOperators.remove(Operator.NEQ); assertThat(invalidOperators).allSatisfy(op -> { - assertThat(function.evaluate("Dismantler.allowedBrands", op, "Moskvich", null, context)).isFalse(); + assertThat(function.evaluate(CX_POLICY_NS + "Dismantler.allowedBrands", op, "Moskvich", null, context)).isFalse(); verify(context).reportProblem("Invalid operator: this constraint only allows the following operators: [EQ, NEQ], but received '%s'.".formatted(op)); }); } @@ -282,7 +283,7 @@ void evaluate_illegalOperator_constraintIsScalar() { @Test void evaluate_righOpInvalidType() { when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createDismantlerCredential("Gaz", "Yugo").build()))); - assertThat(function.evaluate("Dismantler.allowedBrands", IN, Map.of("foo", "bar"), null, context)).isFalse(); + assertThat(function.evaluate(CX_POLICY_NS + "Dismantler.allowedBrands", IN, Map.of("foo", "bar"), null, context)).isFalse(); verify(context).reportProblem(startsWith("Invalid right-operand type: expected String or List, but received:")); } } @@ -295,14 +296,14 @@ class ActivityType { @Test void evaluate_eq_list() { when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createDismantlerCredential(brands, "vehicleDismantle", "vehicleScrap").build()))); - assertThat(function.evaluate("Dismantler.activityType", Operator.EQ, List.of("vehicleDismantle", "vehicleScrap"), null, context)).isTrue(); + assertThat(function.evaluate(CX_POLICY_NS + "Dismantler.activityType", Operator.EQ, List.of("vehicleDismantle", "vehicleScrap"), null, context)).isTrue(); } @DisplayName("Constraint (list) must credential EXACTLY - failure") @Test void evaluate_eq_list_notSatisfied() { when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createDismantlerCredential(brands, "vehicleDismantle", "vehicleScrap").build()))); - assertThat(function.evaluate("Dismantler.activityType", Operator.EQ, List.of("vehicleRefurbish"), null, context)).isFalse(); + assertThat(function.evaluate(CX_POLICY_NS + "Dismantler.activityType", Operator.EQ, List.of("vehicleRefurbish"), null, context)).isFalse(); verify(context, never()).reportProblem(anyString()); } @@ -310,14 +311,14 @@ void evaluate_eq_list_notSatisfied() { @Test void evaluate_eq_scalar() { when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createDismantlerCredential(brands, "vehicleDismantle").build()))); - assertThat(function.evaluate("Dismantler.activityType", Operator.EQ, "vehicleDismantle", null, context)).isTrue(); + assertThat(function.evaluate(CX_POLICY_NS + "Dismantler.activityType", Operator.EQ, "vehicleDismantle", null, context)).isTrue(); } @DisplayName("Constraint (scalar) must credential EXACTLY - failure") @Test void evaluate_eq_scalar_notSatisfied() { when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createDismantlerCredential(brands, "vehicleDismantle").build()))); - assertThat(function.evaluate("Dismantler.activityType", Operator.EQ, "vehicleScrap", null, context)).isFalse(); + assertThat(function.evaluate(CX_POLICY_NS + "Dismantler.activityType", Operator.EQ, "vehicleScrap", null, context)).isFalse(); verify(context, never()).reportProblem(anyString()); } @@ -325,81 +326,81 @@ void evaluate_eq_scalar_notSatisfied() { @Test void evaluate_neq_satisfied() { when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createDismantlerCredential(brands, "vehicleDismantle").build()))); - assertThat(function.evaluate("Dismantler.activityType", Operator.NEQ, "vehicleScrap", null, context)).isTrue(); + assertThat(function.evaluate(CX_POLICY_NS + "Dismantler.activityType", Operator.NEQ, "vehicleScrap", null, context)).isTrue(); when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createDismantlerCredential(brands, "vehicleDismantle").build()))); - assertThat(function.evaluate("Dismantler.activityType", Operator.NEQ, List.of("vehicleScrap", "vehicleRefurbish"), null, context)).isTrue(); + assertThat(function.evaluate(CX_POLICY_NS + "Dismantler.activityType", Operator.NEQ, List.of("vehicleScrap", "vehicleRefurbish"), null, context)).isTrue(); } @DisplayName("Constraint and credential must be DISJOINT - failure") @Test void evaluate_neq_notSatisfied() { when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createDismantlerCredential(brands, "vehicleDismantle").build()))); - assertThat(function.evaluate("Dismantler.activityType", Operator.NEQ, "vehicleDismantle", null, context)).isFalse(); + assertThat(function.evaluate(CX_POLICY_NS + "Dismantler.activityType", Operator.NEQ, "vehicleDismantle", null, context)).isFalse(); when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createDismantlerCredential(brands, "vehicleDismantle").build()))); - assertThat(function.evaluate("Dismantler.activityType", Operator.NEQ, List.of("vehicleDismantle", "vehicleRefurbish"), null, context)).isTrue(); + assertThat(function.evaluate(CX_POLICY_NS + "Dismantler.activityType", Operator.NEQ, List.of("vehicleDismantle", "vehicleRefurbish"), null, context)).isTrue(); } @DisplayName("Constraint and credential must INTERSECT") @Test void evaluate_isAnyOf_satisfied() { when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createDismantlerCredential(brands, "vehicleDismantle", "vehicleScrap").build()))); - assertThat(function.evaluate("Dismantler.activityType", Operator.IS_ANY_OF, List.of("vehicleDismantle", "vehicleRefurbish"), null, context)).isTrue(); + assertThat(function.evaluate(CX_POLICY_NS + "Dismantler.activityType", Operator.IS_ANY_OF, List.of("vehicleDismantle", "vehicleRefurbish"), null, context)).isTrue(); } @DisplayName("Constraint and credential must INTERSECT - failure") @Test void evaluate_isAnyOf_notSatisfied() { when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createDismantlerCredential(brands, "vehicleDismantle", "vehicleScrap").build()))); - assertThat(function.evaluate("Dismantler.activityType", Operator.IS_ANY_OF, List.of("vehicleCrush", "vehicleRefurbish"), null, context)).isFalse(); + assertThat(function.evaluate(CX_POLICY_NS + "Dismantler.activityType", Operator.IS_ANY_OF, List.of("vehicleCrush", "vehicleRefurbish"), null, context)).isFalse(); when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createDismantlerCredential(brands, "vehicleDismantle", "vehicleScrap").build()))); - assertThat(function.evaluate("Dismantler.activityType", Operator.IS_ANY_OF, List.of(), null, context)).isFalse(); + assertThat(function.evaluate(CX_POLICY_NS + "Dismantler.activityType", Operator.IS_ANY_OF, List.of(), null, context)).isFalse(); when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createDismantlerCredential(brands).build()))); - assertThat(function.evaluate("Dismantler.activityType", Operator.IS_ANY_OF, List.of("vehicleCrush", "vehicleRefurbish"), null, context)).isFalse(); + assertThat(function.evaluate(CX_POLICY_NS + "Dismantler.activityType", Operator.IS_ANY_OF, List.of("vehicleCrush", "vehicleRefurbish"), null, context)).isFalse(); } @DisplayName("Constraint and credential must NOT INTERSECT") @Test void evaluate_isNoneOf_satisfied() { when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createDismantlerCredential(brands, "vehicleDismantle", "vehicleScrap").build()))); - assertThat(function.evaluate("Dismantler.activityType", Operator.IS_NONE_OF, List.of("vehicleRefurbish"), null, context)).isTrue(); + assertThat(function.evaluate(CX_POLICY_NS + "Dismantler.activityType", Operator.IS_NONE_OF, List.of("vehicleRefurbish"), null, context)).isTrue(); when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createDismantlerCredential(brands, "vehicleDismantle", "vehicleScrap").build()))); - assertThat(function.evaluate("Dismantler.activityType", Operator.IS_NONE_OF, List.of(), null, context)).isTrue(); + assertThat(function.evaluate(CX_POLICY_NS + "Dismantler.activityType", Operator.IS_NONE_OF, List.of(), null, context)).isTrue(); when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createDismantlerCredential(brands).build()))); - assertThat(function.evaluate("Dismantler.activityType", Operator.IS_NONE_OF, List.of("vehicleRefurbish"), null, context)).isTrue(); + assertThat(function.evaluate(CX_POLICY_NS + "Dismantler.activityType", Operator.IS_NONE_OF, List.of("vehicleRefurbish"), null, context)).isTrue(); } @DisplayName("Constraint and credential must NOT INTERSECT - failure") @Test void evaluate_isNoneOf_notSatisfied() { when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createDismantlerCredential(brands, "vehicleDismantle", "vehicleRefurbish").build()))); - assertThat(function.evaluate("Dismantler.activityType", Operator.IS_NONE_OF, List.of("vehicleRefurbish"), null, context)).isFalse(); + assertThat(function.evaluate(CX_POLICY_NS + "Dismantler.activityType", Operator.IS_NONE_OF, List.of("vehicleRefurbish"), null, context)).isFalse(); } @DisplayName("Activity list from credential must be FULLY CONTAINED within constraint") @Test void evaluate_in_satisfied() { when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createDismantlerCredential(brands, "vehicleRefurbish").build()))); - assertThat(function.evaluate("Dismantler.activityType", Operator.IN, List.of("vehicleRefurbish", "vehicleDismantle"), null, context)).isTrue(); + assertThat(function.evaluate(CX_POLICY_NS + "Dismantler.activityType", Operator.IN, List.of("vehicleRefurbish", "vehicleDismantle"), null, context)).isTrue(); when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createDismantlerCredential(brands, "vehicleDismantle").build()))); - assertThat(function.evaluate("Dismantler.activityType", Operator.IN, List.of("vehicleDismantle"), null, context)).isTrue(); + assertThat(function.evaluate(CX_POLICY_NS + "Dismantler.activityType", Operator.IN, List.of("vehicleDismantle"), null, context)).isTrue(); } @DisplayName("Activity list from credential must be FULLY CONTAINED within constraint - failure") @Test void evaluate_in_notSatisfied() { when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createDismantlerCredential(brands, "vehicleRefurbish", "vehicleScrap").build()))); - assertThat(function.evaluate("Dismantler.activityType", Operator.IN, List.of("vehicleRefurbish", "vehicleDismantle"), null, context)).isFalse(); + assertThat(function.evaluate(CX_POLICY_NS + "Dismantler.activityType", Operator.IN, List.of("vehicleRefurbish", "vehicleDismantle"), null, context)).isFalse(); when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createDismantlerCredential(brands, "vehicleScrap").build()))); - assertThat(function.evaluate("Dismantler.activityType", Operator.IN, List.of("vehicleRefurbish", "vehicleDismantle"), null, context)).isFalse(); + assertThat(function.evaluate(CX_POLICY_NS + "Dismantler.activityType", Operator.IN, List.of("vehicleRefurbish", "vehicleDismantle"), null, context)).isFalse(); } @@ -410,7 +411,7 @@ void evaluate_illegalOperator_constraintIsList() { var illegalOp = List.of(Operator.HAS_PART, Operator.GEQ, Operator.LEQ, Operator.GT, Operator.LT, Operator.IS_ALL_OF); assertThat(illegalOp).allSatisfy(op -> { - assertThat(function.evaluate("Dismantler.activityType", op, List.of("vehicleDismantle"), null, context)).isFalse(); + assertThat(function.evaluate(CX_POLICY_NS + "Dismantler.activityType", op, List.of("vehicleDismantle"), null, context)).isFalse(); }); } @@ -424,7 +425,7 @@ void evaluate_illegalOperator_constraintIsScalar() { invalidOperators.remove(Operator.NEQ); assertThat(invalidOperators).allSatisfy(op -> { - assertThat(function.evaluate("Dismantler.activityType", op, "vehicleDismantle", null, context)).isFalse(); + assertThat(function.evaluate(CX_POLICY_NS + "Dismantler.activityType", op, "vehicleDismantle", null, context)).isFalse(); verify(context).reportProblem("Invalid operator: this constraint only allows the following operators: [EQ, NEQ], but received '%s'.".formatted(op)); }); } @@ -433,7 +434,7 @@ void evaluate_illegalOperator_constraintIsScalar() { @Test void evaluate_righOpInvalidType() { when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createDismantlerCredential(brands, "vehicleDismantle").build()))); - assertThat(function.evaluate("Dismantler.activityType", IN, Map.of("foo", "bar"), null, context)).isFalse(); + assertThat(function.evaluate(CX_POLICY_NS + "Dismantler.activityType", IN, Map.of("foo", "bar"), null, context)).isFalse(); verify(context).reportProblem(startsWith("Invalid right-operand type: expected String or List, but received:")); } } diff --git a/edc-extensions/cx-policy/src/test/java/org/eclipse/tractusx/edc/policy/cx/framework/FrameworkAgreementConstraintFunctionTest.java b/edc-extensions/cx-policy/src/test/java/org/eclipse/tractusx/edc/policy/cx/framework/FrameworkAgreementConstraintFunctionTest.java index 55b0a0789..03cf56f3a 100644 --- a/edc-extensions/cx-policy/src/test/java/org/eclipse/tractusx/edc/policy/cx/framework/FrameworkAgreementConstraintFunctionTest.java +++ b/edc-extensions/cx-policy/src/test/java/org/eclipse/tractusx/edc/policy/cx/framework/FrameworkAgreementConstraintFunctionTest.java @@ -33,6 +33,7 @@ import java.util.Map; import static org.assertj.core.api.Assertions.assertThat; +import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.CX_POLICY_NS; import static org.eclipse.tractusx.edc.policy.cx.CredentialFunctions.createCredential; import static org.eclipse.tractusx.edc.policy.cx.CredentialFunctions.createPcfCredential; import static org.mockito.ArgumentMatchers.eq; @@ -63,7 +64,7 @@ void evaluate_leftOperandInvalid() { @Test void evaluate_invalidOperator() { - assertThat(function.evaluate("FrameworkAgreement.foobar", Operator.HAS_PART, "irrelevant", permission, context)).isFalse(); + assertThat(function.evaluate(CX_POLICY_NS + "FrameworkAgreement.foobar", Operator.HAS_PART, "irrelevant", permission, context)).isFalse(); verify(context).reportProblem(eq("Invalid operator: this constraint only allows the following operators: [EQ, NEQ], but received 'HAS_PART'.")); verifyNoMoreInteractions(context); } @@ -71,7 +72,7 @@ void evaluate_invalidOperator() { @Test void evaluate_noParticipantOnContext() { when(context.getContextData(eq(ParticipantAgent.class))).thenReturn(null); - assertThat(function.evaluate("FrameworkAgreement.foobar", Operator.EQ, "irrelevant", permission, context)).isFalse(); + assertThat(function.evaluate(CX_POLICY_NS + "FrameworkAgreement.foobar", Operator.EQ, "irrelevant", permission, context)).isFalse(); verify(context).reportProblem(eq("Required PolicyContext data not found: " + ParticipantAgent.class.getName())); verify(context).getContextData(eq(ParticipantAgent.class)); verifyNoMoreInteractions(context); @@ -80,7 +81,7 @@ void evaluate_noParticipantOnContext() { @Test void evaluate_vcClaimNotPresent() { when(participantAgent.getClaims()).thenReturn(Map.of()); - assertThat(function.evaluate("FrameworkAgreement.foobar", Operator.EQ, "active", permission, context)).isFalse(); + assertThat(function.evaluate(CX_POLICY_NS + "FrameworkAgreement.foobar", Operator.EQ, "active", permission, context)).isFalse(); verify(context).reportProblem(eq("ParticipantAgent did not contain a 'vc' claim.")); } @@ -89,7 +90,7 @@ void evaluate_vcClaimNotListOfCredentials() { when(participantAgent.getClaims()).thenReturn(Map.of( "vc", new Object() )); - assertThat(function.evaluate("FrameworkAgreement.foobar", Operator.EQ, "active:0.0.1", permission, context)).isFalse(); + assertThat(function.evaluate(CX_POLICY_NS + "FrameworkAgreement.foobar", Operator.EQ, "active:0.0.1", permission, context)).isFalse(); verify(context).reportProblem(eq("ParticipantAgent contains a 'vc' claim, but the type is incorrect. Expected java.util.List, received java.lang.Object.")); } @@ -98,7 +99,7 @@ void evaluate_vcClaimCredentialsEmpty() { when(participantAgent.getClaims()).thenReturn(Map.of( "vc", new ArrayList() )); - assertThat(function.evaluate("FrameworkAgreement.foobar", Operator.EQ, "active", permission, context)).isFalse(); + assertThat(function.evaluate(CX_POLICY_NS + "FrameworkAgreement.foobar", Operator.EQ, "active", permission, context)).isFalse(); verify(context).reportProblem(eq("ParticipantAgent contains a 'vc' claim but it did not contain any VerifiableCredentials.")); } @@ -107,7 +108,7 @@ void evaluate_rightOperandInvalidFormat() { when(participantAgent.getClaims()).thenReturn(Map.of( "vc", List.of(createPcfCredential().build()) )); - assertThat(function.evaluate("FrameworkAgreement.pcf", Operator.EQ, "/violate$", permission, context)).isFalse(); + assertThat(function.evaluate(CX_POLICY_NS + "FrameworkAgreement.pcf", Operator.EQ, "/violate$", permission, context)).isFalse(); verify(context).reportProblem(eq("Right-operand must contain the keyword 'active' followed by an optional version string: 'active'[:version], but was '/violate$'.")); } @@ -115,8 +116,8 @@ void evaluate_rightOperandInvalidFormat() { void evaluate_requiredCredentialNotFound() { when(participantAgent.getClaims()).thenReturn(Map.of( "vc", List.of( - createCredential("PcfCredential", "1.3.0").build(), - createCredential("PcfCredential", "1.0.0").build()) + createCredential(CX_POLICY_NS + "PcfCredential", "1.3.0").build(), + createCredential(CX_POLICY_NS + "PcfCredential", "1.0.0").build()) )); assertThat(function.evaluate("FrameworkAgreement", Operator.EQ, "someOther:1.3.0", permission, context)).isFalse(); } @@ -129,7 +130,7 @@ void evaluate_requiredCredential_wrongVersion() { createCredential("PcfCredential", "1.8.0").build(), createCredential("PcfCredential", "1.0.0").build()) )); - assertThat(function.evaluate("FrameworkAgreement", Operator.EQ, "pcf:1.3.0", permission, context)).isFalse(); + assertThat(function.evaluate(CX_POLICY_NS + "FrameworkAgreement", Operator.EQ, "pcf:1.3.0", permission, context)).isFalse(); } @Test @@ -140,7 +141,7 @@ void evaluate_requiredCredentialFound() { createCredential("SomeOtherType", "3.4.1").build() ) )); - assertThat(function.evaluate("FrameworkAgreement", Operator.EQ, "pcf", permission, context)).isTrue(); + assertThat(function.evaluate(CX_POLICY_NS + "FrameworkAgreement", Operator.EQ, "pcf", permission, context)).isTrue(); } @Test @@ -151,7 +152,7 @@ void evaluate_requiredCredentialFound_withCorrectVersion() { createCredential("PcfCredential", "1.3.0").build(), createCredential("PcfCredential", "1.0.0").build()) )); - assertThat(function.evaluate("FrameworkAgreement", Operator.EQ, "pcf:1.3.0", permission, context)).isTrue(); + assertThat(function.evaluate(CX_POLICY_NS + "FrameworkAgreement", Operator.EQ, "pcf:1.3.0", permission, context)).isTrue(); } @Test @@ -162,7 +163,7 @@ void evaluate_neq_requiredCredentialFound() { createCredential("SomeOtherType", "3.4.1").build() ) )); - assertThat(function.evaluate("FrameworkAgreement", Operator.NEQ, "sustainability", permission, context)).isTrue(); + assertThat(function.evaluate(CX_POLICY_NS + "FrameworkAgreement", Operator.NEQ, "sustainability", permission, context)).isTrue(); } @Test @@ -174,7 +175,7 @@ void evaluate_neq_oneOfManyViolates() { createCredential("SomeOtherType", "3.4.1").build() ) )); - assertThat(function.evaluate("FrameworkAgreement", Operator.NEQ, "sustainability", permission, context)).isTrue(); + assertThat(function.evaluate(CX_POLICY_NS + "FrameworkAgreement", Operator.NEQ, "sustainability", permission, context)).isTrue(); } @Test @@ -184,7 +185,7 @@ void evaluate_neq_oneViolates() { createCredential("SustainabilityCredential", "6.0.0").build() ) )); - assertThat(function.evaluate("FrameworkAgreement", Operator.NEQ, "sustainability", permission, context)).isFalse(); + assertThat(function.evaluate(CX_POLICY_NS + "FrameworkAgreement", Operator.NEQ, "sustainability", permission, context)).isFalse(); } @Test @@ -195,7 +196,7 @@ void evaluate_neq_requiredCredentialFound_withCorrectVersion() { createCredential("FooBarCredential", "1.3.0").build(), createCredential("BarBazCredential", "1.0.0").build()) )); - assertThat(function.evaluate("FrameworkAgreement", Operator.NEQ, "sustainability:1.3.0", permission, context)).isTrue(); + assertThat(function.evaluate(CX_POLICY_NS + "FrameworkAgreement", Operator.NEQ, "sustainability:1.3.0", permission, context)).isTrue(); } @@ -206,7 +207,7 @@ void evaluate_leftOperand_notContainSubtype() { when(participantAgent.getClaims()).thenReturn(Map.of( "vc", List.of(createPcfCredential().build()) )); - assertThat(function.evaluate("FrameworkAgreement.", Operator.EQ, "active:0.4.2", permission, context)).isFalse(); + assertThat(function.evaluate(CX_POLICY_NS + "FrameworkAgreement.", Operator.EQ, "active:0.4.2", permission, context)).isFalse(); verify(context).reportProblem(eq("Left-operand must contain the sub-type 'FrameworkAgreement.'.")); } @@ -215,7 +216,7 @@ void evaluate_leftOperand_notContainFrameworkLiteral() { when(participantAgent.getClaims()).thenReturn(Map.of( "vc", List.of(createPcfCredential().build()) )); - assertThat(function.evaluate("foobar.pcf", Operator.EQ, "active:0.4.2", permission, context)).isFalse(); + assertThat(function.evaluate(CX_POLICY_NS + "foobar.pcf", Operator.EQ, "active:0.4.2", permission, context)).isFalse(); verify(context).reportProblem(startsWith("Constraint left-operand must start with 'FrameworkAgreement' but was")); } @@ -224,7 +225,7 @@ void evaluate_leftOperand_notStartsWithFrameworkLiteral() { when(participantAgent.getClaims()).thenReturn(Map.of( "vc", List.of(createPcfCredential().build()) )); - assertThat(function.evaluate("foobarFrameworkAgreement.pcf", Operator.EQ, "active:0.4.2", permission, context)).isFalse(); + assertThat(function.evaluate(CX_POLICY_NS + "foobarFrameworkAgreement.pcf", Operator.EQ, "active:0.4.2", permission, context)).isFalse(); verify(context).reportProblem(startsWith("Constraint left-operand must start with 'FrameworkAgreement' but was")); } @@ -233,7 +234,7 @@ void evaluate_rightOperand_notStartWithActiveLiteral() { when(participantAgent.getClaims()).thenReturn(Map.of( "vc", List.of(createPcfCredential().build()) )); - assertThat(function.evaluate("FrameworkAgreement.pcf", Operator.EQ, "violates", permission, context)).isFalse(); + assertThat(function.evaluate(CX_POLICY_NS + "FrameworkAgreement.pcf", Operator.EQ, "violates", permission, context)).isFalse(); verify(context).reportProblem(eq("Right-operand must contain the keyword 'active' followed by an optional version string: 'active'[:version], but was 'violates'.")); } @@ -242,8 +243,8 @@ void evaluate_rightOperandWithVersion() { when(participantAgent.getClaims()).thenReturn(Map.of( "vc", List.of(createPcfCredential().build()) )); - assertThat(function.evaluate("FrameworkAgreement.pcf", Operator.EQ, "active:1.0.0", permission, context)).isTrue(); - assertThat(function.evaluate("FrameworkAgreement.pcf", Operator.EQ, "active:5.3.1", permission, context)).isFalse(); + assertThat(function.evaluate(CX_POLICY_NS + "FrameworkAgreement.pcf", Operator.EQ, "active:1.0.0", permission, context)).isTrue(); + assertThat(function.evaluate(CX_POLICY_NS + "FrameworkAgreement.pcf", Operator.EQ, "active:5.3.1", permission, context)).isFalse(); } @Test @@ -251,7 +252,7 @@ void evaluate_rightOperand() { when(participantAgent.getClaims()).thenReturn(Map.of( "vc", List.of(createPcfCredential().build()) )); - assertThat(function.evaluate("FrameworkAgreement.pcf", Operator.EQ, "active", permission, context)).isTrue(); + assertThat(function.evaluate(CX_POLICY_NS + "FrameworkAgreement.pcf", Operator.EQ, "active", permission, context)).isTrue(); } } @@ -271,7 +272,7 @@ void evaluate_rightOperand_onlySubtype() { when(participantAgent.getClaims()).thenReturn(Map.of( "vc", List.of(createPcfCredential().build()) )); - assertThat(function.evaluate("FrameworkAgreement", Operator.EQ, "pcf", permission, context)).isTrue(); + assertThat(function.evaluate(CX_POLICY_NS + "FrameworkAgreement", Operator.EQ, "pcf", permission, context)).isTrue(); } @Test @@ -279,8 +280,8 @@ void evaluate_rightOperand_withVersion() { when(participantAgent.getClaims()).thenReturn(Map.of( "vc", List.of(createPcfCredential().build()) )); - assertThat(function.evaluate("FrameworkAgreement", Operator.EQ, "pcf:1.0.0", permission, context)).isTrue(); - assertThat(function.evaluate("FrameworkAgreement", Operator.EQ, "pcf:4.2.0", permission, context)).isFalse(); + assertThat(function.evaluate(CX_POLICY_NS + "FrameworkAgreement", Operator.EQ, "pcf:1.0.0", permission, context)).isTrue(); + assertThat(function.evaluate(CX_POLICY_NS + "FrameworkAgreement", Operator.EQ, "pcf:4.2.0", permission, context)).isFalse(); } @Test diff --git a/edc-extensions/cx-policy/src/test/java/org/eclipse/tractusx/edc/policy/cx/membership/MembershipConstraintFunctionTest.java b/edc-extensions/cx-policy/src/test/java/org/eclipse/tractusx/edc/policy/cx/membership/MembershipConstraintFunctionTest.java index e327f9b6b..69839f3e6 100644 --- a/edc-extensions/cx-policy/src/test/java/org/eclipse/tractusx/edc/policy/cx/membership/MembershipConstraintFunctionTest.java +++ b/edc-extensions/cx-policy/src/test/java/org/eclipse/tractusx/edc/policy/cx/membership/MembershipConstraintFunctionTest.java @@ -29,9 +29,11 @@ import java.util.Map; import static org.assertj.core.api.Assertions.assertThat; +import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.CX_POLICY_NS; import static org.eclipse.tractusx.edc.policy.cx.CredentialFunctions.createMembershipCredential; import static org.eclipse.tractusx.edc.policy.cx.CredentialFunctions.createPcfCredential; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.startsWith; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -52,48 +54,48 @@ void setup() { @Test void evaluate_leftOperandInvalid() { when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createMembershipCredential().build()))); - assertThat(function.evaluate("foobar", Operator.EQ, "active", null, context)).isFalse(); - verify(context).reportProblem(eq("Invalid left-operand: must be 'Membership', but was 'foobar'")); + assertThat(function.evaluate(CX_POLICY_NS + "foobar", Operator.EQ, "active", null, context)).isFalse(); + verify(context).reportProblem(startsWith("Invalid left-operand: must be 'Membership', but was")); } @Test void evaluate_noParticipantAgentOnContext() { when(context.getContextData(eq(ParticipantAgent.class))).thenReturn(null); - assertThat(function.evaluate("Membership", Operator.EQ, "active", null, context)).isFalse(); + assertThat(function.evaluate(CX_POLICY_NS + "Membership", Operator.EQ, "active", null, context)).isFalse(); verify(context).reportProblem("Required PolicyContext data not found: org.eclipse.edc.spi.agent.ParticipantAgent"); } @Test void evaluate_noVcClaimOnParticipantAgent() { - assertThat(function.evaluate("Membership", Operator.EQ, "active", null, context)).isFalse(); + assertThat(function.evaluate(CX_POLICY_NS + "Membership", Operator.EQ, "active", null, context)).isFalse(); verify(context).reportProblem(eq("ParticipantAgent did not contain a 'vc' claim.")); } @Test void evaluate_vcClaimEmpty() { when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of())); - assertThat(function.evaluate("Membership", Operator.EQ, "active", null, context)).isFalse(); + assertThat(function.evaluate(CX_POLICY_NS + "Membership", Operator.EQ, "active", null, context)).isFalse(); verify(context).reportProblem(eq("ParticipantAgent contains a 'vc' claim but it did not contain any VerifiableCredentials.")); } @Test void evaluate_vcClaimNotList() { when(participantAgent.getClaims()).thenReturn(Map.of("vc", new Object())); - assertThat(function.evaluate("Membership", Operator.EQ, "active", null, context)).isFalse(); + assertThat(function.evaluate(CX_POLICY_NS + "Membership", Operator.EQ, "active", null, context)).isFalse(); verify(context).reportProblem(eq("ParticipantAgent contains a 'vc' claim, but the type is incorrect. Expected java.util.List, received java.lang.Object.")); } @Test void evaluate_rightOperandNotActive() { when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createMembershipCredential().build()))); - assertThat(function.evaluate("Membership", Operator.EQ, "invalid", null, context)).isFalse(); + assertThat(function.evaluate(CX_POLICY_NS + "Membership", Operator.EQ, "invalid", null, context)).isFalse(); verify(context).reportProblem(eq("Right-operand must be equal to 'active', but was 'invalid'")); } @Test void evaluate_whenSingleCredentialFound() { when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createMembershipCredential().build()))); - assertThat(function.evaluate("Membership", Operator.EQ, "active", null, context)).isTrue(); + assertThat(function.evaluate(CX_POLICY_NS + "Membership", Operator.EQ, "active", null, context)).isTrue(); } @Test @@ -101,12 +103,12 @@ void evaluate_whenMultipleCredentialsFound() { when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createMembershipCredential().build(), createMembershipCredential().build(), createPcfCredential().build()))); - assertThat(function.evaluate("Membership", Operator.EQ, "active", null, context)).isTrue(); + assertThat(function.evaluate(CX_POLICY_NS + "Membership", Operator.EQ, "active", null, context)).isTrue(); } @Test void evaluate_whenCredentialNotFound() { when(participantAgent.getClaims()).thenReturn(Map.of("vc", List.of(createPcfCredential().build()))); - assertThat(function.evaluate("Membership", Operator.EQ, "active", null, context)).isFalse(); + assertThat(function.evaluate(CX_POLICY_NS + "Membership", Operator.EQ, "active", null, context)).isFalse(); } } \ No newline at end of file diff --git a/edc-extensions/iatp/tx-iatp/src/main/java/org/eclipse/tractusx/edc/iam/iatp/scope/CredentialScopeExtractor.java b/edc-extensions/iatp/tx-iatp/src/main/java/org/eclipse/tractusx/edc/iam/iatp/scope/CredentialScopeExtractor.java index a1f0ec91d..48654a1e6 100644 --- a/edc-extensions/iatp/tx-iatp/src/main/java/org/eclipse/tractusx/edc/iam/iatp/scope/CredentialScopeExtractor.java +++ b/edc-extensions/iatp/tx-iatp/src/main/java/org/eclipse/tractusx/edc/iam/iatp/scope/CredentialScopeExtractor.java @@ -25,17 +25,17 @@ import java.util.Set; -import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.TX_CREDENTIAL_NAMESPACE; +import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.CX_POLICY_NS; import static org.eclipse.tractusx.edc.iam.iatp.TxIatpConstants.CREDENTIAL_TYPE_NAMESPACE; /** * Extract credentials from the policy constraints *

    * Extract and map from the Credential DSL the required credential type - * The left operand should be bound to the namespace {@link org.eclipse.tractusx.edc.edr.spi.CoreConstants#TX_CREDENTIAL_NAMESPACE} + * The left operand should be bound to the namespace {@link org.eclipse.tractusx.edc.edr.spi.CoreConstants#CX_CREDENTIAL_NS} */ public class CredentialScopeExtractor implements ScopeExtractor { - public static final String FRAMEWORK_CREDENTIAL_PREFIX = "FrameworkAgreement."; + public static final String FRAMEWORK_CREDENTIAL_PREFIX = "FrameworkAgreement"; public static final String SCOPE_FORMAT = "%s:%s:read"; public static final String CREDENTIAL_FORMAT = "%sCredential"; @@ -45,17 +45,41 @@ public CredentialScopeExtractor() { @Override public Set extractScopes(Object leftValue, Operator operator, Object rightValue, PolicyContext context) { Set scopes = Set.of(); - if (leftValue instanceof String leftOperand && leftOperand.startsWith(TX_CREDENTIAL_NAMESPACE)) { - var credential = leftOperand.replace(TX_CREDENTIAL_NAMESPACE, ""); - if (credential.startsWith(FRAMEWORK_CREDENTIAL_PREFIX)) { - credential = credential.replace(FRAMEWORK_CREDENTIAL_PREFIX, ""); - } - scopes = Set.of(SCOPE_FORMAT.formatted(CREDENTIAL_TYPE_NAMESPACE, CREDENTIAL_FORMAT.formatted(capitalize(credential)))); + if (leftValue instanceof String leftOperand && leftOperand.startsWith(CX_POLICY_NS)) { + leftOperand = leftOperand.replace(CX_POLICY_NS, ""); + var credentialType = extractCredentialType(leftOperand, rightValue); + scopes = Set.of(SCOPE_FORMAT.formatted(CREDENTIAL_TYPE_NAMESPACE, CREDENTIAL_FORMAT.formatted(capitalize(credentialType)))); } return scopes; } + /** + * Possible values for credential: + *

      + *
    • FrameworkAgreement -> subtype is encoded in rightValue, return subtype from rightOperand
    • + *
    • FrameworkAgreement.[subtype] -> return subtype
    • + *
    • Dismantler -> return "Dismantler"
    • + *
    • Dismantler.[expr] -> return "Dismantler"
    • + *
    • Membership -> return "Membership"
    • + *
    + */ + private String extractCredentialType(String leftOperand, Object rightValue) { + if (leftOperand.equals(FRAMEWORK_CREDENTIAL_PREFIX)) { //this is the "new" notation, where the subtype is encoded in the right operand + var rightOperand = rightValue.toString(); + var ix = rightOperand.indexOf(":"); + return ix > 0 ? rightOperand.substring(0, ix) : rightOperand; + } + // for FrameworkAgreement.xyz we need the "xyz" part + if (leftOperand.startsWith(FRAMEWORK_CREDENTIAL_PREFIX + ".")) { + leftOperand = leftOperand.replace(FRAMEWORK_CREDENTIAL_PREFIX + ".", ""); + } else { //for all others, e.g. Dismantler.activityType, we only need the "Dismantler" part + var ix = leftOperand.indexOf("."); + leftOperand = ix > 0 ? leftOperand.substring(0, ix) : leftOperand; + } + return leftOperand; + } + private String capitalize(String input) { return input.substring(0, 1).toUpperCase() + input.substring(1).toLowerCase(); } diff --git a/edc-extensions/iatp/tx-iatp/src/test/java/org/eclipse/tractusx/edc/iam/iatp/scope/CredentialScopeExtractorTest.java b/edc-extensions/iatp/tx-iatp/src/test/java/org/eclipse/tractusx/edc/iam/iatp/scope/CredentialScopeExtractorTest.java index f20f52c0f..3130668fc 100644 --- a/edc-extensions/iatp/tx-iatp/src/test/java/org/eclipse/tractusx/edc/iam/iatp/scope/CredentialScopeExtractorTest.java +++ b/edc-extensions/iatp/tx-iatp/src/test/java/org/eclipse/tractusx/edc/iam/iatp/scope/CredentialScopeExtractorTest.java @@ -42,7 +42,7 @@ void setup() { void verify_extractScopes() { var builder = TokenParameters.Builder.newInstance(); var ctx = PolicyContextImpl.Builder.newInstance().additional(TokenParameters.Builder.class, builder).build(); - var scopes = extractor.extractScopes(CoreConstants.TX_CREDENTIAL_NAMESPACE + FRAMEWORK_CREDENTIAL_PREFIX + "pfc", null, null, ctx); + var scopes = extractor.extractScopes(CoreConstants.CX_POLICY_NS + FRAMEWORK_CREDENTIAL_PREFIX + ".pfc", null, null, ctx); assertThat(scopes).contains(CREDENTIAL_TYPE_NAMESPACE + ":PfcCredential:read"); } diff --git a/edc-tests/e2e-tests/build.gradle.kts b/edc-tests/e2e-tests/build.gradle.kts index 52ae1929c..a9c9730c2 100644 --- a/edc-tests/e2e-tests/build.gradle.kts +++ b/edc-tests/e2e-tests/build.gradle.kts @@ -57,6 +57,7 @@ dependencies { testImplementation(libs.testcontainers.postgres) testImplementation(libs.testcontainers.vault) testImplementation(libs.bouncyCastle.bcpkixJdk18on) + testImplementation(project(":spi:core-spi")) testCompileOnly(project(":edc-tests:runtime:extensions")) testCompileOnly(project(":edc-tests:runtime:runtime-memory")) diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/helpers/IatpHelperFunctions.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/helpers/IatpHelperFunctions.java index 81e3cc461..8bc16089b 100644 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/helpers/IatpHelperFunctions.java +++ b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/helpers/IatpHelperFunctions.java @@ -95,9 +95,6 @@ public static JsonObject membershipSubject(String did, String id) { return Json.createObjectBuilder() .add("type", "MembershipCredential") .add("holderIdentifier", id) - .add("status", "Active") - .add("memberOf", "Catena-X") - .add("startTime", Instant.now().toString()) .add("id", did) .build(); @@ -107,7 +104,6 @@ public static JsonObject frameworkAgreementSubject(String did, String id, String return Json.createObjectBuilder() .add("type", type) .add("holderIdentifier", id) - .add("useCaseType", type) .add("contractVersion", "1.0.0") .add("contractTemplate", "https://public.catena-x.org/contracts/traceabilty.v1.pdf") .add("id", did) @@ -126,7 +122,7 @@ private static JsonArray context() { return Json.createArrayBuilder() .add("https://www.w3.org/2018/credentials/v1") .add("https://w3id.org/security/suites/jws-2020/v1") - .add("https://catenax-ng.github.io/product-core-schemas/businessPartnerData.json") + .add("https://w3id.org/catenax/credentials") .build(); } @@ -169,6 +165,7 @@ private static void storeCredentials(DataspaceIssuer issuer, IatpParticipant par private static List issueCredentials(DataspaceIssuer issuer, IatpParticipant participant, JsonLd jsonLd) { return List.of( issuer.issueMembershipCredential(participant, jsonLd), + issuer.issueDismantlerCredential(participant, jsonLd), issuer.issueFrameworkCredential(participant, jsonLd, "PcfCredential")); } diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/helpers/PolicyHelperFunctions.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/helpers/PolicyHelperFunctions.java index fbff919f0..2c7f62c04 100644 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/helpers/PolicyHelperFunctions.java +++ b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/helpers/PolicyHelperFunctions.java @@ -48,7 +48,6 @@ public class PolicyHelperFunctions { public static final String TX_NAMESPACE = "https://w3id.org/tractusx/v0.0.1/ns/"; - public static final String TX_CREDENTIAL_NAMESPACE = "https://w3id.org/tractusx/credentials/v0.0.1/ns/"; private static final String ODRL_JSONLD = "http://www.w3.org/ns/odrl.jsonld"; private static final String BUSINESS_PARTNER_EVALUATION_KEY = "BusinessPartnerNumber"; @@ -58,41 +57,47 @@ public class PolicyHelperFunctions { private static final ObjectMapper MAPPER = JacksonJsonLd.createObjectMapper(); - public static JsonObject bpnGroupPolicy(Operator operator, String... allowedGroups) { return bpnGroupPolicy(operator.getOdrlRepresentation(), allowedGroups); } - private static JsonObject bpnGroupPolicy(String operator, String... allowedGroups) { + /** + * Creates a {@link PolicyDefinition} using the given ID, that contains equality constraints for each of the given BusinessPartnerNumbers: + * each BPN is converted into an {@link AtomicConstraint} {@code BusinessPartnerNumber EQ [BPN]}. + */ + public static JsonObject frameworkPolicy(String id, Map permissions) { + return policyDefinitionBuilder(frameworkPolicy(permissions)) + .add(ID, id) + .build(); + } - var groupConstraint = atomicConstraint(BUSINESS_PARTNER_CONSTRAINT_KEY, operator, Arrays.asList(allowedGroups)); + public static JsonObject frameworkPolicy(Map permissions) { + return Json.createObjectBuilder() + .add(CONTEXT, ODRL_JSONLD) + .add(TYPE, "Set") + .add("permission", Json.createArrayBuilder() + .add(frameworkPermission(permissions))) + .build(); + } + + public static JsonObject frameworkPolicy(String leftOperand, Operator operator, Object rightOperand) { + var constraint = atomicConstraint(leftOperand, operator.getOdrlRepresentation(), rightOperand); var permission = Json.createObjectBuilder() .add("action", "use") .add("constraint", Json.createObjectBuilder() .add(TYPE, ODRL_LOGICAL_CONSTRAINT_TYPE) - .add("or", groupConstraint) + .add("or", constraint) .build()) .build(); return Json.createObjectBuilder() .add(CONTEXT, ODRL_JSONLD) .add(TYPE, "Set") - .add("permission", permission) - .build(); - } - - /** - * Creates a {@link PolicyDefinition} using the given ID, that contains equality constraints for each of the given BusinessPartnerNumbers: - * each BPN is converted into an {@link AtomicConstraint} {@code BusinessPartnerNumber EQ [BPN]}. - */ - public static JsonObject frameworkPolicy(String id, Map permissions) { - return policyDefinitionBuilder(frameworkPolicy(permissions)) - .add(ID, id) + .add("permission", Json.createArrayBuilder().add(permission)) .build(); } - /** * Creates a {@link PolicyDefinition} using the given ID, that contains equality constraints for each of the given BusinessPartnerNumbers: * each BPN is converted into an {@link AtomicConstraint} {@code BusinessPartnerNumber EQ [BPN]}. @@ -106,16 +111,6 @@ public static JsonObject frameworkTemplatePolicy(String id, String frameworkKind } } - - private static String fetchFrameworkTemplate() { - try (var stream = PolicyHelperFunctions.class.getClassLoader().getResourceAsStream("framework-policy.json")) { - return new String(stream.readAllBytes(), StandardCharsets.UTF_8); - } catch (IOException e) { - throw new RuntimeException(e); - } - - } - public static JsonObjectBuilder policyDefinitionBuilder() { return Json.createObjectBuilder() .add(TYPE, EDC_NAMESPACE + "PolicyDefinitionDto"); @@ -135,6 +130,35 @@ public static JsonObject bnpPolicy(String... bnps) { .build(); } + + private static JsonObject bpnGroupPolicy(String operator, String... allowedGroups) { + + var groupConstraint = atomicConstraint(BUSINESS_PARTNER_CONSTRAINT_KEY, operator, Arrays.asList(allowedGroups)); + + var permission = Json.createObjectBuilder() + .add("action", "use") + .add("constraint", Json.createObjectBuilder() + .add(TYPE, ODRL_LOGICAL_CONSTRAINT_TYPE) + .add("or", groupConstraint) + .build()) + .build(); + + return Json.createObjectBuilder() + .add(CONTEXT, ODRL_JSONLD) + .add(TYPE, "Set") + .add("permission", permission) + .build(); + } + + private static String fetchFrameworkTemplate() { + try (var stream = PolicyHelperFunctions.class.getClassLoader().getResourceAsStream("framework-policy.json")) { + return new String(stream.readAllBytes(), StandardCharsets.UTF_8); + } catch (IOException e) { + throw new RuntimeException(e); + } + + } + private static JsonObject permission(String... bpns) { var bpnConstraints = Stream.of(bpns) @@ -150,15 +174,6 @@ private static JsonObject permission(String... bpns) { .build(); } - public static JsonObject frameworkPolicy(Map permissions) { - return Json.createObjectBuilder() - .add(CONTEXT, ODRL_JSONLD) - .add(TYPE, "Set") - .add("permission", Json.createArrayBuilder() - .add(frameworkPermission(permissions))) - .build(); - } - private static JsonObject frameworkPermission(Map permissions) { var constraints = permissions.entrySet().stream() @@ -180,8 +195,8 @@ private static JsonObject atomicConstraint(String leftOperand, String operator, .add("leftOperand", leftOperand) .add("operator", operator); - if (rightOperand instanceof Collection) { - builder.add("rightOperand", ((Collection) rightOperand).stream().map(Object::toString).collect(Collectors.joining(","))); + if (rightOperand instanceof Collection coll) { + builder.add("rightOperand", coll.stream().map(Object::toString).collect(Collectors.joining(","))); } else { builder.add("rightOperand", rightOperand.toString()); } diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/tx/iatp/DataspaceIssuer.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/tx/iatp/DataspaceIssuer.java index 887e53211..8bb537034 100644 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/tx/iatp/DataspaceIssuer.java +++ b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/tx/iatp/DataspaceIssuer.java @@ -24,6 +24,7 @@ import com.nimbusds.jose.jwk.Curve; import com.nimbusds.jose.jwk.ECKey; import com.nimbusds.jose.jwk.JWK; +import jakarta.json.Json; import jakarta.json.JsonObject; import org.eclipse.edc.iam.did.spi.document.DidDocument; import org.eclipse.edc.iam.did.spi.document.VerificationMethod; @@ -107,12 +108,26 @@ public VerifiableCredentialResource issueMembershipCredential(IatpParticipant pa () -> membershipSubject(participant.didUrl(), participant.getBpn())); } - public VerifiableCredentialResource issueFrameworkCredential(IatpParticipant participant, JsonLd jsonLd, String type) { - return issueCredential(participant, jsonLd, "UseCaseFrameworkCondition", () -> CredentialSubject.Builder.newInstance() + public VerifiableCredentialResource issueDismantlerCredential(IatpParticipant participant, JsonLd jsonLd) { + return issueCredential(participant, jsonLd, "DismantlerCredential", () -> CredentialSubject.Builder.newInstance() + .claim("holderIdentifier", participant.didUrl()) + .claim("activityType", "vehicleDismantle") + .claim("allowedVehicleBrands", List.of("Moskvich", "Lada")) + .build(), + () -> Json.createObjectBuilder() + .add("type", "MembershipCredential") + .add("holderIdentifier", participant.didUrl()) + .add("activityType", "vehicleDismantle") + .add("allowedVehicleBrands", Json.createArrayBuilder().add("Moskvich").add("Lada").build()) + .add("id", participant.didUrl()) + .build()); + } + + public VerifiableCredentialResource issueFrameworkCredential(IatpParticipant participant, JsonLd jsonLd, String credentialType) { + return issueCredential(participant, jsonLd, credentialType, () -> CredentialSubject.Builder.newInstance() .claim("holderIdentifier", participant.getBpn()) - .claim("useCaseType", type) .build(), - () -> frameworkAgreementSubject(participant.didUrl(), participant.getBpn(), type)); + () -> frameworkAgreementSubject(participant.didUrl(), participant.getBpn(), credentialType)); } diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/AbstractHttpConsumerPullWithProxyTest.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/AbstractHttpConsumerPullWithProxyTest.java index 9f33897de..27043b3ea 100644 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/AbstractHttpConsumerPullWithProxyTest.java +++ b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/AbstractHttpConsumerPullWithProxyTest.java @@ -57,7 +57,7 @@ public abstract class AbstractHttpConsumerPullWithProxyTest { .id(PLATO_BPN) .build(); - private MockWebServer server; + protected MockWebServer server; @BeforeEach void setup() throws IOException { diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/DimHttpConsumerPullWithProxyInMemoryTest.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/DimHttpConsumerPullWithProxyInMemoryTest.java index 7a377bba7..98c938079 100644 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/DimHttpConsumerPullWithProxyInMemoryTest.java +++ b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/DimHttpConsumerPullWithProxyInMemoryTest.java @@ -46,8 +46,8 @@ import java.util.function.Supplier; import static org.eclipse.edc.junit.testfixtures.TestUtils.getFreePort; +import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.CX_CREDENTIAL_NS; import static org.eclipse.tractusx.edc.helpers.IatpHelperFunctions.configureParticipant; -import static org.eclipse.tractusx.edc.helpers.PolicyHelperFunctions.TX_CREDENTIAL_NAMESPACE; import static org.eclipse.tractusx.edc.helpers.PolicyHelperFunctions.frameworkPolicy; @EndToEndTest @@ -130,7 +130,7 @@ void setup() throws IOException { @Override protected JsonObject createContractPolicy(String bpn) { - return frameworkPolicy(Map.of(TX_CREDENTIAL_NAMESPACE + "Membership", "active")); + return frameworkPolicy(Map.of(CX_CREDENTIAL_NS + "Membership", "active")); } } diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/IatpHttpConsumerPullWithProxyInMemoryTest.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/IatpHttpConsumerPullWithProxyInMemoryTest.java index cc8c2e3ec..e87631e18 100644 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/IatpHttpConsumerPullWithProxyInMemoryTest.java +++ b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/IatpHttpConsumerPullWithProxyInMemoryTest.java @@ -19,24 +19,44 @@ package org.eclipse.tractusx.edc.tests.transfer; +import jakarta.json.Json; import jakarta.json.JsonObject; +import okhttp3.mockwebserver.MockResponse; +import org.eclipse.edc.connector.transfer.spi.types.TransferProcessStates; import org.eclipse.edc.iam.did.spi.document.DidDocument; import org.eclipse.edc.junit.annotations.EndToEndTest; +import org.eclipse.edc.policy.model.Operator; +import org.eclipse.edc.spi.types.domain.edr.EndpointDataReference; import org.eclipse.tractusx.edc.lifecycle.ParticipantRuntime; import org.eclipse.tractusx.edc.lifecycle.tx.iatp.DataspaceIssuer; import org.eclipse.tractusx.edc.lifecycle.tx.iatp.IatpParticipant; import org.eclipse.tractusx.edc.lifecycle.tx.iatp.SecureTokenService; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.RegisterExtension; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.ArgumentsProvider; +import org.junit.jupiter.params.provider.ArgumentsSource; import java.io.IOException; import java.util.HashMap; +import java.util.List; import java.util.Map; - +import java.util.concurrent.atomic.AtomicReference; +import java.util.stream.Stream; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.awaitility.Awaitility.await; +import static org.awaitility.pollinterval.FibonacciPollInterval.fibonacci; +import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.CX_CREDENTIAL_NS; +import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.CX_POLICY_NS; import static org.eclipse.tractusx.edc.helpers.IatpHelperFunctions.configureParticipant; -import static org.eclipse.tractusx.edc.helpers.PolicyHelperFunctions.TX_CREDENTIAL_NAMESPACE; import static org.eclipse.tractusx.edc.helpers.PolicyHelperFunctions.frameworkPolicy; +import static org.eclipse.tractusx.edc.helpers.TransferProcessHelperFunctions.createProxyRequest; +import static org.eclipse.tractusx.edc.tests.TestCommon.ASYNC_TIMEOUT; @EndToEndTest public class IatpHttpConsumerPullWithProxyInMemoryTest extends AbstractHttpConsumerPullWithProxyTest { @@ -94,7 +114,125 @@ void setup() throws IOException { @Override protected JsonObject createContractPolicy(String bpn) { - return frameworkPolicy(Map.of(TX_CREDENTIAL_NAMESPACE + "Membership", "active")); + return frameworkPolicy(Map.of(CX_CREDENTIAL_NS + "Membership", "active")); + } + + @DisplayName("Contract policy is fulfilled") + @ParameterizedTest(name = "{1}") + @ArgumentsSource(ValidContractPolicyProvider.class) + void transferData_whenContractPolicyFulfilled(JsonObject contractPolicy, String description) throws IOException, InterruptedException { + var assetId = "api-asset-1"; + var url = server.url("/mock/api"); + server.start(); + + var authCodeHeaderName = "test-authkey"; + var authCode = "test-authcode"; + + Map dataAddress = Map.of( + "baseUrl", url.toString(), + "type", "HttpData", + "contentType", "application/json", + "authKey", authCodeHeaderName, + "authCode", authCode + ); + + PLATO.createAsset(assetId, Map.of(), dataAddress); + + var accessPolicyId = PLATO.createPolicyDefinition(createAccessPolicy(SOKRATES.getBpn())); + var contractPolicyId = PLATO.createPolicyDefinition(contractPolicy); + PLATO.createContractDefinition(assetId, "def-1", accessPolicyId, contractPolicyId); + var transferProcessId = SOKRATES.requestAsset(PLATO, assetId, Json.createObjectBuilder().build(), createProxyRequest()); + + var edr = new AtomicReference(); + + // wait until transfer process completes + await().pollInterval(fibonacci()) + .atMost(ASYNC_TIMEOUT) + .untilAsserted(() -> { + var tpState = SOKRATES.getTransferProcessState(transferProcessId); + assertThat(tpState).isNotNull().isEqualTo(TransferProcessStates.STARTED.toString()); + }); + + // wait until EDC is available on the consumer side + server.enqueue(new MockResponse().setBody("test response").setResponseCode(200)); + await().pollInterval(fibonacci()) + .atMost(ASYNC_TIMEOUT) + .untilAsserted(() -> { + edr.set(SOKRATES.edrs().getDataReferenceFromBackend(transferProcessId)); + assertThat(edr).isNotNull(); + }); + + // pull data out of provider's backend service: + // Cons-DP -> Prov-DP -> Prov-backend + assertThat(SOKRATES.data().pullData(edr.get(), Map.of())).isEqualTo("test response"); + var rq = server.takeRequest(); + assertThat(rq.getHeader(authCodeHeaderName)).isEqualTo(authCode); + assertThat(rq.getHeader("Edc-Contract-Agreement-Id")).isEqualTo(edr.get().getContractId()); + assertThat(rq.getHeader("Edc-Bpn")).isEqualTo(SOKRATES.getBpn()); + assertThat(rq.getMethod()).isEqualToIgnoringCase("GET"); + } + + @DisplayName("Contract policy is NOT fulfilled") + @ParameterizedTest(name = "{1}") + @ArgumentsSource(InvalidContractPolicyProvider.class) + void transferData_whenContractPolicyNotFulfilled(JsonObject contractPolicy, String description) throws IOException, InterruptedException { + var assetId = "api-asset-1"; + var url = server.url("/mock/api"); + server.start(); + + var authCodeHeaderName = "test-authkey"; + var authCode = "test-authcode"; + + Map dataAddress = Map.of( + "baseUrl", url.toString(), + "type", "HttpData", + "contentType", "application/json", + "authKey", authCodeHeaderName, + "authCode", authCode + ); + + PLATO.createAsset(assetId, Map.of(), dataAddress); + + var accessPolicyId = PLATO.createPolicyDefinition(createAccessPolicy(SOKRATES.getBpn())); + var contractPolicyId = PLATO.createPolicyDefinition(contractPolicy); + PLATO.createContractDefinition(assetId, "def-1", accessPolicyId, contractPolicyId); + var negotiationId = SOKRATES.initContractNegotiation(PLATO, assetId); + + await().pollInterval(fibonacci()) + .atMost(ASYNC_TIMEOUT) + .untilAsserted(() -> { + assertThat(SOKRATES.getContractNegotiationError(negotiationId)).isNotNull(); + }); + } + + private static class ValidContractPolicyProvider implements ArgumentsProvider { + @Override + public Stream provideArguments(ExtensionContext extensionContext) { + return Stream.of( + Arguments.of(frameworkPolicy(Map.of(CX_POLICY_NS + "Membership", "active")), "MembershipCredential"), + Arguments.of(frameworkPolicy(Map.of(CX_POLICY_NS + "FrameworkAgreement.pcf", "active")), "PCF Use Case (legacy notation)"), + Arguments.of(frameworkPolicy(Map.of(CX_POLICY_NS + "FrameworkAgreement", "pcf")), "PCF Use Case (new notation)"), + Arguments.of(frameworkPolicy(Map.of(CX_POLICY_NS + "Dismantler", "active")), "Dismantler Credential"), + Arguments.of(frameworkPolicy(Map.of(CX_POLICY_NS + "Dismantler.activityType", "vehicleDismantle")), "Dismantler Cred (activity type)"), + Arguments.of(frameworkPolicy(CX_POLICY_NS + "Dismantler.allowedBrands", Operator.IS_ANY_OF, List.of("Moskvich", "Tatra")), "Dismantler allowedBrands (IS_ANY_OF, one intersects)"), + Arguments.of(frameworkPolicy(CX_POLICY_NS + "Dismantler.allowedBrands", Operator.EQ, List.of("Moskvich", "Lada")), "Dismantler allowedBrands (EQ, exact match)"), + Arguments.of(frameworkPolicy(CX_POLICY_NS + "Dismantler.allowedBrands", Operator.IS_NONE_OF, List.of("Yugo", "Tatra")), "Dismantler allowedBrands (IS_NONE_OF, no intersect)"), + Arguments.of(frameworkPolicy(CX_POLICY_NS + "Dismantler.allowedBrands", Operator.IN, List.of("Moskvich", "Tatra", "Yugo", "Lada")), "Dismantler allowedBrands (IN, fully contained)") + ); + } } + private static class InvalidContractPolicyProvider implements ArgumentsProvider { + @Override + public Stream provideArguments(ExtensionContext extensionContext) { + return Stream.of( + Arguments.of(frameworkPolicy(Map.of(CX_POLICY_NS + "FrameworkAgreement.sustainability", "active")), "Sustainability Use Case (legacy notation)"), + Arguments.of(frameworkPolicy(Map.of(CX_POLICY_NS + "FrameworkAgreement", "traceability")), "Traceability Use Case (new notation)"), + Arguments.of(frameworkPolicy(Map.of(CX_POLICY_NS + "Dismantler.activityType", "vehicleScrap")), "Dismantler activityType does not match"), + Arguments.of(frameworkPolicy(CX_POLICY_NS + "Dismantler.allowedBrands", Operator.NEQ, List.of("Moskvich", "Lada")), "Dismantler allowedBrands (NEQ, but is equal)"), + Arguments.of(frameworkPolicy(CX_POLICY_NS + "Dismantler.allowedBrands", Operator.IS_NONE_OF, List.of("Yugo", "Lada")), "Dismantler allowedBrands (IS_NONE_OF, but is one contains)"), + Arguments.of(frameworkPolicy(CX_POLICY_NS + "Dismantler.allowedBrands", Operator.IN, List.of("Moskvich", "Tatra", "Yugo")), "Dismantler allowedBrands (IN, but not subset)") + ); + } + } } diff --git a/edc-tests/edc-dataplane/cloud-transfer-tests/src/test/java/org/eclipse/tractusx/edc/dataplane/transfer/test/S3ToS3Test.java b/edc-tests/edc-dataplane/cloud-transfer-tests/src/test/java/org/eclipse/tractusx/edc/dataplane/transfer/test/S3ToS3Test.java index 976547dad..5d3e4aa08 100644 --- a/edc-tests/edc-dataplane/cloud-transfer-tests/src/test/java/org/eclipse/tractusx/edc/dataplane/transfer/test/S3ToS3Test.java +++ b/edc-tests/edc-dataplane/cloud-transfer-tests/src/test/java/org/eclipse/tractusx/edc/dataplane/transfer/test/S3ToS3Test.java @@ -178,13 +178,13 @@ void transferFile_targetContainerNotExist_shouldFail() { // wait until the data plane logs an exception that it cannot transfer the file await().pollInterval(Duration.ofSeconds(2)) .atMost(Duration.ofSeconds(10)) - .untilAsserted(() -> verify(DATAPLANE_RUNTIME.getContext().getMonitor()).severe(startsWith("Error writing the %s object on the %s bucket: The specified bucket does not exist".formatted(TESTFILE_NAME, S3_CONSUMER_BUCKET_NAME)), + .untilAsserted(() -> verify(DATAPLANE_RUNTIME.getContext().getMonitor()).severe(startsWith("Failed to upload the %s object: The specified bucket does not exist".formatted(TESTFILE_NAME)), isA(NoSuchBucketException.class))); } @ParameterizedTest(name = "File size bytes: {0}") // 1mb, 512mb, 1gb - @ValueSource(longs = {1024 * 1024 * 512, 1024L * 1024L * 1024L, 1024L * 1024L * 1024L * 1024}) + @ValueSource(longs = { 1024 * 1024 * 512, 1024L * 1024L * 1024L, 1024L * 1024L * 1024L * 1024 }) void transferfile_largeFile(long sizeBytes) { // create large sparse file diff --git a/edc-tests/runtime/iatp/iatp-extensions/src/main/java/org/eclipse/tractusx/edc/iatp/CredentialsJsonLdExtension.java b/edc-tests/runtime/iatp/iatp-extensions/src/main/java/org/eclipse/tractusx/edc/iatp/CredentialsJsonLdExtension.java index 061a73a05..584ae5308 100644 --- a/edc-tests/runtime/iatp/iatp-extensions/src/main/java/org/eclipse/tractusx/edc/iatp/CredentialsJsonLdExtension.java +++ b/edc-tests/runtime/iatp/iatp-extensions/src/main/java/org/eclipse/tractusx/edc/iatp/CredentialsJsonLdExtension.java @@ -30,11 +30,11 @@ @Extension("Credentials JSON LD extension") public class CredentialsJsonLdExtension implements ServiceExtension { - public static final String BUSINESS_PARTNER_DATA = "https://catenax-ng.github.io/product-core-schemas/businessPartnerData.json"; + public static final String BUSINESS_PARTNER_DATA = "https://w3id.org/catenax/credentials"; @Inject private JsonLd jsonLd; - + @Override public void initialize(ServiceExtensionContext context) { diff --git a/edc-tests/runtime/iatp/iatp-extensions/src/main/java/org/eclipse/tractusx/edc/iatp/ih/IdentityHubExtension.java b/edc-tests/runtime/iatp/iatp-extensions/src/main/java/org/eclipse/tractusx/edc/iatp/ih/IdentityHubExtension.java index 2a5bd9a74..c54b60b22 100644 --- a/edc-tests/runtime/iatp/iatp-extensions/src/main/java/org/eclipse/tractusx/edc/iatp/ih/IdentityHubExtension.java +++ b/edc-tests/runtime/iatp/iatp-extensions/src/main/java/org/eclipse/tractusx/edc/iatp/ih/IdentityHubExtension.java @@ -24,14 +24,12 @@ import org.eclipse.edc.runtime.metamodel.annotation.Provider; import org.eclipse.edc.spi.system.ServiceExtension; -import java.util.List; - @Extension("Identity Hub extension for testing") public class IdentityHubExtension implements ServiceExtension { @Provider public ScopeToCriterionTransformer scopeToCriterionTransformer() { - return new TxScopeToCriterionTransformer(List.of("MembershipCredential", "DismantlerCredential", "BpnCredential")); + return new TxScopeToCriterionTransformer(); } } diff --git a/edc-tests/runtime/iatp/iatp-extensions/src/main/java/org/eclipse/tractusx/edc/iatp/ih/TxScopeToCriterionTransformer.java b/edc-tests/runtime/iatp/iatp-extensions/src/main/java/org/eclipse/tractusx/edc/iatp/ih/TxScopeToCriterionTransformer.java index a65434fc5..df1c0b577 100644 --- a/edc-tests/runtime/iatp/iatp-extensions/src/main/java/org/eclipse/tractusx/edc/iatp/ih/TxScopeToCriterionTransformer.java +++ b/edc-tests/runtime/iatp/iatp-extensions/src/main/java/org/eclipse/tractusx/edc/iatp/ih/TxScopeToCriterionTransformer.java @@ -34,17 +34,12 @@ */ public class TxScopeToCriterionTransformer implements ScopeToCriterionTransformer { - public static final String TYPE_OPERAND = "verifiableCredential.credential.types"; + public static final String TYPE_OPERAND = "verifiableCredential.credential.type"; public static final String ALIAS_LITERAL = "org.eclipse.tractusx.vc.type"; public static final String CONTAINS_OPERATOR = "contains"; private static final String SCOPE_SEPARATOR = ":"; - private final List knownCredentialTypes; private final List allowedOperations = List.of("read", "*", "all"); - public TxScopeToCriterionTransformer(List knownCredentialTypes) { - this.knownCredentialTypes = knownCredentialTypes; - } - @Override public Result transform(String scope) { var tokens = tokenize(scope); @@ -52,14 +47,7 @@ public Result transform(String scope) { return failure("Scope string cannot be converted: %s".formatted(tokens.getFailureDetail())); } var credentialType = tokens.getContent()[1]; - - if (!knownCredentialTypes.contains(credentialType)) { - //select based on the credentialSubject.useCaseType property - // even though "claims" is a Map, we need to access it using the dot notation. See ReflectionUtil.java - return success(new Criterion("verifiableCredential.credential.credentialSubject.useCaseType", "=", credentialType)); - } else { - return success(new Criterion(TYPE_OPERAND, CONTAINS_OPERATOR, credentialType)); - } + return success(new Criterion(TYPE_OPERAND, CONTAINS_OPERATOR, credentialType)); } protected Result tokenize(String scope) { diff --git a/edc-tests/runtime/iatp/iatp-extensions/src/main/java/org/eclipse/tractusx/edc/iatp/policy/IdentityExtractor.java b/edc-tests/runtime/iatp/iatp-extensions/src/main/java/org/eclipse/tractusx/edc/iatp/policy/IdentityExtractor.java index 056cdebaf..7afddbe82 100644 --- a/edc-tests/runtime/iatp/iatp-extensions/src/main/java/org/eclipse/tractusx/edc/iatp/policy/IdentityExtractor.java +++ b/edc-tests/runtime/iatp/iatp-extensions/src/main/java/org/eclipse/tractusx/edc/iatp/policy/IdentityExtractor.java @@ -55,7 +55,7 @@ public class IdentityExtractor implements ParticipantAgentServiceExtension { } private boolean isIdentityCredential(VerifiableCredential verifiableCredential) { - return verifiableCredential.getTypes().stream().anyMatch(t -> t.endsWith(IDENTITY_CREDENTIAL)); + return verifiableCredential.getType().stream().anyMatch(t -> t.endsWith(IDENTITY_CREDENTIAL)); } private Optional getIdentifier(VerifiableCredential verifiableCredential) { diff --git a/edc-tests/runtime/iatp/iatp-extensions/src/main/resources/cx-credentials-context.json b/edc-tests/runtime/iatp/iatp-extensions/src/main/resources/cx-credentials-context.json index 110c98f99..dd90f3745 100644 --- a/edc-tests/runtime/iatp/iatp-extensions/src/main/resources/cx-credentials-context.json +++ b/edc-tests/runtime/iatp/iatp-extensions/src/main/resources/cx-credentials-context.json @@ -1,48 +1,60 @@ { "@context": { "@version": 1.1, - "ctx": "https://raw.githubusercontent.com/catenax-ng/product-core-schemas/main/businessPartnerData#", - "schema": "https://schema.org/", + "@protected": true, + "cred": "https://www.w3.org/2018/credentials#", + "xsd": "http://www.w3.org/2001/XMLSchema#", + "cx-credentials": "https://w3id.org/catenax/credentials/", + "BehavioralTwinCredential": { + "@id": "cx-credentials:BehavioralTwinCredential" + }, "BpnCredential": { - "@id": "ctx:BpnCredential", - "@context": { - "@version": 1.1, - "id": "@id", - "type": "@type", - "bpn": "schema:identifier" - } + "@id": "cx-credentials:BpnCredential" + }, + "DismantlerCredential": { + "@id": "cx-credentials:DismantlerCredential" }, "MembershipCredential": { - "@id": "ctx:MembershipCredential", - "@context": { - "@version": 1.1, - "id": "@id", - "type": "@type", - "startTime": { - "@id": "schema:startTime", - "@type": "schema:DateTime" - }, - "memberOf": { - "@id": "schema:memberOf", - "@type": "schema:Text" - }, - "status": { - "@id": "ctx:status", - "@type": "schema:Text" - }, - "holderIdentifier": { - "@id": "ctx:holderIdentifier" - } - } - }, - "UseCaseFrameworkCondition": { - "@id": "ctx:UseCaseFrameworkCondition" - }, - "contractVersion": "ctx:contractVersion", - "contractTemplate": "ctx:contractTemplate", - "useCaseType": "ctx:useCaseType", + "@id": "cx-credentials:MembershipCredential" + }, + "PcfCredential": { + "@id": "cx-credentials:PcfCredential" + }, + "ResiliencyCredential": { + "@id": "cx-credentials:ResiliencyCredential" + }, + "QualityCredential": { + "@id": "cx-credentials:QualityCredential" + }, + "SustainabilityCredential": { + "@id": "cx-credentials:SustainabilityCredential" + }, + "TraceabilityCredential": { + "@id": "cx-credentials:TraceabilityCredential" + }, + "activityType": { + "@id": "cx-credentials:activityType", + "@type": "xsd:string" + }, + "allowedVehicleBrands": { + "@id": "cx-credentials:allowedVehicleBrands", + "@container": "@set" + }, + "bpn": { + "@id": "cx-credentials:bpn", + "@type": "xsd:string" + }, + "contractTemplate": { + "@id": "cx-credentials:contractTemplate", + "@type": "@id" + }, + "contractVersion": { + "@id": "cx-credentials:contractVersion", + "@type": "@id" + }, "holderIdentifier": { - "@id": "ctx:holderIdentifier" + "@id": "cx-credentials:holderIdentifier", + "@type": "xsd:string" } } } diff --git a/edc-tests/runtime/iatp/runtime-memory-iatp-dim-ih/build.gradle.kts b/edc-tests/runtime/iatp/runtime-memory-iatp-dim-ih/build.gradle.kts index d90e9e01d..91147986a 100644 --- a/edc-tests/runtime/iatp/runtime-memory-iatp-dim-ih/build.gradle.kts +++ b/edc-tests/runtime/iatp/runtime-memory-iatp-dim-ih/build.gradle.kts @@ -30,7 +30,7 @@ dependencies { exclude(module = "ssi-identity-core") exclude(module = "ssi-miw-credential-client") exclude(module = "ssi-identity-extractor") - exclude(module = "cx-policy") + exclude(module = "cx-policy-legacy") } implementation(project(":core:json-ld-core")) implementation(project(":edc-extensions:iatp:tx-iatp")) diff --git a/edc-tests/runtime/iatp/runtime-memory-iatp-ih/build.gradle.kts b/edc-tests/runtime/iatp/runtime-memory-iatp-ih/build.gradle.kts index 329cbf632..ae572775d 100644 --- a/edc-tests/runtime/iatp/runtime-memory-iatp-ih/build.gradle.kts +++ b/edc-tests/runtime/iatp/runtime-memory-iatp-ih/build.gradle.kts @@ -30,8 +30,9 @@ dependencies { exclude(module = "ssi-identity-core") exclude(module = "ssi-miw-credential-client") exclude(module = "ssi-identity-extractor") - exclude(module = "cx-policy") + exclude(module = "cx-policy-legacy") } + implementation(project(":edc-extensions:cx-policy")) implementation(project(":core:json-ld-core")) implementation(project(":edc-extensions:iatp:tx-iatp")) diff --git a/edc-tests/runtime/iatp/runtime-memory-sts/build.gradle.kts b/edc-tests/runtime/iatp/runtime-memory-sts/build.gradle.kts index 00cc47b67..88dcebd26 100644 --- a/edc-tests/runtime/iatp/runtime-memory-sts/build.gradle.kts +++ b/edc-tests/runtime/iatp/runtime-memory-sts/build.gradle.kts @@ -30,7 +30,7 @@ dependencies { exclude(module = "ssi-identity-core") exclude(module = "ssi-miw-credential-client") exclude(module = "ssi-identity-extractor") - exclude(module = "cx-policy") + exclude(module = "cx-policy-legacy") } implementation(project(":core:json-ld-core")) implementation(project(":edc-tests:runtime:extensions")) diff --git a/edc-tests/runtime/runtime-memory-ssi/build.gradle.kts b/edc-tests/runtime/runtime-memory-ssi/build.gradle.kts index fdadffe79..7d8b69ae3 100644 --- a/edc-tests/runtime/runtime-memory-ssi/build.gradle.kts +++ b/edc-tests/runtime/runtime-memory-ssi/build.gradle.kts @@ -35,7 +35,7 @@ dependencies { implementation(project(":edc-extensions:ssi:ssi-identity-core")) implementation(project(":edc-extensions:ssi:ssi-miw-credential-client")); implementation(project(":edc-extensions:ssi:ssi-identity-extractor")) - implementation(project(":edc-extensions:cx-policy")) + implementation(project(":edc-extensions:cx-policy-legacy")) implementation(project(":edc-tests:runtime:extensions")) diff --git a/edc-tests/runtime/runtime-memory/build.gradle.kts b/edc-tests/runtime/runtime-memory/build.gradle.kts index a2cf6f64a..7a389a698 100644 --- a/edc-tests/runtime/runtime-memory/build.gradle.kts +++ b/edc-tests/runtime/runtime-memory/build.gradle.kts @@ -31,7 +31,7 @@ dependencies { exclude(module = "ssi-identity-core") exclude(module = "ssi-miw-credential-client") exclude(module = "ssi-identity-extractor") - exclude(module = "cx-policy") + exclude(module = "cx-policy-legacy") } implementation(project(":edc-tests:runtime:extensions")) diff --git a/edc-tests/runtime/runtime-postgresql-hashicorp/build.gradle.kts b/edc-tests/runtime/runtime-postgresql-hashicorp/build.gradle.kts index 692248c43..6a4339af2 100644 --- a/edc-tests/runtime/runtime-postgresql-hashicorp/build.gradle.kts +++ b/edc-tests/runtime/runtime-postgresql-hashicorp/build.gradle.kts @@ -32,7 +32,7 @@ dependencies { exclude(module = "ssi-identity-core") exclude(module = "ssi-miw-credential-client") exclude(module = "ssi-identity-extractor") - exclude(module = "cx-policy") + exclude(module = "cx-policy-legacy") } implementation(project(":edc-tests:runtime:extensions")) diff --git a/edc-tests/runtime/runtime-postgresql/build.gradle.kts b/edc-tests/runtime/runtime-postgresql/build.gradle.kts index 993e47481..4eb0ef35c 100644 --- a/edc-tests/runtime/runtime-postgresql/build.gradle.kts +++ b/edc-tests/runtime/runtime-postgresql/build.gradle.kts @@ -32,7 +32,7 @@ dependencies { exclude(module = "ssi-identity-core") exclude(module = "ssi-miw-credential-client") exclude(module = "ssi-identity-extractor") - exclude(module = "cx-policy") + exclude(module = "cx-policy-legacy") exclude(group = "org.eclipse.edc", "vault-hashicorp") } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 3dfe3e9ad..7faba232e 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -2,7 +2,7 @@ format.version = "1.1" [versions] -edc = "0.5.2-20240219-SNAPSHOT" +edc = "0.5.2-SNAPSHOT" apache-sshd = "2.12.1" assertj = "3.25.3" awaitility = "4.2.0" diff --git a/settings.gradle.kts b/settings.gradle.kts index 65841a7b9..3b4ed3422 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -49,6 +49,7 @@ include(":edc-extensions:edr:edr-api") include(":edc-extensions:edr:edr-callback") include(":edc-extensions:edr:edr-cache-sql") include(":edc-extensions:cx-policy") +include(":edc-extensions:cx-policy-legacy") include("edc-extensions:ssi:ssi-identity-core") include("edc-extensions:ssi:ssi-miw-credential-client") include(":edc-extensions:ssi:ssi-identity-extractor") diff --git a/spi/core-spi/src/main/java/org/eclipse/tractusx/edc/edr/spi/CoreConstants.java b/spi/core-spi/src/main/java/org/eclipse/tractusx/edc/edr/spi/CoreConstants.java index d3448b178..87ab2566f 100644 --- a/spi/core-spi/src/main/java/org/eclipse/tractusx/edc/edr/spi/CoreConstants.java +++ b/spi/core-spi/src/main/java/org/eclipse/tractusx/edc/edr/spi/CoreConstants.java @@ -23,10 +23,12 @@ public final class CoreConstants { public static final String TX_PREFIX = "tx"; public static final String TX_NAMESPACE = "https://w3id.org/tractusx/v0.0.1/ns/"; - public static final String TX_CREDENTIAL_NAMESPACE = "https://w3id.org/tractusx/credentials/v0.0.1/ns/"; public static final String TX_CONTEXT = "https://w3id.org/tractusx/edc/v0.0.1"; public static final String EDC_CONTEXT = "https://w3id.org/edc/v0.0.1"; - + public static final String CX_CREDENTIAL_NS = "https://w3id.org/catenax/credentials/"; + public static final String CX_POLICY_NS = "https://w3id.org/catenax/policy/"; + public static final String TX_CREDENTIAL_NAMESPACE = "https://w3id.org/tractusx/credentials/v0.0.1/ns/"; + private CoreConstants() { } } diff --git a/spi/ssi-spi/src/main/java/org/eclipse/tractusx/edc/iam/ssi/spi/jsonld/CredentialsNamespaces.java b/spi/ssi-spi/src/main/java/org/eclipse/tractusx/edc/iam/ssi/spi/jsonld/CredentialsNamespaces.java index b622d5d11..48a11fb1b 100644 --- a/spi/ssi-spi/src/main/java/org/eclipse/tractusx/edc/iam/ssi/spi/jsonld/CredentialsNamespaces.java +++ b/spi/ssi-spi/src/main/java/org/eclipse/tractusx/edc/iam/ssi/spi/jsonld/CredentialsNamespaces.java @@ -41,7 +41,7 @@ public interface CredentialsNamespaces { String CX_USE_CASE_NS = CX_NS + "usecase"; @Deprecated String CX_USE_CASE_NS_V1 = CX_USE_CASE_NS + "/v1"; - String CX_NS_1_0 = "https://w3id.org/catenax/credentials/v1.0.0/"; + @Deprecated String CX_SUMMARY_CREDENTIAL = "SummaryCredential"; String CREDENTIAL_SUBJECT = W3C_VC_PREFIX + "#credentialSubject"; String CREDENTIAL_ISSUER = W3C_VC_PREFIX + "#issuer"; From e6f18c520fdf0a81379a29b5976b40def51c6b16 Mon Sep 17 00:00:00 2001 From: Enrico Risa Date: Mon, 26 Feb 2024 10:08:43 +0100 Subject: [PATCH 026/100] chore: fix compile error after DataFlowRequest refactor (#1076) * chore: fix compile error after DataFlowRequest refactor * chore: dependencies file --- DEPENDENCIES | 83 +++++++++++-------- .../asset/ConsumerAssetRequestController.java | 4 +- .../ConsumerAssetRequestControllerTest.java | 18 ++-- .../gateway/ProviderGatewayController.java | 6 +- .../sftp/client/SftpDataSinkFactory.java | 10 +-- .../sftp/client/SftpDataSourceFactory.java | 10 +-- .../sftp/client/SftpDataSinkFactoryTest.java | 12 +-- .../client/SftpDataSourceFactoryTest.java | 12 +-- .../transfer/test/AzureToAzureTest.java | 10 +-- .../transfer/test/MultiCloudTest.java | 6 +- .../dataplane/transfer/test/S3ToS3Test.java | 8 +- 11 files changed, 95 insertions(+), 84 deletions(-) diff --git a/DEPENDENCIES b/DEPENDENCIES index ea2c16354..b5e362192 100644 --- a/DEPENDENCIES +++ b/DEPENDENCIES @@ -5,18 +5,15 @@ maven/mavencentral/com.apicatalog/titanium-json-ld/1.0.0, Apache-2.0, approved, maven/mavencentral/com.apicatalog/titanium-json-ld/1.3.1, Apache-2.0, approved, #8912 maven/mavencentral/com.apicatalog/titanium-json-ld/1.3.3, Apache-2.0, approved, #8912 maven/mavencentral/com.azure/azure-core-http-netty/1.13.11, MIT AND Apache-2.0, approved, #7948 -maven/mavencentral/com.azure/azure-core-http-netty/1.13.9, MIT AND Apache-2.0, approved, #7948 maven/mavencentral/com.azure/azure-core-http-netty/1.14.0, MIT AND Apache-2.0, approved, #13238 -maven/mavencentral/com.azure/azure-core/1.44.1, MIT, approved, clearlydefined maven/mavencentral/com.azure/azure-core/1.45.1, MIT AND Apache-2.0, approved, #11845 maven/mavencentral/com.azure/azure-core/1.46.0, MIT AND Apache-2.0, approved, #13234 -maven/mavencentral/com.azure/azure-identity/1.11.1, MIT AND Apache-2.0, approved, #13237 maven/mavencentral/com.azure/azure-identity/1.11.2, MIT AND Apache-2.0, approved, #13237 maven/mavencentral/com.azure/azure-json/1.1.0, MIT AND Apache-2.0, approved, #10547 maven/mavencentral/com.azure/azure-security-keyvault-secrets/4.7.3, MIT, approved, #10868 -maven/mavencentral/com.azure/azure-storage-blob/12.24.1, MIT, approved, #10568 -maven/mavencentral/com.azure/azure-storage-common/12.23.1, MIT, approved, #10569 -maven/mavencentral/com.azure/azure-storage-internal-avro/12.9.1, MIT, approved, #10560 +maven/mavencentral/com.azure/azure-storage-blob/12.25.2, , restricted, clearlydefined +maven/mavencentral/com.azure/azure-storage-common/12.24.2, , restricted, clearlydefined +maven/mavencentral/com.azure/azure-storage-internal-avro/12.10.2, , restricted, clearlydefined maven/mavencentral/com.fasterxml.jackson.core/jackson-annotations/2.10.3, Apache-2.0, approved, CQ21280 maven/mavencentral/com.fasterxml.jackson.core/jackson-annotations/2.13.5, Apache-2.0, approved, clearlydefined maven/mavencentral/com.fasterxml.jackson.core/jackson-annotations/2.15.1, Apache-2.0, approved, #7947 @@ -55,19 +52,21 @@ maven/mavencentral/com.fasterxml.jackson/jackson-bom/2.15.1, Apache-2.0, approve maven/mavencentral/com.fasterxml.jackson/jackson-bom/2.16.1, Apache-2.0, approved, #11852 maven/mavencentral/com.fasterxml.woodstox/woodstox-core/6.5.1, Apache-2.0, approved, #7950 maven/mavencentral/com.github.docker-java/docker-java-api/3.3.4, Apache-2.0, approved, #10346 +maven/mavencentral/com.github.docker-java/docker-java-api/3.3.5, Apache-2.0, approved, #10346 maven/mavencentral/com.github.docker-java/docker-java-transport-zerodep/3.3.4, Apache-2.0 AND (Apache-2.0 AND BSD-3-Clause), approved, #7946 +maven/mavencentral/com.github.docker-java/docker-java-transport-zerodep/3.3.5, Apache-2.0 AND (Apache-2.0 AND BSD-3-Clause), approved, #7946 maven/mavencentral/com.github.docker-java/docker-java-transport/3.3.4, Apache-2.0, approved, #7942 +maven/mavencentral/com.github.docker-java/docker-java-transport/3.3.5, Apache-2.0, approved, #7942 maven/mavencentral/com.github.stephenc.jcip/jcip-annotations/1.0-1, Apache-2.0, approved, CQ21949 maven/mavencentral/com.google.code.findbugs/jsr305/3.0.2, Apache-2.0, approved, #20 maven/mavencentral/com.google.code.gson/gson/2.10.1, Apache-2.0, approved, #6159 maven/mavencentral/com.google.collections/google-collections/1.0, Apache-2.0, approved, CQ3285 maven/mavencentral/com.google.crypto.tink/tink/1.12.0, Apache-2.0, approved, #12041 -maven/mavencentral/com.google.errorprone/error_prone_annotations/2.18.0, Apache-2.0, approved, clearlydefined maven/mavencentral/com.google.errorprone/error_prone_annotations/2.22.0, Apache-2.0, approved, #10661 -maven/mavencentral/com.google.guava/failureaccess/1.0.1, Apache-2.0, approved, CQ22654 -maven/mavencentral/com.google.guava/guava/32.0.1-jre, Apache-2.0 AND CC0-1.0 AND CC-PDDC, approved, #8772 +maven/mavencentral/com.google.errorprone/error_prone_annotations/2.23.0, Apache-2.0, approved, #11083 +maven/mavencentral/com.google.guava/failureaccess/1.0.2, Apache-2.0, approved, CQ22654 +maven/mavencentral/com.google.guava/guava/33.0.0-jre, Apache-2.0 AND CC0-1.0, approved, #12173 maven/mavencentral/com.google.guava/listenablefuture/9999.0-empty-to-avoid-conflict-with-guava, Apache-2.0, approved, CQ22657 -maven/mavencentral/com.google.j2objc/j2objc-annotations/2.8, Apache-2.0, approved, clearlydefined maven/mavencentral/com.google.protobuf/protobuf-java/3.24.3, BSD-3-Clause, approved, clearlydefined maven/mavencentral/com.microsoft.azure/msal4j-persistence-extension/1.2.0, MIT, approved, clearlydefined maven/mavencentral/com.microsoft.azure/msal4j/1.14.0, MIT, approved, clearlydefined @@ -77,7 +76,7 @@ maven/mavencentral/com.nimbusds/lang-tag/1.7, Apache-2.0, approved, clearlydefin maven/mavencentral/com.nimbusds/nimbus-jose-jwt/9.30.2, Apache-2.0, approved, clearlydefined maven/mavencentral/com.nimbusds/nimbus-jose-jwt/9.37.3, Apache-2.0, approved, #11701 maven/mavencentral/com.nimbusds/oauth2-oidc-sdk/10.7.1, Apache-2.0, approved, clearlydefined -maven/mavencentral/com.puppycrawl.tools/checkstyle/10.12.3, LGPL-2.1-only AND Apache-2.0 AND LGPL-2.1-or-later AND ANTLR-PD AND GPL-2.0-or-later AND LGPL-2.0-or-later AND (Apache-2.0 AND LGPL-2.1-or-later) AND LicenseRef-scancode-proprietary-license, restricted, #13190 +maven/mavencentral/com.puppycrawl.tools/checkstyle/10.13.0, , restricted, clearlydefined maven/mavencentral/com.squareup.okhttp3/mockwebserver/5.0.0-alpha.12, Apache-2.0, approved, clearlydefined maven/mavencentral/com.squareup.okhttp3/mockwebserver3/5.0.0-alpha.12, Apache-2.0, approved, clearlydefined maven/mavencentral/com.squareup.okhttp3/okhttp-dnsoverhttps/4.12.0, Apache-2.0, approved, #11159 @@ -98,7 +97,7 @@ maven/mavencentral/commons-logging/commons-logging/1.2, Apache-2.0, approved, CQ maven/mavencentral/dev.failsafe/failsafe-okhttp/3.3.2, Apache-2.0, approved, #9178 maven/mavencentral/dev.failsafe/failsafe/3.3.1, Apache-2.0, approved, #9268 maven/mavencentral/dev.failsafe/failsafe/3.3.2, Apache-2.0, approved, #9268 -maven/mavencentral/info.picocli/picocli/4.7.4, Apache-2.0, approved, #4365 +maven/mavencentral/info.picocli/picocli/4.7.5, Apache-2.0, approved, #4365 maven/mavencentral/io.github.classgraph/classgraph/4.8.154, MIT, approved, CQ22530 maven/mavencentral/io.github.classgraph/classgraph/4.8.162, MIT, approved, CQ22530 maven/mavencentral/io.micrometer/micrometer-commons/1.12.3, Apache-2.0 AND (Apache-2.0 AND MIT), approved, #11679 @@ -106,27 +105,21 @@ maven/mavencentral/io.micrometer/micrometer-core/1.12.3, Apache-2.0 AND (Apache- maven/mavencentral/io.micrometer/micrometer-observation/1.12.3, Apache-2.0, approved, #11680 maven/mavencentral/io.netty/netty-buffer/4.1.100.Final, Apache-2.0, approved, CQ21842 maven/mavencentral/io.netty/netty-buffer/4.1.101.Final, Apache-2.0, approved, CQ21842 -maven/mavencentral/io.netty/netty-codec-dns/4.1.100.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 maven/mavencentral/io.netty/netty-codec-dns/4.1.101.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 maven/mavencentral/io.netty/netty-codec-http/4.1.100.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 maven/mavencentral/io.netty/netty-codec-http/4.1.101.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 maven/mavencentral/io.netty/netty-codec-http2/4.1.100.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 maven/mavencentral/io.netty/netty-codec-http2/4.1.101.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 -maven/mavencentral/io.netty/netty-codec-socks/4.1.100.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 maven/mavencentral/io.netty/netty-codec-socks/4.1.101.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 maven/mavencentral/io.netty/netty-codec/4.1.100.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 maven/mavencentral/io.netty/netty-codec/4.1.101.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 maven/mavencentral/io.netty/netty-common/4.1.100.Final, Apache-2.0 AND MIT AND CC0-1.0, approved, CQ21843 maven/mavencentral/io.netty/netty-common/4.1.101.Final, Apache-2.0 AND MIT AND CC0-1.0, approved, CQ21843 -maven/mavencentral/io.netty/netty-handler-proxy/4.1.100.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 maven/mavencentral/io.netty/netty-handler-proxy/4.1.101.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 maven/mavencentral/io.netty/netty-handler/4.1.100.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 maven/mavencentral/io.netty/netty-handler/4.1.101.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 -maven/mavencentral/io.netty/netty-resolver-dns-classes-macos/4.1.100.Final, Apache-2.0, approved, #6367 maven/mavencentral/io.netty/netty-resolver-dns-classes-macos/4.1.101.Final, Apache-2.0, approved, #6367 -maven/mavencentral/io.netty/netty-resolver-dns-native-macos/4.1.100.Final, Apache-2.0, approved, #7004 maven/mavencentral/io.netty/netty-resolver-dns-native-macos/4.1.101.Final, Apache-2.0, approved, #7004 -maven/mavencentral/io.netty/netty-resolver-dns/4.1.100.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 maven/mavencentral/io.netty/netty-resolver-dns/4.1.101.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 maven/mavencentral/io.netty/netty-resolver/4.1.100.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 maven/mavencentral/io.netty/netty-resolver/4.1.101.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 @@ -134,11 +127,8 @@ maven/mavencentral/io.netty/netty-tcnative-boringssl-static/2.0.62.Final, Apache maven/mavencentral/io.netty/netty-tcnative-classes/2.0.62.Final, Apache-2.0, approved, clearlydefined maven/mavencentral/io.netty/netty-transport-classes-epoll/4.1.100.Final, Apache-2.0, approved, #6366 maven/mavencentral/io.netty/netty-transport-classes-epoll/4.1.101.Final, Apache-2.0, approved, #6366 -maven/mavencentral/io.netty/netty-transport-classes-kqueue/4.1.100.Final, Apache-2.0, approved, #4107 maven/mavencentral/io.netty/netty-transport-classes-kqueue/4.1.101.Final, Apache-2.0, approved, #4107 -maven/mavencentral/io.netty/netty-transport-native-epoll/4.1.100.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 maven/mavencentral/io.netty/netty-transport-native-epoll/4.1.101.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 -maven/mavencentral/io.netty/netty-transport-native-kqueue/4.1.100.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 maven/mavencentral/io.netty/netty-transport-native-kqueue/4.1.101.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 maven/mavencentral/io.netty/netty-transport-native-unix-common/4.1.100.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 maven/mavencentral/io.netty/netty-transport-native-unix-common/4.1.101.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 @@ -147,13 +137,8 @@ maven/mavencentral/io.netty/netty-transport/4.1.101.Final, Apache-2.0 AND BSD-3- maven/mavencentral/io.opentelemetry.instrumentation/opentelemetry-instrumentation-annotations/1.32.0, Apache-2.0, approved, #11684 maven/mavencentral/io.opentelemetry/opentelemetry-api/1.32.0, Apache-2.0, approved, #11682 maven/mavencentral/io.opentelemetry/opentelemetry-context/1.32.0, Apache-2.0, approved, #11683 -maven/mavencentral/io.projectreactor.netty/reactor-netty-core/1.0.38, Apache-2.0, approved, #9687 -maven/mavencentral/io.projectreactor.netty/reactor-netty-core/1.0.39, Apache-2.0, approved, #9687 maven/mavencentral/io.projectreactor.netty/reactor-netty-core/1.0.40, Apache-2.0, approved, #9687 -maven/mavencentral/io.projectreactor.netty/reactor-netty-http/1.0.38, Apache-2.0, approved, #11661 -maven/mavencentral/io.projectreactor.netty/reactor-netty-http/1.0.39, Apache-2.0, approved, #11661 maven/mavencentral/io.projectreactor.netty/reactor-netty-http/1.0.40, Apache-2.0, approved, #11661 -maven/mavencentral/io.projectreactor/reactor-core/3.4.33, Apache-2.0, approved, #7517 maven/mavencentral/io.projectreactor/reactor-core/3.4.34, Apache-2.0, approved, #7517 maven/mavencentral/io.rest-assured/json-path/5.4.0, Apache-2.0, approved, #12042 maven/mavencentral/io.rest-assured/rest-assured-common/5.4.0, Apache-2.0, approved, #12039 @@ -201,8 +186,8 @@ maven/mavencentral/net.java.dev.jna/jna/5.13.0, Apache-2.0 AND LGPL-2.1-or-later maven/mavencentral/net.minidev/accessors-smart/2.5.0, Apache-2.0, approved, clearlydefined maven/mavencentral/net.minidev/json-smart/2.4.10, Apache-2.0, approved, #3288 maven/mavencentral/net.minidev/json-smart/2.5.0, Apache-2.0, approved, clearlydefined -maven/mavencentral/net.sf.saxon/Saxon-HE/12.3, MPL-2.0-no-copyleft-exception AND (LicenseRef-scancode-proprietary-license AND MPL-2.0-no-copyleft-exception) AND (MPL-2.0-no-copyleft-exception AND X11) AND (MIT AND MPL-2.0-no-copyleft-exception) AND (MPL-1.0 AND MPL-2.0-no-copyleft-exception) AND (Apache-2.0 AND MPL-2.0-no-copyleft-exception) AND MPL-1.0, restricted, #13191 -maven/mavencentral/org.antlr/antlr4-runtime/4.11.1, BSD-3-Clause, approved, clearlydefined +maven/mavencentral/net.sf.saxon/Saxon-HE/12.4, MPL-2.0 AND (MPL-2.0 AND Apache-2.0) AND (MPL-2.0 AND LicenseRef-X11-style) AND MPL-1.0 AND W3C, approved, #12716 +maven/mavencentral/org.antlr/antlr4-runtime/4.13.1, BSD-3-Clause, approved, #10767 maven/mavencentral/org.apache.commons/commons-compress/1.24.0, Apache-2.0 AND BSD-3-Clause AND bzip2-1.0.6 AND LicenseRef-Public-Domain, approved, #10368 maven/mavencentral/org.apache.commons/commons-lang3/3.11, Apache-2.0, approved, CQ22642 maven/mavencentral/org.apache.commons/commons-lang3/3.12.0, Apache-2.0, approved, clearlydefined @@ -231,16 +216,14 @@ maven/mavencentral/org.apache.sshd/sshd-core/2.12.1, Apache-2.0, approved, #1284 maven/mavencentral/org.apache.sshd/sshd-sftp/2.12.1, Apache-2.0, approved, #12840 maven/mavencentral/org.apache.xbean/xbean-reflect/3.7, Apache-2.0, approved, clearlydefined maven/mavencentral/org.apiguardian/apiguardian-api/1.1.2, Apache-2.0, approved, clearlydefined -maven/mavencentral/org.assertj/assertj-core/3.25.1, Apache-2.0, approved, #12585 maven/mavencentral/org.assertj/assertj-core/3.25.3, Apache-2.0, approved, #12585 maven/mavencentral/org.awaitility/awaitility/4.2.0, Apache-2.0, approved, clearlydefined maven/mavencentral/org.bouncycastle/bcpkix-jdk18on/1.77, MIT, approved, #11593 maven/mavencentral/org.bouncycastle/bcprov-jdk18on/1.77, MIT AND CC0-1.0, approved, #11595 maven/mavencentral/org.bouncycastle/bcutil-jdk18on/1.77, MIT, approved, #11596 maven/mavencentral/org.ccil.cowan.tagsoup/tagsoup/1.2.1, Apache-2.0, approved, clearlydefined -maven/mavencentral/org.checkerframework/checker-qual/3.27.0, MIT, approved, clearlydefined -maven/mavencentral/org.checkerframework/checker-qual/3.31.0, MIT, approved, clearlydefined maven/mavencentral/org.checkerframework/checker-qual/3.41.0, MIT, approved, #12032 +maven/mavencentral/org.checkerframework/checker-qual/3.42.0, MIT, approved, clearlydefined maven/mavencentral/org.codehaus.plexus/plexus-classworlds/2.6.0, Apache-2.0 AND Plexus, approved, CQ22821 maven/mavencentral/org.codehaus.plexus/plexus-component-annotations/2.1.0, Apache-2.0, approved, #809 maven/mavencentral/org.codehaus.plexus/plexus-container-default/2.1.0, Apache-2.0, approved, clearlydefined @@ -314,6 +297,7 @@ maven/mavencentral/org.eclipse.edc/dsp-transfer-process-api/0.5.2-SNAPSHOT, Apac maven/mavencentral/org.eclipse.edc/dsp-transfer-process-http-dispatcher/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/dsp-transfer-process-transform/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/dsp-transfer-process/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-version-api/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/dsp/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/http-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/http/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc @@ -482,8 +466,8 @@ maven/mavencentral/org.ow2.asm/asm-tree/9.6, BSD-3-Clause, approved, #10773 maven/mavencentral/org.ow2.asm/asm/9.3, BSD-3-Clause, approved, clearlydefined maven/mavencentral/org.ow2.asm/asm/9.5, BSD-3-Clause, approved, #7554 maven/mavencentral/org.ow2.asm/asm/9.6, BSD-3-Clause, approved, #10776 -maven/mavencentral/org.postgresql/postgresql/42.7.0, BSD-2-Clause AND Apache-2.0, approved, #11681 maven/mavencentral/org.postgresql/postgresql/42.7.1, BSD-2-Clause AND Apache-2.0, approved, #11681 +maven/mavencentral/org.postgresql/postgresql/42.7.2, BSD-2-Clause AND Apache-2.0, approved, #11681 maven/mavencentral/org.reactivestreams/reactive-streams/1.0.4, CC0-1.0, approved, CQ16332 maven/mavencentral/org.reflections/reflections/0.10.2, Apache-2.0 AND WTFPL, approved, clearlydefined maven/mavencentral/org.rnorth.duct-tape/duct-tape/1.0.8, MIT, approved, clearlydefined @@ -498,41 +482,68 @@ maven/mavencentral/org.slf4j/slf4j-api/2.0.12, MIT, approved, #5915 maven/mavencentral/org.slf4j/slf4j-api/2.0.9, MIT, approved, #5915 maven/mavencentral/org.testcontainers/database-commons/1.19.5, Apache-2.0, approved, #10345 maven/mavencentral/org.testcontainers/jdbc/1.19.5, Apache-2.0, approved, #10348 -maven/mavencentral/org.testcontainers/junit-jupiter/1.19.3, MIT, approved, #10344 maven/mavencentral/org.testcontainers/junit-jupiter/1.19.5, MIT, approved, #10344 +maven/mavencentral/org.testcontainers/junit-jupiter/1.19.6, MIT, approved, #10344 maven/mavencentral/org.testcontainers/postgresql/1.19.5, MIT, approved, #10350 maven/mavencentral/org.testcontainers/testcontainers/1.19.5, Apache-2.0 AND MIT, approved, #10347 +maven/mavencentral/org.testcontainers/testcontainers/1.19.6, Apache-2.0 AND MIT, approved, #10347 maven/mavencentral/org.testcontainers/vault/1.19.5, MIT, approved, #10852 -maven/mavencentral/org.xmlresolver/xmlresolver/5.2.0, Apache-2.0, approved, clearlydefined +maven/mavencentral/org.xmlresolver/xmlresolver/5.2.2, Apache-2.0, approved, clearlydefined maven/mavencentral/org.yaml/snakeyaml/2.0, Apache-2.0 AND (Apache-2.0 OR BSD-3-Clause OR EPL-1.0 OR GPL-2.0-or-later OR LGPL-2.1-or-later), approved, #7275 maven/mavencentral/org.yaml/snakeyaml/2.2, Apache-2.0 AND (Apache-2.0 OR BSD-3-Clause OR EPL-1.0 OR GPL-2.0-or-later OR LGPL-2.1-or-later), approved, #10232 +maven/mavencentral/software.amazon.awssdk/annotations/2.24.10, Apache-2.0, approved, #13251 maven/mavencentral/software.amazon.awssdk/annotations/2.24.5, Apache-2.0, approved, #13251 +maven/mavencentral/software.amazon.awssdk/apache-client/2.24.10, Apache-2.0, approved, #13257 maven/mavencentral/software.amazon.awssdk/apache-client/2.24.5, Apache-2.0, approved, #13257 +maven/mavencentral/software.amazon.awssdk/arns/2.24.10, Apache-2.0, approved, #13243 maven/mavencentral/software.amazon.awssdk/arns/2.24.5, Apache-2.0, approved, #13243 +maven/mavencentral/software.amazon.awssdk/auth/2.24.10, Apache-2.0, approved, #13256 maven/mavencentral/software.amazon.awssdk/auth/2.24.5, Apache-2.0, approved, #13256 +maven/mavencentral/software.amazon.awssdk/aws-core/2.24.10, Apache-2.0, approved, #13240 maven/mavencentral/software.amazon.awssdk/aws-core/2.24.5, Apache-2.0, approved, #13240 +maven/mavencentral/software.amazon.awssdk/aws-query-protocol/2.24.10, Apache-2.0, approved, #13262 maven/mavencentral/software.amazon.awssdk/aws-query-protocol/2.24.5, Apache-2.0, approved, #13262 +maven/mavencentral/software.amazon.awssdk/aws-xml-protocol/2.24.10, Apache-2.0, approved, #13247 maven/mavencentral/software.amazon.awssdk/aws-xml-protocol/2.24.5, Apache-2.0, approved, #13247 +maven/mavencentral/software.amazon.awssdk/checksums-spi/2.24.10, Apache-2.0, approved, #13245 maven/mavencentral/software.amazon.awssdk/checksums-spi/2.24.5, Apache-2.0, approved, #13245 +maven/mavencentral/software.amazon.awssdk/checksums/2.24.10, Apache-2.0, approved, #13242 maven/mavencentral/software.amazon.awssdk/checksums/2.24.5, Apache-2.0, approved, #13242 +maven/mavencentral/software.amazon.awssdk/crt-core/2.24.10, Apache-2.0, approved, #13252 maven/mavencentral/software.amazon.awssdk/crt-core/2.24.5, Apache-2.0, approved, #13252 +maven/mavencentral/software.amazon.awssdk/endpoints-spi/2.24.10, Apache-2.0, approved, #13246 maven/mavencentral/software.amazon.awssdk/endpoints-spi/2.24.5, Apache-2.0, approved, #13246 +maven/mavencentral/software.amazon.awssdk/http-auth-aws/2.24.10, Apache-2.0, approved, #13253 maven/mavencentral/software.amazon.awssdk/http-auth-aws/2.24.5, Apache-2.0, approved, #13253 +maven/mavencentral/software.amazon.awssdk/http-auth-spi/2.24.10, Apache-2.0, approved, #13264 maven/mavencentral/software.amazon.awssdk/http-auth-spi/2.24.5, Apache-2.0, approved, #13264 +maven/mavencentral/software.amazon.awssdk/http-auth/2.24.10, Apache-2.0, approved, #13248 maven/mavencentral/software.amazon.awssdk/http-auth/2.24.5, Apache-2.0, approved, #13248 +maven/mavencentral/software.amazon.awssdk/http-client-spi/2.24.10, Apache-2.0, approved, #13259 maven/mavencentral/software.amazon.awssdk/http-client-spi/2.24.5, Apache-2.0, approved, #13259 -maven/mavencentral/software.amazon.awssdk/iam/2.24.5, , restricted, clearlydefined +maven/mavencentral/software.amazon.awssdk/iam/2.24.10, , restricted, clearlydefined +maven/mavencentral/software.amazon.awssdk/identity-spi/2.24.10, Apache-2.0, approved, #13244 maven/mavencentral/software.amazon.awssdk/identity-spi/2.24.5, Apache-2.0, approved, #13244 +maven/mavencentral/software.amazon.awssdk/json-utils/2.24.10, Apache-2.0, approved, #13261 maven/mavencentral/software.amazon.awssdk/json-utils/2.24.5, Apache-2.0, approved, #13261 +maven/mavencentral/software.amazon.awssdk/metrics-spi/2.24.10, Apache-2.0, approved, #13239 maven/mavencentral/software.amazon.awssdk/metrics-spi/2.24.5, Apache-2.0, approved, #13239 +maven/mavencentral/software.amazon.awssdk/netty-nio-client/2.24.10, Apache-2.0, approved, #13260 maven/mavencentral/software.amazon.awssdk/netty-nio-client/2.24.5, Apache-2.0, approved, #13260 +maven/mavencentral/software.amazon.awssdk/profiles/2.24.10, Apache-2.0, approved, #13258 maven/mavencentral/software.amazon.awssdk/profiles/2.24.5, Apache-2.0, approved, #13258 +maven/mavencentral/software.amazon.awssdk/protocol-core/2.24.10, Apache-2.0, approved, #13241 maven/mavencentral/software.amazon.awssdk/protocol-core/2.24.5, Apache-2.0, approved, #13241 +maven/mavencentral/software.amazon.awssdk/regions/2.24.10, Apache-2.0, approved, #13255 maven/mavencentral/software.amazon.awssdk/regions/2.24.5, Apache-2.0, approved, #13255 maven/mavencentral/software.amazon.awssdk/s3-transfer-manager/2.24.5, Apache-2.0, approved, #13263 +maven/mavencentral/software.amazon.awssdk/s3/2.24.10, Apache-2.0, approved, #13254 maven/mavencentral/software.amazon.awssdk/s3/2.24.5, Apache-2.0, approved, #13254 +maven/mavencentral/software.amazon.awssdk/sdk-core/2.24.10, Apache-2.0, approved, #13265 maven/mavencentral/software.amazon.awssdk/sdk-core/2.24.5, Apache-2.0, approved, #13265 -maven/mavencentral/software.amazon.awssdk/sts/2.24.5, , restricted, clearlydefined +maven/mavencentral/software.amazon.awssdk/sts/2.24.10, , restricted, clearlydefined +maven/mavencentral/software.amazon.awssdk/third-party-jackson-core/2.24.10, Apache-2.0, approved, #13249 maven/mavencentral/software.amazon.awssdk/third-party-jackson-core/2.24.5, Apache-2.0, approved, #13249 +maven/mavencentral/software.amazon.awssdk/utils/2.24.10, Apache-2.0, approved, #13250 maven/mavencentral/software.amazon.awssdk/utils/2.24.5, Apache-2.0, approved, #13250 maven/mavencentral/software.amazon.eventstream/eventstream/1.0.1, Apache-2.0, approved, clearlydefined diff --git a/edc-extensions/dataplane-proxy/edc-dataplane-proxy-consumer-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/consumer/api/asset/ConsumerAssetRequestController.java b/edc-extensions/dataplane-proxy/edc-dataplane-proxy-consumer-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/consumer/api/asset/ConsumerAssetRequestController.java index 5d104c214..b6232ac2f 100644 --- a/edc-extensions/dataplane-proxy/edc-dataplane-proxy-consumer-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/consumer/api/asset/ConsumerAssetRequestController.java +++ b/edc-extensions/dataplane-proxy/edc-dataplane-proxy-consumer-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/consumer/api/asset/ConsumerAssetRequestController.java @@ -35,7 +35,7 @@ import org.eclipse.edc.spi.monitor.Monitor; import org.eclipse.edc.spi.types.domain.DataAddress; import org.eclipse.edc.spi.types.domain.edr.EndpointDataReference; -import org.eclipse.edc.spi.types.domain.transfer.DataFlowRequest; +import org.eclipse.edc.spi.types.domain.transfer.DataFlowStartMessage; import org.eclipse.tractusx.edc.dataplane.proxy.consumer.api.asset.model.AssetRequest; import org.eclipse.tractusx.edc.edr.spi.store.EndpointDataReferenceCache; @@ -105,7 +105,7 @@ public void requestAsset(AssetRequest request, @Suspended AsyncResponse response .map((url) -> Map.of()) .orElseGet(() -> dataPlaneProperties(request)); - var flowRequest = DataFlowRequest.Builder.newInstance() + var flowRequest = DataFlowStartMessage.Builder.newInstance() .processId(randomUUID().toString()) .trackable(false) .sourceDataAddress(sourceAddress) diff --git a/edc-extensions/dataplane-proxy/edc-dataplane-proxy-consumer-api/src/test/java/org/eclipse/tractusx/edc/dataplane/proxy/consumer/api/asset/model/ConsumerAssetRequestControllerTest.java b/edc-extensions/dataplane-proxy/edc-dataplane-proxy-consumer-api/src/test/java/org/eclipse/tractusx/edc/dataplane/proxy/consumer/api/asset/model/ConsumerAssetRequestControllerTest.java index 7c45031bd..e8709749a 100644 --- a/edc-extensions/dataplane-proxy/edc-dataplane-proxy-consumer-api/src/test/java/org/eclipse/tractusx/edc/dataplane/proxy/consumer/api/asset/model/ConsumerAssetRequestControllerTest.java +++ b/edc-extensions/dataplane-proxy/edc-dataplane-proxy-consumer-api/src/test/java/org/eclipse/tractusx/edc/dataplane/proxy/consumer/api/asset/model/ConsumerAssetRequestControllerTest.java @@ -29,7 +29,7 @@ import org.eclipse.edc.junit.annotations.ApiTest; import org.eclipse.edc.spi.monitor.Monitor; import org.eclipse.edc.spi.types.domain.edr.EndpointDataReference; -import org.eclipse.edc.spi.types.domain.transfer.DataFlowRequest; +import org.eclipse.edc.spi.types.domain.transfer.DataFlowStartMessage; import org.eclipse.edc.web.jersey.testfixtures.RestControllerTestBase; import org.eclipse.tractusx.edc.dataplane.proxy.consumer.api.asset.ClientErrorExceptionMapper; import org.eclipse.tractusx.edc.dataplane.proxy.consumer.api.asset.ConsumerAssetRequestController; @@ -71,6 +71,13 @@ public class ConsumerAssetRequestControllerTest extends RestControllerTestBase { private final PipelineService pipelineService = mock(); private final ObjectMapper mapper = new ObjectMapper(); + private static Stream provideServiceResultForProxyCall() { + return Stream.of( + Arguments.of(StreamResult.notFound(), NOT_FOUND.getStatusCode()), + Arguments.of(StreamResult.notAuthorized(), UNAUTHORIZED.getStatusCode()), + Arguments.of(StreamResult.error("error"), INTERNAL_SERVER_ERROR.getStatusCode())); + } + @Test void requestAsset_shouldReturnData_withAssetId() throws IOException { @@ -288,7 +295,7 @@ void requestAsset_shouldReturnData_withDataPlaneUrl() throws IOException { assertThat(proxyResponse).containsAllEntriesOf(response); - var captor = ArgumentCaptor.forClass(DataFlowRequest.class); + var captor = ArgumentCaptor.forClass(DataFlowStartMessage.class); verify(pipelineService).transfer(captor.capture(), any()); @@ -311,13 +318,6 @@ protected Object additionalResource() { return new ClientErrorExceptionMapper(); } - private static Stream provideServiceResultForProxyCall() { - return Stream.of( - Arguments.of(StreamResult.notFound(), NOT_FOUND.getStatusCode()), - Arguments.of(StreamResult.notAuthorized(), UNAUTHORIZED.getStatusCode()), - Arguments.of(StreamResult.error("error"), INTERNAL_SERVER_ERROR.getStatusCode())); - } - private RequestSpecification baseRequest() { return given() .baseUri("http://localhost:" + port) diff --git a/edc-extensions/dataplane-proxy/edc-dataplane-proxy-provider-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/api/gateway/ProviderGatewayController.java b/edc-extensions/dataplane-proxy/edc-dataplane-proxy-provider-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/api/gateway/ProviderGatewayController.java index 19d35432e..fcff2cf0d 100644 --- a/edc-extensions/dataplane-proxy/edc-dataplane-proxy-provider-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/api/gateway/ProviderGatewayController.java +++ b/edc-extensions/dataplane-proxy/edc-dataplane-proxy-provider-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/api/gateway/ProviderGatewayController.java @@ -37,7 +37,7 @@ import org.eclipse.edc.spi.monitor.Monitor; import org.eclipse.edc.spi.result.Result; import org.eclipse.edc.spi.types.domain.DataAddress; -import org.eclipse.edc.spi.types.domain.transfer.DataFlowRequest; +import org.eclipse.edc.spi.types.domain.transfer.DataFlowStartMessage; import org.eclipse.tractusx.edc.dataplane.proxy.spi.provider.gateway.authorization.AuthorizationHandlerRegistry; import org.eclipse.tractusx.edc.dataplane.proxy.spi.provider.gateway.configuration.GatewayConfiguration; import org.eclipse.tractusx.edc.dataplane.proxy.spi.provider.gateway.configuration.GatewayConfigurationRegistry; @@ -168,7 +168,7 @@ public void requestAsset(@Context ContainerRequestContext context, @Suspended As } } - private DataFlowRequest createRequest(String subPath, GatewayConfiguration configuration, HttpDataAddress httpDataAddress) { + private DataFlowStartMessage createRequest(String subPath, GatewayConfiguration configuration, HttpDataAddress httpDataAddress) { var path = configuration.getProxiedPath() + "/" + subPath; var sourceAddressBuilder = HttpDataAddress.Builder.newInstance() @@ -180,7 +180,7 @@ private DataFlowRequest createRequest(String subPath, GatewayConfiguration confi .type(ASYNC) .build(); - return DataFlowRequest.Builder.newInstance() + return DataFlowStartMessage.Builder.newInstance() .processId(randomUUID().toString()) .trackable(false) .sourceDataAddress(sourceAddressBuilder.build()) diff --git a/edc-extensions/transferprocess-sftp-client/src/main/java/org/eclipse/tractusx/edc/transferprocess/sftp/client/SftpDataSinkFactory.java b/edc-extensions/transferprocess-sftp-client/src/main/java/org/eclipse/tractusx/edc/transferprocess/sftp/client/SftpDataSinkFactory.java index 82c9a56d5..13089d78e 100644 --- a/edc-extensions/transferprocess-sftp-client/src/main/java/org/eclipse/tractusx/edc/transferprocess/sftp/client/SftpDataSinkFactory.java +++ b/edc-extensions/transferprocess-sftp-client/src/main/java/org/eclipse/tractusx/edc/transferprocess/sftp/client/SftpDataSinkFactory.java @@ -23,7 +23,7 @@ import org.eclipse.edc.connector.dataplane.spi.pipeline.DataSink; import org.eclipse.edc.connector.dataplane.spi.pipeline.DataSinkFactory; import org.eclipse.edc.spi.result.Result; -import org.eclipse.edc.spi.types.domain.transfer.DataFlowRequest; +import org.eclipse.edc.spi.types.domain.transfer.DataFlowStartMessage; import org.eclipse.tractusx.edc.transferprocess.sftp.common.EdcSftpException; import org.eclipse.tractusx.edc.transferprocess.sftp.common.SftpDataAddress; import org.jetbrains.annotations.NotNull; @@ -32,7 +32,7 @@ public class SftpDataSinkFactory implements DataSinkFactory { @Override - public boolean canHandle(DataFlowRequest request) { + public boolean canHandle(DataFlowStartMessage request) { try { SftpDataAddress.fromDataAddress(request.getDestinationDataAddress()); return true; @@ -42,7 +42,7 @@ public boolean canHandle(DataFlowRequest request) { } @Override - public DataSink createSink(DataFlowRequest request) { + public DataSink createSink(DataFlowStartMessage request) { if (!canHandle(request)) { return null; } @@ -63,9 +63,9 @@ public DataSink createSink(DataFlowRequest request) { } @Override - public @NotNull Result validateRequest(DataFlowRequest request) { + public @NotNull Result validateRequest(DataFlowStartMessage request) { if (!canHandle(request)) { - return Result.failure(String.format("Invalid DataFlowRequest: %s", request.getId())); + return Result.failure(String.format("Invalid DataFlowStartMessage: %s", request.getId())); } return Result.success(); diff --git a/edc-extensions/transferprocess-sftp-client/src/main/java/org/eclipse/tractusx/edc/transferprocess/sftp/client/SftpDataSourceFactory.java b/edc-extensions/transferprocess-sftp-client/src/main/java/org/eclipse/tractusx/edc/transferprocess/sftp/client/SftpDataSourceFactory.java index 4254dd9fc..b85fa3410 100644 --- a/edc-extensions/transferprocess-sftp-client/src/main/java/org/eclipse/tractusx/edc/transferprocess/sftp/client/SftpDataSourceFactory.java +++ b/edc-extensions/transferprocess-sftp-client/src/main/java/org/eclipse/tractusx/edc/transferprocess/sftp/client/SftpDataSourceFactory.java @@ -22,14 +22,14 @@ import org.eclipse.edc.connector.dataplane.spi.pipeline.DataSource; import org.eclipse.edc.connector.dataplane.spi.pipeline.DataSourceFactory; import org.eclipse.edc.spi.result.Result; -import org.eclipse.edc.spi.types.domain.transfer.DataFlowRequest; +import org.eclipse.edc.spi.types.domain.transfer.DataFlowStartMessage; import org.eclipse.tractusx.edc.transferprocess.sftp.common.EdcSftpException; import org.eclipse.tractusx.edc.transferprocess.sftp.common.SftpDataAddress; import org.jetbrains.annotations.NotNull; public class SftpDataSourceFactory implements DataSourceFactory { @Override - public boolean canHandle(DataFlowRequest request) { + public boolean canHandle(DataFlowStartMessage request) { try { SftpDataAddress.fromDataAddress(request.getSourceDataAddress()); return true; @@ -39,7 +39,7 @@ public boolean canHandle(DataFlowRequest request) { } @Override - public DataSource createSource(DataFlowRequest request) { + public DataSource createSource(DataFlowStartMessage request) { if (!canHandle(request)) { return null; } @@ -57,9 +57,9 @@ public DataSource createSource(DataFlowRequest request) { } @Override - public @NotNull Result validateRequest(DataFlowRequest request) { + public @NotNull Result validateRequest(DataFlowStartMessage request) { if (!canHandle(request)) { - return Result.failure(String.format("Invalid DataFlowRequest: %s", request.getId())); + return Result.failure(String.format("Invalid DataFlowStartMessage: %s", request.getId())); } return Result.success(); } diff --git a/edc-extensions/transferprocess-sftp-client/src/test/java/org/eclipse/tractusx/edc/transferprocess/sftp/client/SftpDataSinkFactoryTest.java b/edc-extensions/transferprocess-sftp-client/src/test/java/org/eclipse/tractusx/edc/transferprocess/sftp/client/SftpDataSinkFactoryTest.java index 57f4171cb..85225e4e3 100644 --- a/edc-extensions/transferprocess-sftp-client/src/test/java/org/eclipse/tractusx/edc/transferprocess/sftp/client/SftpDataSinkFactoryTest.java +++ b/edc-extensions/transferprocess-sftp-client/src/test/java/org/eclipse/tractusx/edc/transferprocess/sftp/client/SftpDataSinkFactoryTest.java @@ -22,7 +22,7 @@ import org.apache.sshd.sftp.client.SftpClient; import org.eclipse.edc.spi.types.domain.DataAddress; -import org.eclipse.edc.spi.types.domain.transfer.DataFlowRequest; +import org.eclipse.edc.spi.types.domain.transfer.DataFlowStartMessage; import org.eclipse.tractusx.edc.transferprocess.sftp.common.SftpDataAddress; import org.eclipse.tractusx.edc.transferprocess.sftp.common.SftpLocation; import org.eclipse.tractusx.edc.transferprocess.sftp.common.SftpUser; @@ -43,7 +43,7 @@ void validate_valid() { var sftpDataAddress = SftpDataAddress.Builder.newInstance().sftpUser(sftpUser).sftpLocation(sftpLocation).build(); - var request = Mockito.mock(DataFlowRequest.class); + var request = Mockito.mock(DataFlowStartMessage.class); Mockito.when(request.getDestinationDataAddress()).thenReturn(sftpDataAddress); Assertions.assertTrue(dataSinkFactory.validateRequest(request).succeeded()); @@ -53,7 +53,7 @@ void validate_valid() { void validate_invalidDataAddressType() { var dataSinkFactory = new SftpDataSinkFactory(); var dataAddress = DataAddress.Builder.newInstance().type("wrong").build(); - var request = Mockito.mock(DataFlowRequest.class); + var request = Mockito.mock(DataFlowStartMessage.class); Mockito.when(request.getDestinationDataAddress()).thenReturn(dataAddress); Assertions.assertTrue(dataSinkFactory.validateRequest(request).failed()); @@ -73,7 +73,7 @@ void validate_invalidDataAddressParameters() { final var dataAddress = DataAddress.Builder.newInstance().properties(properties).build(); - var request = Mockito.mock(DataFlowRequest.class); + var request = Mockito.mock(DataFlowStartMessage.class); Mockito.when(request.getDestinationDataAddress()).thenReturn(dataAddress); Assertions.assertTrue(dataSinkFactory.validateRequest(request).failed()); @@ -94,7 +94,7 @@ void createSink_successful() { var sftpDataAddress = SftpDataAddress.Builder.newInstance().sftpUser(sftpUser).sftpLocation(sftpLocation).build(); - var request = Mockito.mock(DataFlowRequest.class); + var request = Mockito.mock(DataFlowStartMessage.class); Mockito.when(request.getDestinationDataAddress()).thenReturn(sftpDataAddress); try (var staticWrapper = @@ -113,7 +113,7 @@ void createSink_successful() { void createSink_invalidDataAddressType() { var dataSinkFactory = new SftpDataSinkFactory(); var dataAddress = DataAddress.Builder.newInstance().type("wrong").build(); - var request = Mockito.mock(DataFlowRequest.class); + var request = Mockito.mock(DataFlowStartMessage.class); Mockito.when(request.getDestinationDataAddress()).thenReturn(dataAddress); Assertions.assertNull(dataSinkFactory.createSink(request)); diff --git a/edc-extensions/transferprocess-sftp-client/src/test/java/org/eclipse/tractusx/edc/transferprocess/sftp/client/SftpDataSourceFactoryTest.java b/edc-extensions/transferprocess-sftp-client/src/test/java/org/eclipse/tractusx/edc/transferprocess/sftp/client/SftpDataSourceFactoryTest.java index a45e18c79..8f32555ad 100644 --- a/edc-extensions/transferprocess-sftp-client/src/test/java/org/eclipse/tractusx/edc/transferprocess/sftp/client/SftpDataSourceFactoryTest.java +++ b/edc-extensions/transferprocess-sftp-client/src/test/java/org/eclipse/tractusx/edc/transferprocess/sftp/client/SftpDataSourceFactoryTest.java @@ -22,7 +22,7 @@ import org.apache.sshd.sftp.client.SftpClient; import org.eclipse.edc.spi.types.domain.DataAddress; -import org.eclipse.edc.spi.types.domain.transfer.DataFlowRequest; +import org.eclipse.edc.spi.types.domain.transfer.DataFlowStartMessage; import org.eclipse.tractusx.edc.transferprocess.sftp.common.SftpDataAddress; import org.eclipse.tractusx.edc.transferprocess.sftp.common.SftpLocation; import org.eclipse.tractusx.edc.transferprocess.sftp.common.SftpUser; @@ -47,7 +47,7 @@ void validate_valid() { var sftpDataAddress = SftpDataAddress.Builder.newInstance().sftpUser(sftpUser).sftpLocation(sftpLocation).build(); - var request = mock(DataFlowRequest.class); + var request = mock(DataFlowStartMessage.class); when(request.getSourceDataAddress()).thenReturn(sftpDataAddress); Assertions.assertTrue(dataSourceFactory.validateRequest(request).succeeded()); @@ -57,7 +57,7 @@ void validate_valid() { void validate_invalidDataAddressType() { var dataSourceFactory = new SftpDataSourceFactory(); var dataAddress = DataAddress.Builder.newInstance().type("wrong").build(); - var request = mock(DataFlowRequest.class); + var request = mock(DataFlowStartMessage.class); when(request.getSourceDataAddress()).thenReturn(dataAddress); Assertions.assertTrue(dataSourceFactory.validateRequest(request).failed()); @@ -76,7 +76,7 @@ void validate_invalidDataAddressParameters() { "userPassword", "password"); var dataAddress = DataAddress.Builder.newInstance().properties(properties).build(); - var request = mock(DataFlowRequest.class); + var request = mock(DataFlowStartMessage.class); when(request.getSourceDataAddress()).thenReturn(dataAddress); Assertions.assertTrue(dataSourceFactory.validateRequest(request).failed()); @@ -93,7 +93,7 @@ void createSink_successful() { var sftpDataAddress = SftpDataAddress.Builder.newInstance().sftpUser(sftpUser).sftpLocation(sftpLocation).build(); - var request = mock(DataFlowRequest.class); + var request = mock(DataFlowStartMessage.class); when(request.getSourceDataAddress()).thenReturn(sftpDataAddress); try (var staticWrapper = @@ -112,7 +112,7 @@ void createSink_successful() { void createSink_invalidDataAddressType() { var dataSourceFactory = new SftpDataSourceFactory(); var dataAddress = DataAddress.Builder.newInstance().type("wrong").build(); - var request = mock(DataFlowRequest.class); + var request = mock(DataFlowStartMessage.class); when(request.getSourceDataAddress()).thenReturn(dataAddress); Assertions.assertNull(dataSourceFactory.createSource(request)); diff --git a/edc-tests/edc-dataplane/cloud-transfer-tests/src/test/java/org/eclipse/tractusx/edc/dataplane/transfer/test/AzureToAzureTest.java b/edc-tests/edc-dataplane/cloud-transfer-tests/src/test/java/org/eclipse/tractusx/edc/dataplane/transfer/test/AzureToAzureTest.java index ba23e280c..1add84143 100644 --- a/edc-tests/edc-dataplane/cloud-transfer-tests/src/test/java/org/eclipse/tractusx/edc/dataplane/transfer/test/AzureToAzureTest.java +++ b/edc-tests/edc-dataplane/cloud-transfer-tests/src/test/java/org/eclipse/tractusx/edc/dataplane/transfer/test/AzureToAzureTest.java @@ -21,7 +21,7 @@ import io.restassured.http.ContentType; import org.eclipse.edc.azure.testfixtures.annotations.AzureStorageIntegrationTest; -import org.eclipse.edc.spi.types.domain.transfer.DataFlowRequest; +import org.eclipse.edc.spi.types.domain.transfer.DataFlowStartMessage; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; @@ -59,7 +59,7 @@ /** * This test is intended to verify transfers within the same cloud provider, i.e. AzureBlob-to-AzureBlob. - * It spins up a fully-fledged dataplane and issues the DataFlowRequest via the data plane's Control API + * It spins up a fully-fledged dataplane and issues the DataFlowStartMessage via the data plane's Control API */ @SuppressWarnings("resource") @Testcontainers @@ -142,7 +142,7 @@ void transferFile_success() { */ @ParameterizedTest(name = "File size bytes: {0}") // 1mb, 512mb, 1gb - @ValueSource(longs = {1024 * 1024 * 512, 1024L * 1024L * 1024L, /*1024L * 1024L * 1024L * 1024 takes extremely long!*/}) + @ValueSource(longs = { 1024 * 1024 * 512, 1024L * 1024L * 1024L, /*1024L * 1024L * 1024L * 1024 takes extremely long!*/ }) void transferFile_largeFile(long sizeBytes) throws IOException { // upload file to provider's blob store var bcc = providerBlobHelper.createContainer(AZBLOB_PROVIDER_CONTAINER_NAME); @@ -216,8 +216,8 @@ void transferFile_targetContainerNotExist_shouldFail() { .severe(contains("Error creating blob %s on account %s".formatted(TESTFILE_NAME, AZBLOB_CONSUMER_ACCOUNT_NAME)), isA(IOException.class))); } - private DataFlowRequest createFlowRequest(String blobName) { - return DataFlowRequest.Builder.newInstance() + private DataFlowStartMessage createFlowRequest(String blobName) { + return DataFlowStartMessage.Builder.newInstance() .id("test-request") .sourceDataAddress(blobSourceAddress(blobName)) .destinationDataAddress(blobDestinationAddress(blobName)) diff --git a/edc-tests/edc-dataplane/cloud-transfer-tests/src/test/java/org/eclipse/tractusx/edc/dataplane/transfer/test/MultiCloudTest.java b/edc-tests/edc-dataplane/cloud-transfer-tests/src/test/java/org/eclipse/tractusx/edc/dataplane/transfer/test/MultiCloudTest.java index 157599195..013bbe79a 100644 --- a/edc-tests/edc-dataplane/cloud-transfer-tests/src/test/java/org/eclipse/tractusx/edc/dataplane/transfer/test/MultiCloudTest.java +++ b/edc-tests/edc-dataplane/cloud-transfer-tests/src/test/java/org/eclipse/tractusx/edc/dataplane/transfer/test/MultiCloudTest.java @@ -28,7 +28,7 @@ import org.eclipse.edc.azure.testfixtures.annotations.AzureStorageIntegrationTest; import org.eclipse.edc.junit.testfixtures.TestUtils; import org.eclipse.edc.spi.types.domain.DataAddress; -import org.eclipse.edc.spi.types.domain.transfer.DataFlowRequest; +import org.eclipse.edc.spi.types.domain.transfer.DataFlowStartMessage; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; @@ -126,7 +126,7 @@ void transferFile_azureToS3() { assertThat(r.sdkHttpResponse().isSuccessful()).isTrue(); // create data flow request - var dfr = DataFlowRequest.Builder.newInstance() + var dfr = DataFlowStartMessage.Builder.newInstance() .id("test-request") .sourceDataAddress(DataAddress.Builder.newInstance() .type("AzureStorage") @@ -185,7 +185,7 @@ void transferFile_s3ToAzure() { // create data flow request - var dfr = DataFlowRequest.Builder.newInstance() + var dfr = DataFlowStartMessage.Builder.newInstance() .id("test-request") .sourceDataAddress(DataAddress.Builder.newInstance() .type(S3BucketSchema.TYPE) diff --git a/edc-tests/edc-dataplane/cloud-transfer-tests/src/test/java/org/eclipse/tractusx/edc/dataplane/transfer/test/S3ToS3Test.java b/edc-tests/edc-dataplane/cloud-transfer-tests/src/test/java/org/eclipse/tractusx/edc/dataplane/transfer/test/S3ToS3Test.java index 5d3e4aa08..f55e53bc2 100644 --- a/edc-tests/edc-dataplane/cloud-transfer-tests/src/test/java/org/eclipse/tractusx/edc/dataplane/transfer/test/S3ToS3Test.java +++ b/edc-tests/edc-dataplane/cloud-transfer-tests/src/test/java/org/eclipse/tractusx/edc/dataplane/transfer/test/S3ToS3Test.java @@ -27,7 +27,7 @@ import org.eclipse.edc.aws.s3.testfixtures.annotations.AwsS3IntegrationTest; import org.eclipse.edc.junit.testfixtures.TestUtils; import org.eclipse.edc.spi.types.domain.DataAddress; -import org.eclipse.edc.spi.types.domain.transfer.DataFlowRequest; +import org.eclipse.edc.spi.types.domain.transfer.DataFlowStartMessage; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; @@ -71,7 +71,7 @@ /** * This test is intended to verify transfers within the same cloud provider, i.e. S3-to-S3. - * It spins up a fully-fledged dataplane and issues the DataFlowRequest via the data plane's Control API + * It spins up a fully-fledged dataplane and issues the DataFlowStartMessage via the data plane's Control API */ @Testcontainers @AwsS3IntegrationTest @@ -244,8 +244,8 @@ private CompletableFuture uploadLargeFile(File file, String buc } - private DataFlowRequest createFlowRequest() { - return DataFlowRequest.Builder.newInstance() + private DataFlowStartMessage createFlowRequest() { + return DataFlowStartMessage.Builder.newInstance() .id("test-request") .sourceDataAddress(DataAddress.Builder.newInstance() .type(S3BucketSchema.TYPE) From aa2972a675226e0cdf9672ccd264c9623283033b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 26 Feb 2024 10:52:39 +0100 Subject: [PATCH 027/100] chore(deps): bump aws from 2.24.5 to 2.24.10 (#1077) * chore(deps): bump aws from 2.24.5 to 2.24.10 Bumps `aws` from 2.24.5 to 2.24.10. Updates `software.amazon.awssdk:s3` from 2.24.5 to 2.24.10 Updates `software.amazon.awssdk:s3-transfer-manager` from 2.24.5 to 2.24.10 --- updated-dependencies: - dependency-name: software.amazon.awssdk:s3 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:s3-transfer-manager dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] * chore: dependencies file --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Enrico Risa --- DEPENDENCIES | 28 +--------------------------- gradle/libs.versions.toml | 2 +- 2 files changed, 2 insertions(+), 28 deletions(-) diff --git a/DEPENDENCIES b/DEPENDENCIES index b5e362192..d6f2feeaa 100644 --- a/DEPENDENCIES +++ b/DEPENDENCIES @@ -492,58 +492,32 @@ maven/mavencentral/org.xmlresolver/xmlresolver/5.2.2, Apache-2.0, approved, clea maven/mavencentral/org.yaml/snakeyaml/2.0, Apache-2.0 AND (Apache-2.0 OR BSD-3-Clause OR EPL-1.0 OR GPL-2.0-or-later OR LGPL-2.1-or-later), approved, #7275 maven/mavencentral/org.yaml/snakeyaml/2.2, Apache-2.0 AND (Apache-2.0 OR BSD-3-Clause OR EPL-1.0 OR GPL-2.0-or-later OR LGPL-2.1-or-later), approved, #10232 maven/mavencentral/software.amazon.awssdk/annotations/2.24.10, Apache-2.0, approved, #13251 -maven/mavencentral/software.amazon.awssdk/annotations/2.24.5, Apache-2.0, approved, #13251 maven/mavencentral/software.amazon.awssdk/apache-client/2.24.10, Apache-2.0, approved, #13257 -maven/mavencentral/software.amazon.awssdk/apache-client/2.24.5, Apache-2.0, approved, #13257 maven/mavencentral/software.amazon.awssdk/arns/2.24.10, Apache-2.0, approved, #13243 -maven/mavencentral/software.amazon.awssdk/arns/2.24.5, Apache-2.0, approved, #13243 maven/mavencentral/software.amazon.awssdk/auth/2.24.10, Apache-2.0, approved, #13256 -maven/mavencentral/software.amazon.awssdk/auth/2.24.5, Apache-2.0, approved, #13256 maven/mavencentral/software.amazon.awssdk/aws-core/2.24.10, Apache-2.0, approved, #13240 -maven/mavencentral/software.amazon.awssdk/aws-core/2.24.5, Apache-2.0, approved, #13240 maven/mavencentral/software.amazon.awssdk/aws-query-protocol/2.24.10, Apache-2.0, approved, #13262 -maven/mavencentral/software.amazon.awssdk/aws-query-protocol/2.24.5, Apache-2.0, approved, #13262 maven/mavencentral/software.amazon.awssdk/aws-xml-protocol/2.24.10, Apache-2.0, approved, #13247 -maven/mavencentral/software.amazon.awssdk/aws-xml-protocol/2.24.5, Apache-2.0, approved, #13247 maven/mavencentral/software.amazon.awssdk/checksums-spi/2.24.10, Apache-2.0, approved, #13245 -maven/mavencentral/software.amazon.awssdk/checksums-spi/2.24.5, Apache-2.0, approved, #13245 maven/mavencentral/software.amazon.awssdk/checksums/2.24.10, Apache-2.0, approved, #13242 -maven/mavencentral/software.amazon.awssdk/checksums/2.24.5, Apache-2.0, approved, #13242 maven/mavencentral/software.amazon.awssdk/crt-core/2.24.10, Apache-2.0, approved, #13252 -maven/mavencentral/software.amazon.awssdk/crt-core/2.24.5, Apache-2.0, approved, #13252 maven/mavencentral/software.amazon.awssdk/endpoints-spi/2.24.10, Apache-2.0, approved, #13246 -maven/mavencentral/software.amazon.awssdk/endpoints-spi/2.24.5, Apache-2.0, approved, #13246 maven/mavencentral/software.amazon.awssdk/http-auth-aws/2.24.10, Apache-2.0, approved, #13253 -maven/mavencentral/software.amazon.awssdk/http-auth-aws/2.24.5, Apache-2.0, approved, #13253 maven/mavencentral/software.amazon.awssdk/http-auth-spi/2.24.10, Apache-2.0, approved, #13264 -maven/mavencentral/software.amazon.awssdk/http-auth-spi/2.24.5, Apache-2.0, approved, #13264 maven/mavencentral/software.amazon.awssdk/http-auth/2.24.10, Apache-2.0, approved, #13248 -maven/mavencentral/software.amazon.awssdk/http-auth/2.24.5, Apache-2.0, approved, #13248 maven/mavencentral/software.amazon.awssdk/http-client-spi/2.24.10, Apache-2.0, approved, #13259 -maven/mavencentral/software.amazon.awssdk/http-client-spi/2.24.5, Apache-2.0, approved, #13259 maven/mavencentral/software.amazon.awssdk/iam/2.24.10, , restricted, clearlydefined maven/mavencentral/software.amazon.awssdk/identity-spi/2.24.10, Apache-2.0, approved, #13244 -maven/mavencentral/software.amazon.awssdk/identity-spi/2.24.5, Apache-2.0, approved, #13244 maven/mavencentral/software.amazon.awssdk/json-utils/2.24.10, Apache-2.0, approved, #13261 -maven/mavencentral/software.amazon.awssdk/json-utils/2.24.5, Apache-2.0, approved, #13261 maven/mavencentral/software.amazon.awssdk/metrics-spi/2.24.10, Apache-2.0, approved, #13239 -maven/mavencentral/software.amazon.awssdk/metrics-spi/2.24.5, Apache-2.0, approved, #13239 maven/mavencentral/software.amazon.awssdk/netty-nio-client/2.24.10, Apache-2.0, approved, #13260 -maven/mavencentral/software.amazon.awssdk/netty-nio-client/2.24.5, Apache-2.0, approved, #13260 maven/mavencentral/software.amazon.awssdk/profiles/2.24.10, Apache-2.0, approved, #13258 -maven/mavencentral/software.amazon.awssdk/profiles/2.24.5, Apache-2.0, approved, #13258 maven/mavencentral/software.amazon.awssdk/protocol-core/2.24.10, Apache-2.0, approved, #13241 -maven/mavencentral/software.amazon.awssdk/protocol-core/2.24.5, Apache-2.0, approved, #13241 maven/mavencentral/software.amazon.awssdk/regions/2.24.10, Apache-2.0, approved, #13255 -maven/mavencentral/software.amazon.awssdk/regions/2.24.5, Apache-2.0, approved, #13255 -maven/mavencentral/software.amazon.awssdk/s3-transfer-manager/2.24.5, Apache-2.0, approved, #13263 +maven/mavencentral/software.amazon.awssdk/s3-transfer-manager/2.24.10, Apache-2.0, approved, #13263 maven/mavencentral/software.amazon.awssdk/s3/2.24.10, Apache-2.0, approved, #13254 -maven/mavencentral/software.amazon.awssdk/s3/2.24.5, Apache-2.0, approved, #13254 maven/mavencentral/software.amazon.awssdk/sdk-core/2.24.10, Apache-2.0, approved, #13265 -maven/mavencentral/software.amazon.awssdk/sdk-core/2.24.5, Apache-2.0, approved, #13265 maven/mavencentral/software.amazon.awssdk/sts/2.24.10, , restricted, clearlydefined maven/mavencentral/software.amazon.awssdk/third-party-jackson-core/2.24.10, Apache-2.0, approved, #13249 -maven/mavencentral/software.amazon.awssdk/third-party-jackson-core/2.24.5, Apache-2.0, approved, #13249 maven/mavencentral/software.amazon.awssdk/utils/2.24.10, Apache-2.0, approved, #13250 -maven/mavencentral/software.amazon.awssdk/utils/2.24.5, Apache-2.0, approved, #13250 maven/mavencentral/software.amazon.eventstream/eventstream/1.0.1, Apache-2.0, approved, clearlydefined diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 7faba232e..bed1c478b 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -6,7 +6,7 @@ edc = "0.5.2-SNAPSHOT" apache-sshd = "2.12.1" assertj = "3.25.3" awaitility = "4.2.0" -aws = "2.24.5" +aws = "2.24.10" azure-identity = "1.11.2" bouncyCastle-jdk18on = "1.77" flyway = "10.8.1" From a9a7db17530ccbc2cdf2217b5492f6066d8b9f1b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 26 Feb 2024 11:25:31 +0100 Subject: [PATCH 028/100] chore(deps): bump testcontainers from 1.19.5 to 1.19.6 (#1078) * chore(deps): bump testcontainers from 1.19.5 to 1.19.6 Bumps `testcontainers` from 1.19.5 to 1.19.6. Updates `org.testcontainers:junit-jupiter` from 1.19.5 to 1.19.6 - [Release notes](https://github.com/testcontainers/testcontainers-java/releases) - [Changelog](https://github.com/testcontainers/testcontainers-java/blob/main/CHANGELOG.md) - [Commits](https://github.com/testcontainers/testcontainers-java/compare/1.19.5...1.19.6) Updates `org.testcontainers:postgresql` from 1.19.5 to 1.19.6 - [Release notes](https://github.com/testcontainers/testcontainers-java/releases) - [Changelog](https://github.com/testcontainers/testcontainers-java/blob/main/CHANGELOG.md) - [Commits](https://github.com/testcontainers/testcontainers-java/compare/1.19.5...1.19.6) Updates `org.testcontainers:vault` from 1.19.5 to 1.19.6 - [Release notes](https://github.com/testcontainers/testcontainers-java/releases) - [Changelog](https://github.com/testcontainers/testcontainers-java/blob/main/CHANGELOG.md) - [Commits](https://github.com/testcontainers/testcontainers-java/compare/1.19.5...1.19.6) --- updated-dependencies: - dependency-name: org.testcontainers:junit-jupiter dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.testcontainers:postgresql dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.testcontainers:vault dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] * chore: dependencies file --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Enrico Risa --- DEPENDENCIES | 5 ++++- gradle/libs.versions.toml | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/DEPENDENCIES b/DEPENDENCIES index d6f2feeaa..5b656d191 100644 --- a/DEPENDENCIES +++ b/DEPENDENCIES @@ -481,13 +481,16 @@ maven/mavencentral/org.slf4j/slf4j-api/1.7.7, MIT, approved, CQ9827 maven/mavencentral/org.slf4j/slf4j-api/2.0.12, MIT, approved, #5915 maven/mavencentral/org.slf4j/slf4j-api/2.0.9, MIT, approved, #5915 maven/mavencentral/org.testcontainers/database-commons/1.19.5, Apache-2.0, approved, #10345 +maven/mavencentral/org.testcontainers/database-commons/1.19.6, Apache-2.0, approved, #10345 maven/mavencentral/org.testcontainers/jdbc/1.19.5, Apache-2.0, approved, #10348 +maven/mavencentral/org.testcontainers/jdbc/1.19.6, Apache-2.0, approved, #10348 maven/mavencentral/org.testcontainers/junit-jupiter/1.19.5, MIT, approved, #10344 maven/mavencentral/org.testcontainers/junit-jupiter/1.19.6, MIT, approved, #10344 maven/mavencentral/org.testcontainers/postgresql/1.19.5, MIT, approved, #10350 +maven/mavencentral/org.testcontainers/postgresql/1.19.6, MIT, approved, #10350 maven/mavencentral/org.testcontainers/testcontainers/1.19.5, Apache-2.0 AND MIT, approved, #10347 maven/mavencentral/org.testcontainers/testcontainers/1.19.6, Apache-2.0 AND MIT, approved, #10347 -maven/mavencentral/org.testcontainers/vault/1.19.5, MIT, approved, #10852 +maven/mavencentral/org.testcontainers/vault/1.19.6, MIT, approved, #10852 maven/mavencentral/org.xmlresolver/xmlresolver/5.2.2, Apache-2.0, approved, clearlydefined maven/mavencentral/org.yaml/snakeyaml/2.0, Apache-2.0 AND (Apache-2.0 OR BSD-3-Clause OR EPL-1.0 OR GPL-2.0-or-later OR LGPL-2.1-or-later), approved, #7275 maven/mavencentral/org.yaml/snakeyaml/2.2, Apache-2.0 AND (Apache-2.0 OR BSD-3-Clause OR EPL-1.0 OR GPL-2.0-or-later OR LGPL-2.1-or-later), approved, #10232 diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index bed1c478b..4be7d4960 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -21,7 +21,7 @@ postgres = "42.7.1" restAssured = "5.4.0" rsApi = "3.1.0" slf4j = "2.0.12" -testcontainers = "1.19.5" +testcontainers = "1.19.6" tink = "1.12.0" titanium = "1.3.3" From bb3e313e8d22203560f126a7bc3c82bb38c7fa56 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 26 Feb 2024 12:21:59 +0100 Subject: [PATCH 029/100] chore(deps): bump mikefarah/yq from 4.41.1 to 4.42.1 (#1079) Bumps [mikefarah/yq](https://github.com/mikefarah/yq) from 4.41.1 to 4.42.1. - [Release notes](https://github.com/mikefarah/yq/releases) - [Changelog](https://github.com/mikefarah/yq/blob/master/release_notes.txt) - [Commits](https://github.com/mikefarah/yq/compare/v4.41.1...v4.42.1) --- updated-dependencies: - dependency-name: mikefarah/yq dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/draft-new-release.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/draft-new-release.yaml b/.github/workflows/draft-new-release.yaml index b6ce90acf..48033a9bd 100644 --- a/.github/workflows/draft-new-release.yaml +++ b/.github/workflows/draft-new-release.yaml @@ -54,7 +54,7 @@ jobs: GITHUB_PACKAGE_USERNAME: ${{ github.actor }} GITHUB_PACKAGE_PASSWORD: ${{ secrets.GITHUB_TOKEN }} - name: Bump version in /charts - uses: mikefarah/yq@v4.41.1 + uses: mikefarah/yq@v4.42.1 with: cmd: |- find charts -name Chart.yaml -maxdepth 3 | xargs -n1 yq -i '.appVersion = "${{ github.event.inputs.version }}" | .version = "${{ github.event.inputs.version }}"' From ed22d0ce5343279e0aede2ce3b57b01420741c05 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 26 Feb 2024 12:44:22 +0100 Subject: [PATCH 030/100] chore(deps): bump actions/upload-artifact from 3 to 4 (#1080) Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 3 to 4. - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/upload-artifact dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/dast-scan.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/dast-scan.yaml b/.github/workflows/dast-scan.yaml index ab993e800..4f7693c50 100644 --- a/.github/workflows/dast-scan.yaml +++ b/.github/workflows/dast-scan.yaml @@ -85,7 +85,7 @@ jobs: - name: Upload HTML report if: success() || failure() - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: ZAP_API scan report path: ./API_report.html @@ -117,7 +117,7 @@ jobs: - name: Upload HTML report if: success() || failure() - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: ZAP_FULL scan report path: ./fullscan_report.html \ No newline at end of file From 1ed0bb35bf2f7eab20e5a24bd924b942c10b9bab Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 26 Feb 2024 13:05:27 +0100 Subject: [PATCH 031/100] chore(deps): bump org.postgresql:postgresql from 42.7.1 to 42.7.2 (#1081) Bumps [org.postgresql:postgresql](https://github.com/pgjdbc/pgjdbc) from 42.7.1 to 42.7.2. - [Release notes](https://github.com/pgjdbc/pgjdbc/releases) - [Changelog](https://github.com/pgjdbc/pgjdbc/blob/master/CHANGELOG.md) - [Commits](https://github.com/pgjdbc/pgjdbc/compare/REL42.7.1...REL42.7.2) --- updated-dependencies: - dependency-name: org.postgresql:postgresql dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 4be7d4960..a6046fb4b 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -17,7 +17,7 @@ jupiter = "5.10.2" mockwebserver = "5.0.0-alpha.12" nimbus = "9.37.3" okhttp = "4.12.0" -postgres = "42.7.1" +postgres = "42.7.2" restAssured = "5.4.0" rsApi = "3.1.0" slf4j = "2.0.12" From d3cbf44e0d92d643a5903043a1f6aed644bc05f3 Mon Sep 17 00:00:00 2001 From: Enrico Risa Date: Wed, 28 Feb 2024 13:56:59 +0100 Subject: [PATCH 032/100] chore: fix compile issue after trackable removal (#1085) --- DEPENDENCIES | 21 ++++++------------- .../asset/ConsumerAssetRequestController.java | 1 - .../gateway/ProviderGatewayController.java | 1 - ...__Alter_TransferProcess_AddDataPlaneId.sql | 15 +++++++++++++ .../transfer/test/AzureToAzureTest.java | 1 - .../transfer/test/MultiCloudTest.java | 2 -- .../dataplane/transfer/test/S3ToS3Test.java | 1 - 7 files changed, 21 insertions(+), 21 deletions(-) create mode 100644 edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/transferprocess/V0_0_14__Alter_TransferProcess_AddDataPlaneId.sql diff --git a/DEPENDENCIES b/DEPENDENCIES index 5b656d191..38f6e3b88 100644 --- a/DEPENDENCIES +++ b/DEPENDENCIES @@ -11,9 +11,9 @@ maven/mavencentral/com.azure/azure-core/1.46.0, MIT AND Apache-2.0, approved, #1 maven/mavencentral/com.azure/azure-identity/1.11.2, MIT AND Apache-2.0, approved, #13237 maven/mavencentral/com.azure/azure-json/1.1.0, MIT AND Apache-2.0, approved, #10547 maven/mavencentral/com.azure/azure-security-keyvault-secrets/4.7.3, MIT, approved, #10868 -maven/mavencentral/com.azure/azure-storage-blob/12.25.2, , restricted, clearlydefined -maven/mavencentral/com.azure/azure-storage-common/12.24.2, , restricted, clearlydefined -maven/mavencentral/com.azure/azure-storage-internal-avro/12.10.2, , restricted, clearlydefined +maven/mavencentral/com.azure/azure-storage-blob/12.25.2, MIT, approved, #13400 +maven/mavencentral/com.azure/azure-storage-common/12.24.2, MIT, approved, #13402 +maven/mavencentral/com.azure/azure-storage-internal-avro/12.10.2, MIT, approved, #13399 maven/mavencentral/com.fasterxml.jackson.core/jackson-annotations/2.10.3, Apache-2.0, approved, CQ21280 maven/mavencentral/com.fasterxml.jackson.core/jackson-annotations/2.13.5, Apache-2.0, approved, clearlydefined maven/mavencentral/com.fasterxml.jackson.core/jackson-annotations/2.15.1, Apache-2.0, approved, #7947 @@ -51,11 +51,8 @@ maven/mavencentral/com.fasterxml.jackson.module/jackson-module-jakarta-xmlbind-a maven/mavencentral/com.fasterxml.jackson/jackson-bom/2.15.1, Apache-2.0, approved, #7929 maven/mavencentral/com.fasterxml.jackson/jackson-bom/2.16.1, Apache-2.0, approved, #11852 maven/mavencentral/com.fasterxml.woodstox/woodstox-core/6.5.1, Apache-2.0, approved, #7950 -maven/mavencentral/com.github.docker-java/docker-java-api/3.3.4, Apache-2.0, approved, #10346 maven/mavencentral/com.github.docker-java/docker-java-api/3.3.5, Apache-2.0, approved, #10346 -maven/mavencentral/com.github.docker-java/docker-java-transport-zerodep/3.3.4, Apache-2.0 AND (Apache-2.0 AND BSD-3-Clause), approved, #7946 maven/mavencentral/com.github.docker-java/docker-java-transport-zerodep/3.3.5, Apache-2.0 AND (Apache-2.0 AND BSD-3-Clause), approved, #7946 -maven/mavencentral/com.github.docker-java/docker-java-transport/3.3.4, Apache-2.0, approved, #7942 maven/mavencentral/com.github.docker-java/docker-java-transport/3.3.5, Apache-2.0, approved, #7942 maven/mavencentral/com.github.stephenc.jcip/jcip-annotations/1.0-1, Apache-2.0, approved, CQ21949 maven/mavencentral/com.google.code.findbugs/jsr305/3.0.2, Apache-2.0, approved, #20 @@ -76,7 +73,7 @@ maven/mavencentral/com.nimbusds/lang-tag/1.7, Apache-2.0, approved, clearlydefin maven/mavencentral/com.nimbusds/nimbus-jose-jwt/9.30.2, Apache-2.0, approved, clearlydefined maven/mavencentral/com.nimbusds/nimbus-jose-jwt/9.37.3, Apache-2.0, approved, #11701 maven/mavencentral/com.nimbusds/oauth2-oidc-sdk/10.7.1, Apache-2.0, approved, clearlydefined -maven/mavencentral/com.puppycrawl.tools/checkstyle/10.13.0, , restricted, clearlydefined +maven/mavencentral/com.puppycrawl.tools/checkstyle/10.13.0, LGPL-2.1-or-later AND (Apache-2.0 AND LGPL-2.1-or-later) AND Apache-2.0, approved, #13403 maven/mavencentral/com.squareup.okhttp3/mockwebserver/5.0.0-alpha.12, Apache-2.0, approved, clearlydefined maven/mavencentral/com.squareup.okhttp3/mockwebserver3/5.0.0-alpha.12, Apache-2.0, approved, clearlydefined maven/mavencentral/com.squareup.okhttp3/okhttp-dnsoverhttps/4.12.0, Apache-2.0, approved, #11159 @@ -466,7 +463,6 @@ maven/mavencentral/org.ow2.asm/asm-tree/9.6, BSD-3-Clause, approved, #10773 maven/mavencentral/org.ow2.asm/asm/9.3, BSD-3-Clause, approved, clearlydefined maven/mavencentral/org.ow2.asm/asm/9.5, BSD-3-Clause, approved, #7554 maven/mavencentral/org.ow2.asm/asm/9.6, BSD-3-Clause, approved, #10776 -maven/mavencentral/org.postgresql/postgresql/42.7.1, BSD-2-Clause AND Apache-2.0, approved, #11681 maven/mavencentral/org.postgresql/postgresql/42.7.2, BSD-2-Clause AND Apache-2.0, approved, #11681 maven/mavencentral/org.reactivestreams/reactive-streams/1.0.4, CC0-1.0, approved, CQ16332 maven/mavencentral/org.reflections/reflections/0.10.2, Apache-2.0 AND WTFPL, approved, clearlydefined @@ -480,15 +476,10 @@ maven/mavencentral/org.slf4j/slf4j-api/1.7.36, MIT, approved, CQ13368 maven/mavencentral/org.slf4j/slf4j-api/1.7.7, MIT, approved, CQ9827 maven/mavencentral/org.slf4j/slf4j-api/2.0.12, MIT, approved, #5915 maven/mavencentral/org.slf4j/slf4j-api/2.0.9, MIT, approved, #5915 -maven/mavencentral/org.testcontainers/database-commons/1.19.5, Apache-2.0, approved, #10345 maven/mavencentral/org.testcontainers/database-commons/1.19.6, Apache-2.0, approved, #10345 -maven/mavencentral/org.testcontainers/jdbc/1.19.5, Apache-2.0, approved, #10348 maven/mavencentral/org.testcontainers/jdbc/1.19.6, Apache-2.0, approved, #10348 -maven/mavencentral/org.testcontainers/junit-jupiter/1.19.5, MIT, approved, #10344 maven/mavencentral/org.testcontainers/junit-jupiter/1.19.6, MIT, approved, #10344 -maven/mavencentral/org.testcontainers/postgresql/1.19.5, MIT, approved, #10350 maven/mavencentral/org.testcontainers/postgresql/1.19.6, MIT, approved, #10350 -maven/mavencentral/org.testcontainers/testcontainers/1.19.5, Apache-2.0 AND MIT, approved, #10347 maven/mavencentral/org.testcontainers/testcontainers/1.19.6, Apache-2.0 AND MIT, approved, #10347 maven/mavencentral/org.testcontainers/vault/1.19.6, MIT, approved, #10852 maven/mavencentral/org.xmlresolver/xmlresolver/5.2.2, Apache-2.0, approved, clearlydefined @@ -509,7 +500,7 @@ maven/mavencentral/software.amazon.awssdk/http-auth-aws/2.24.10, Apache-2.0, app maven/mavencentral/software.amazon.awssdk/http-auth-spi/2.24.10, Apache-2.0, approved, #13264 maven/mavencentral/software.amazon.awssdk/http-auth/2.24.10, Apache-2.0, approved, #13248 maven/mavencentral/software.amazon.awssdk/http-client-spi/2.24.10, Apache-2.0, approved, #13259 -maven/mavencentral/software.amazon.awssdk/iam/2.24.10, , restricted, clearlydefined +maven/mavencentral/software.amazon.awssdk/iam/2.24.10, Apache-2.0, approved, #13444 maven/mavencentral/software.amazon.awssdk/identity-spi/2.24.10, Apache-2.0, approved, #13244 maven/mavencentral/software.amazon.awssdk/json-utils/2.24.10, Apache-2.0, approved, #13261 maven/mavencentral/software.amazon.awssdk/metrics-spi/2.24.10, Apache-2.0, approved, #13239 @@ -520,7 +511,7 @@ maven/mavencentral/software.amazon.awssdk/regions/2.24.10, Apache-2.0, approved, maven/mavencentral/software.amazon.awssdk/s3-transfer-manager/2.24.10, Apache-2.0, approved, #13263 maven/mavencentral/software.amazon.awssdk/s3/2.24.10, Apache-2.0, approved, #13254 maven/mavencentral/software.amazon.awssdk/sdk-core/2.24.10, Apache-2.0, approved, #13265 -maven/mavencentral/software.amazon.awssdk/sts/2.24.10, , restricted, clearlydefined +maven/mavencentral/software.amazon.awssdk/sts/2.24.10, Apache-2.0, approved, #13442 maven/mavencentral/software.amazon.awssdk/third-party-jackson-core/2.24.10, Apache-2.0, approved, #13249 maven/mavencentral/software.amazon.awssdk/utils/2.24.10, Apache-2.0, approved, #13250 maven/mavencentral/software.amazon.eventstream/eventstream/1.0.1, Apache-2.0, approved, clearlydefined diff --git a/edc-extensions/dataplane-proxy/edc-dataplane-proxy-consumer-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/consumer/api/asset/ConsumerAssetRequestController.java b/edc-extensions/dataplane-proxy/edc-dataplane-proxy-consumer-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/consumer/api/asset/ConsumerAssetRequestController.java index b6232ac2f..8e620f932 100644 --- a/edc-extensions/dataplane-proxy/edc-dataplane-proxy-consumer-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/consumer/api/asset/ConsumerAssetRequestController.java +++ b/edc-extensions/dataplane-proxy/edc-dataplane-proxy-consumer-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/consumer/api/asset/ConsumerAssetRequestController.java @@ -107,7 +107,6 @@ public void requestAsset(AssetRequest request, @Suspended AsyncResponse response var flowRequest = DataFlowStartMessage.Builder.newInstance() .processId(randomUUID().toString()) - .trackable(false) .sourceDataAddress(sourceAddress) .destinationDataAddress(destinationAddress) .traceContext(Map.of()) diff --git a/edc-extensions/dataplane-proxy/edc-dataplane-proxy-provider-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/api/gateway/ProviderGatewayController.java b/edc-extensions/dataplane-proxy/edc-dataplane-proxy-provider-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/api/gateway/ProviderGatewayController.java index fcff2cf0d..00243cdc0 100644 --- a/edc-extensions/dataplane-proxy/edc-dataplane-proxy-provider-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/api/gateway/ProviderGatewayController.java +++ b/edc-extensions/dataplane-proxy/edc-dataplane-proxy-provider-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/api/gateway/ProviderGatewayController.java @@ -182,7 +182,6 @@ private DataFlowStartMessage createRequest(String subPath, GatewayConfiguration return DataFlowStartMessage.Builder.newInstance() .processId(randomUUID().toString()) - .trackable(false) .sourceDataAddress(sourceAddressBuilder.build()) .destinationDataAddress(destinationAddress) .traceContext(Map.of()) diff --git a/edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/transferprocess/V0_0_14__Alter_TransferProcess_AddDataPlaneId.sql b/edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/transferprocess/V0_0_14__Alter_TransferProcess_AddDataPlaneId.sql new file mode 100644 index 000000000..c76c88529 --- /dev/null +++ b/edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/transferprocess/V0_0_14__Alter_TransferProcess_AddDataPlaneId.sql @@ -0,0 +1,15 @@ +-- +-- Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +-- +-- This program and the accompanying materials are made available under the +-- terms of the Apache License, Version 2.0 which is available at +-- https://www.apache.org/licenses/LICENSE-2.0 +-- +-- SPDX-License-Identifier: Apache-2.0 +-- +-- Contributors: +-- Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - initial API and implementation +-- + +-- add column +ALTER TABLE edc_transfer_process ADD COLUMN data_plane_id VARCHAR; diff --git a/edc-tests/edc-dataplane/cloud-transfer-tests/src/test/java/org/eclipse/tractusx/edc/dataplane/transfer/test/AzureToAzureTest.java b/edc-tests/edc-dataplane/cloud-transfer-tests/src/test/java/org/eclipse/tractusx/edc/dataplane/transfer/test/AzureToAzureTest.java index 1add84143..6b4846d95 100644 --- a/edc-tests/edc-dataplane/cloud-transfer-tests/src/test/java/org/eclipse/tractusx/edc/dataplane/transfer/test/AzureToAzureTest.java +++ b/edc-tests/edc-dataplane/cloud-transfer-tests/src/test/java/org/eclipse/tractusx/edc/dataplane/transfer/test/AzureToAzureTest.java @@ -222,7 +222,6 @@ private DataFlowStartMessage createFlowRequest(String blobName) { .sourceDataAddress(blobSourceAddress(blobName)) .destinationDataAddress(blobDestinationAddress(blobName)) .processId("test-process-id") - .trackable(false) .build(); } diff --git a/edc-tests/edc-dataplane/cloud-transfer-tests/src/test/java/org/eclipse/tractusx/edc/dataplane/transfer/test/MultiCloudTest.java b/edc-tests/edc-dataplane/cloud-transfer-tests/src/test/java/org/eclipse/tractusx/edc/dataplane/transfer/test/MultiCloudTest.java index 013bbe79a..06cad6f16 100644 --- a/edc-tests/edc-dataplane/cloud-transfer-tests/src/test/java/org/eclipse/tractusx/edc/dataplane/transfer/test/MultiCloudTest.java +++ b/edc-tests/edc-dataplane/cloud-transfer-tests/src/test/java/org/eclipse/tractusx/edc/dataplane/transfer/test/MultiCloudTest.java @@ -147,7 +147,6 @@ void transferFile_azureToS3() { .build() ) .processId("test-process-id") - .trackable(false) .build(); var url = "http://localhost:%s/control/transfer".formatted(PROVIDER_CONTROL_PORT); @@ -199,7 +198,6 @@ void transferFile_s3ToAzure() { ) .destinationDataAddress(blobDestinationAddress(TESTFILE_NAME)) .processId("test-process-id") - .trackable(false) .build(); var url = "http://localhost:%s/control/transfer".formatted(PROVIDER_CONTROL_PORT); diff --git a/edc-tests/edc-dataplane/cloud-transfer-tests/src/test/java/org/eclipse/tractusx/edc/dataplane/transfer/test/S3ToS3Test.java b/edc-tests/edc-dataplane/cloud-transfer-tests/src/test/java/org/eclipse/tractusx/edc/dataplane/transfer/test/S3ToS3Test.java index f55e53bc2..afe18f394 100644 --- a/edc-tests/edc-dataplane/cloud-transfer-tests/src/test/java/org/eclipse/tractusx/edc/dataplane/transfer/test/S3ToS3Test.java +++ b/edc-tests/edc-dataplane/cloud-transfer-tests/src/test/java/org/eclipse/tractusx/edc/dataplane/transfer/test/S3ToS3Test.java @@ -268,7 +268,6 @@ private DataFlowStartMessage createFlowRequest() { .build() ) .processId("test-process-id") - .trackable(false) .build(); } From 7883ba5ce2bd8d799516d16b14055d060e793cca Mon Sep 17 00:00:00 2001 From: Enrico Risa Date: Mon, 4 Mar 2024 14:31:07 +0100 Subject: [PATCH 033/100] chore: updates tx with the latest EDC changes (#1101) * chore: updates tx with the latest EDC changes * chore: dependencies file --- DEPENDENCIES | 7 +++--- .../edc/lifecycle/tx/ParticipantEdrApi.java | 6 ++++- .../edc/lifecycle/tx/TxParticipant.java | 23 +++++++++++++++---- 3 files changed, 27 insertions(+), 9 deletions(-) diff --git a/DEPENDENCIES b/DEPENDENCIES index 38f6e3b88..dd69edb1b 100644 --- a/DEPENDENCIES +++ b/DEPENDENCIES @@ -73,7 +73,7 @@ maven/mavencentral/com.nimbusds/lang-tag/1.7, Apache-2.0, approved, clearlydefin maven/mavencentral/com.nimbusds/nimbus-jose-jwt/9.30.2, Apache-2.0, approved, clearlydefined maven/mavencentral/com.nimbusds/nimbus-jose-jwt/9.37.3, Apache-2.0, approved, #11701 maven/mavencentral/com.nimbusds/oauth2-oidc-sdk/10.7.1, Apache-2.0, approved, clearlydefined -maven/mavencentral/com.puppycrawl.tools/checkstyle/10.13.0, LGPL-2.1-or-later AND (Apache-2.0 AND LGPL-2.1-or-later) AND Apache-2.0, approved, #13403 +maven/mavencentral/com.puppycrawl.tools/checkstyle/10.14.0, , restricted, clearlydefined maven/mavencentral/com.squareup.okhttp3/mockwebserver/5.0.0-alpha.12, Apache-2.0, approved, clearlydefined maven/mavencentral/com.squareup.okhttp3/mockwebserver3/5.0.0-alpha.12, Apache-2.0, approved, clearlydefined maven/mavencentral/com.squareup.okhttp3/okhttp-dnsoverhttps/4.12.0, Apache-2.0, approved, #11159 @@ -174,9 +174,10 @@ maven/mavencentral/javax.servlet/javax.servlet-api/3.1.0, (CDDL-1.1 OR GPL-2.0-o maven/mavencentral/javax.ws.rs/javax.ws.rs-api/2.1, (CDDL-1.1 OR GPL-2.0 WITH Classpath-exception-2.0) AND Apache-2.0, approved, CQ18121 maven/mavencentral/junit/junit/4.13.2, EPL-2.0, approved, CQ23636 maven/mavencentral/net.bytebuddy/byte-buddy-agent/1.14.1, Apache-2.0, approved, #7164 -maven/mavencentral/net.bytebuddy/byte-buddy-agent/1.14.11, Apache-2.0, approved, #7164 +maven/mavencentral/net.bytebuddy/byte-buddy-agent/1.14.12, Apache-2.0, approved, #7164 maven/mavencentral/net.bytebuddy/byte-buddy/1.14.1, Apache-2.0 AND BSD-3-Clause, approved, #7163 maven/mavencentral/net.bytebuddy/byte-buddy/1.14.11, Apache-2.0 AND BSD-3-Clause, approved, #7163 +maven/mavencentral/net.bytebuddy/byte-buddy/1.14.12, Apache-2.0 AND BSD-3-Clause, approved, #7163 maven/mavencentral/net.java.dev.jna/jna-platform/5.13.0, Apache-2.0 OR LGPL-2.1-or-later, approved, #6707 maven/mavencentral/net.java.dev.jna/jna-platform/5.6.0, Apache-2.0 OR LGPL-2.1-or-later, approved, CQ22390 maven/mavencentral/net.java.dev.jna/jna/5.13.0, Apache-2.0 AND LGPL-2.1-or-later, approved, #6709 @@ -452,8 +453,8 @@ maven/mavencentral/org.junit/junit-bom/5.10.2, EPL-2.0, approved, #9844 maven/mavencentral/org.junit/junit-bom/5.9.2, EPL-2.0, approved, #4711 maven/mavencentral/org.jvnet.mimepull/mimepull/1.9.15, CDDL-1.1 OR GPL-2.0-only WITH Classpath-exception-2.0, approved, CQ21484 maven/mavencentral/org.latencyutils/LatencyUtils/2.0.3, BSD-2-Clause, approved, CQ17408 +maven/mavencentral/org.mockito/mockito-core/5.11.0, MIT AND (Apache-2.0 AND MIT) AND Apache-2.0, approved, #13505 maven/mavencentral/org.mockito/mockito-core/5.2.0, MIT AND (Apache-2.0 AND MIT) AND Apache-2.0, approved, #7401 -maven/mavencentral/org.mockito/mockito-core/5.9.0, MIT AND (Apache-2.0 AND MIT) AND Apache-2.0, approved, #12774 maven/mavencentral/org.objenesis/objenesis/3.3, Apache-2.0, approved, clearlydefined maven/mavencentral/org.opentest4j/opentest4j/1.3.0, Apache-2.0, approved, #9713 maven/mavencentral/org.ow2.asm/asm-commons/9.5, BSD-3-Clause, approved, #7553 diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/tx/ParticipantEdrApi.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/tx/ParticipantEdrApi.java index 473ada2f1..2a06eb038 100644 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/tx/ParticipantEdrApi.java +++ b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/tx/ParticipantEdrApi.java @@ -34,6 +34,7 @@ import static jakarta.json.Json.createObjectBuilder; import static org.assertj.core.api.Assertions.assertThat; import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.ID; +import static org.eclipse.edc.jsonld.spi.PropertyAndTypeNames.ODRL_ASSIGNER_ATTRIBUTE; import static org.eclipse.edc.jsonld.spi.PropertyAndTypeNames.ODRL_TARGET_ATTRIBUTE; import static org.eclipse.tractusx.edc.helpers.CatalogHelperFunctions.getDatasetContractId; import static org.eclipse.tractusx.edc.helpers.CatalogHelperFunctions.getDatasetFirstPolicy; @@ -113,7 +114,10 @@ public String negotiateEdr(TxParticipant other, String assetId, JsonArray callba var dataset = participant.getDatasetForAsset(other, assetId); assertThat(dataset).withFailMessage("Catalog received from " + other.getName() + " was empty!").isNotEmpty(); - var policy = createObjectBuilder(getDatasetFirstPolicy(dataset)).add(ODRL_TARGET_ATTRIBUTE, createObjectBuilder().add(ID, dataset.get(ID))).build(); + var policy = createObjectBuilder(getDatasetFirstPolicy(dataset)) + .add(ODRL_TARGET_ATTRIBUTE, createObjectBuilder().add(ID, dataset.get(ID))) + .add(ODRL_ASSIGNER_ATTRIBUTE, createObjectBuilder().add(ID, other.getBpn())) + .build(); var contractId = getDatasetContractId(dataset); var requestBody = createEdrNegotiationRequest(other.getProtocolEndpoint().getUrl().toString(), other.getBpn(), contractId.toString(), contractId.assetIdPart(), policy, callbacks); diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/tx/TxParticipant.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/tx/TxParticipant.java index db3c4dc5d..1d1ac34cf 100644 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/tx/TxParticipant.java +++ b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/tx/TxParticipant.java @@ -23,6 +23,7 @@ import io.restassured.specification.RequestSpecification; import jakarta.json.Json; import jakarta.json.JsonObject; +import org.eclipse.edc.spi.EdcException; import org.eclipse.edc.test.system.utils.Participant; import java.net.URI; @@ -33,6 +34,7 @@ import static io.restassured.http.ContentType.JSON; import static jakarta.json.Json.createObjectBuilder; import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.ID; +import static org.eclipse.edc.jsonld.spi.PropertyAndTypeNames.ODRL_ASSIGNER_ATTRIBUTE; import static org.eclipse.edc.jsonld.spi.PropertyAndTypeNames.ODRL_POLICY_ATTRIBUTE; import static org.eclipse.edc.jsonld.spi.PropertyAndTypeNames.ODRL_TARGET_ATTRIBUTE; import static org.eclipse.edc.junit.testfixtures.TestUtils.getFreePort; @@ -134,14 +136,25 @@ public String getContractNegotiationError(String negotiationId) { return getContractNegotiationField(negotiationId, "errorDetail"); } - // TODO: temporary override due https://github.com/eclipse-edc/Connector/pull/3868 + // TODO: temporary with workaround override due https://github.com/eclipse-edc/Connector/pull/3926 // remove once fixed in EDC upstream @Override public String initContractNegotiation(Participant provider, String assetId) { - var dataset = getDatasetForAsset(provider, assetId); - var policy = dataset.getJsonArray(ODRL_POLICY_ATTRIBUTE).get(0).asJsonObject(); - var policyWithTarget = createObjectBuilder(policy).add(ODRL_TARGET_ATTRIBUTE, createObjectBuilder().add(ID, dataset.get(ID))).build(); - return super.initContractNegotiation(provider, policyWithTarget); + + if (provider instanceof TxParticipant txProvider) { + var dataset = getDatasetForAsset(provider, assetId); + var policy = dataset.getJsonArray(ODRL_POLICY_ATTRIBUTE).get(0).asJsonObject(); + + var offer = createObjectBuilder(policy) + .add(ODRL_ASSIGNER_ATTRIBUTE, createObjectBuilder().add(ID, txProvider.getBpn())) + .add(ODRL_TARGET_ATTRIBUTE, createObjectBuilder().add(ID, dataset.get(ID))) + .build(); + + return super.initContractNegotiation(provider, offer); + } else { + throw new EdcException("Not a TX participant"); + } + } /** From e211f268060e0e6d8ddbf6ccb1ce48ec7dd88a73 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Mar 2024 14:52:37 +0100 Subject: [PATCH 034/100] chore(deps): bump aquasecurity/trivy-action from 0.17.0 to 0.18.0 (#1091) Bumps [aquasecurity/trivy-action](https://github.com/aquasecurity/trivy-action) from 0.17.0 to 0.18.0. - [Release notes](https://github.com/aquasecurity/trivy-action/releases) - [Commits](https://github.com/aquasecurity/trivy-action/compare/0.17.0...0.18.0) --- updated-dependencies: - dependency-name: aquasecurity/trivy-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/trivy.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/trivy.yml b/.github/workflows/trivy.yml index 2005fb6aa..414b0c681 100644 --- a/.github/workflows/trivy.yml +++ b/.github/workflows/trivy.yml @@ -58,7 +58,7 @@ jobs: steps: - uses: actions/checkout@v4 - name: Run Trivy vulnerability scanner in repo mode - uses: aquasecurity/trivy-action@0.17.0 + uses: aquasecurity/trivy-action@0.18.0 with: scan-type: "config" # ignore-unfixed: true @@ -102,7 +102,7 @@ jobs: ## the next two steps will only execute if the image exists check was successful - name: Run Trivy vulnerability scanner if: success() && steps.imageCheck.outcome != 'failure' - uses: aquasecurity/trivy-action@0.17.0 + uses: aquasecurity/trivy-action@0.18.0 with: image-ref: "tractusx/${{ matrix.image }}:sha-${{ needs.git-sha7.outputs.value }}" format: "sarif" From bafc62580817294bbccafb531237107626c8c8db Mon Sep 17 00:00:00 2001 From: Dominic Reuter <78848280+domreuter@users.noreply.github.com> Date: Tue, 5 Mar 2024 12:37:12 +0100 Subject: [PATCH 035/100] docs: fix broken link (#1084) * docs: fix broken link * chore: update dependencies * Terminal chore: update dependencies * chore: update deps --------- Co-authored-by: Dominic Reuter --- docs/usage/management-api-walkthrough/07_edrs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/usage/management-api-walkthrough/07_edrs.md b/docs/usage/management-api-walkthrough/07_edrs.md index b3e720603..9eb53c81a 100644 --- a/docs/usage/management-api-walkthrough/07_edrs.md +++ b/docs/usage/management-api-walkthrough/07_edrs.md @@ -178,7 +178,7 @@ Content-Type: application/json ## Consumer Data Plane Proxy The Consumer Data Plane Proxy is an extension available in `tractusx-edc` that will use the EDR store to simplify -the data request on Consumer side. The documentation is available [here](../../edc-extensions/dataplane-proxy/edc-dataplane-proxy-consumer-api/README.md). +the data request on Consumer side. The documentation is available [here](../../../edc-extensions/dataplane-proxy/edc-dataplane-proxy-consumer-api/README.md). The API fetches the data according to the input body. The body should contain the `assetId` plus `providerId` or the `transferProcessId` which identifies the EDR to use for fetching data and an `endpointUrl` which is the [provider gateway](../../edc-extensions/dataplane-proxy/edc-dataplane-proxy-provider-api/README.md) From 622b61ef779f2f4b3a1d87f2aea919a6faf1c43e Mon Sep 17 00:00:00 2001 From: Dominic Reuter <78848280+domreuter@users.noreply.github.com> Date: Tue, 5 Mar 2024 12:45:56 +0100 Subject: [PATCH 036/100] fix: bpn migration if table exists (#1083) * fix: bpn migration if table exist * refactor: move back to bpn folder * chore: update dependency file --------- Co-authored-by: Dominic Reuter --- .../migration/bpn/V0_0_1__Init_BusinessGroup_Schema.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/bpn/V0_0_1__Init_BusinessGroup_Schema.sql b/edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/bpn/V0_0_1__Init_BusinessGroup_Schema.sql index aa7b7a08f..44daef527 100644 --- a/edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/bpn/V0_0_1__Init_BusinessGroup_Schema.sql +++ b/edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/bpn/V0_0_1__Init_BusinessGroup_Schema.sql @@ -12,7 +12,7 @@ -- -CREATE TABLE edc_business_partner_group +CREATE TABLE IF NOT EXISTS edc_business_partner_group ( bpn VARCHAR NOT NULL CONSTRAINT edc_business_partner_group_pk From 3752e2a099155f2268daaf86f30329fc60f1d71e Mon Sep 17 00:00:00 2001 From: Jim Marino Date: Tue, 5 Mar 2024 16:58:56 +0100 Subject: [PATCH 037/100] Add DR --- .../2024-03-05_token_refresh/README.md | 66 +++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 docs/development/decision-records/2024-03-05_token_refresh/README.md diff --git a/docs/development/decision-records/2024-03-05_token_refresh/README.md b/docs/development/decision-records/2024-03-05_token_refresh/README.md new file mode 100644 index 000000000..886c68941 --- /dev/null +++ b/docs/development/decision-records/2024-03-05_token_refresh/README.md @@ -0,0 +1,66 @@ +# Tractus-X Token Refresh + +## Decision + +Implement token refresh for the Tractus-X EDC Data Plane according to the [Tractus-X Refresh Token Grant Profile.]() +This enables provider data planes to implement refresh tokens in an interoperable way for client applications using the +Tractus-X EDC Connector. + +Note refresh token support will be done almost exclusively in Tractus-X EDC, except for a few minor updates to upstream +EDC. + +## Rationale + +Data providers may use short-lived tokens for HTTP client pull data transfers to enhance security. Refresh tokens allow +data access to be maintained using short-lived tokens without starting a new transfer process. + +## Approach + +The upstream EDC `DefaultDataPlaneAccessTokenServiceImpl` will be replaced to create a refresh token pinned to the +client's DID. This TX implementation will use the following upstream EDC enhancements: + +- An upstream EDC decorator that adds the client DID as an extension property to the signaling request. +- Upgrade the `AccessTokenData` type to allow for extensible properties to enable the `AccessTokenDataStore` to persist + the renewal token. + +Tractus-X EDC will implement token refresh based on +the [Trasctus-X Refresh Token Grant Profile](https://github.com/eclipse-tractusx/tractusx-profiles/blob/main/tx/refresh/refresh.token.grant.profile.md) + +### Provider Data Plane + +#### TX DataPlaneAccessTokenService + +An implementation of the `DataPlaneAccessTokenService` will be provided that overrides the +default `DefaultDataPlaneAccessTokenServiceImpl` implementation. The TX implementation will do the following: + +- Create an expiring access token and set the `expiresIn` attribute of the `DataAddress.` +- Create a refresh token that is returned in the `refreshToken` property of the `DataAddress`. +- Provide a configuration option to set the `refreshEndpoint` property of the `DataAddress.` If not set, + the `refreshEndpoint` property will not be included. + +It will be possible for distributions not to include the TX implementation of the `DataPlaneAccessTokenService` and +substitute another or revert to the EDC default implementation. + +The refresh token will be sender-constrained to the client DID passed as part of the `DataFlowStartMessage`. + +#### OAuth 2 Refresh API + +The provider data plane will be extended to add a public API that implements the OAuth2 `refresh_token` grant. The +refresh token will be verified according to the steps laid out in the _Tractus-X Refresh Token Grant Profile._ When a +refresh request is successfully made, a new access token and refresh token will be generated and returned to the client. +If a refresh token request fails due to a validation error, the associated access token and refresh token will be +invalidated. + +### Client-side Token Refresh + +A client will be able to initiate a token refresh request in three ways: + +- Request data through a client data plane instance, which will check the token expiration and issue a refresh request + if required. This behavior will be transparent to the client. +- Request data directly and check if the access token is expired. If the token is expired, the client can call a client + data plane management API to renew the access token. +- Request data directly and handle access token renewal using OAuth 2 directly. + +To support refresh token renewal, an DIM specific extension will be added that requests the authentication JWT to be +signed using a key managed by DIM. This extension can use the same DIM API as the IATP extension. + From 902e64e08c88fa3264f1a062f9a7340502b4bc30 Mon Sep 17 00:00:00 2001 From: Jim Marino Date: Tue, 5 Mar 2024 17:21:43 +0100 Subject: [PATCH 038/100] Update docs/development/decision-records/2024-03-05_token_refresh/README.md Co-authored-by: Paul Latzelsperger <43503240+paullatzelsperger@users.noreply.github.com> --- .../decision-records/2024-03-05_token_refresh/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/development/decision-records/2024-03-05_token_refresh/README.md b/docs/development/decision-records/2024-03-05_token_refresh/README.md index 886c68941..4a3209d79 100644 --- a/docs/development/decision-records/2024-03-05_token_refresh/README.md +++ b/docs/development/decision-records/2024-03-05_token_refresh/README.md @@ -2,7 +2,7 @@ ## Decision -Implement token refresh for the Tractus-X EDC Data Plane according to the [Tractus-X Refresh Token Grant Profile.]() +Implement token refresh for the Tractus-X EDC Data Plane according to the [Tractus-X Refresh Token Grant Profile](https://github.com/eclipse-tractusx/tractusx-profiles/blob/main/tx/refresh/refresh.token.grant.profile.md). This enables provider data planes to implement refresh tokens in an interoperable way for client applications using the Tractus-X EDC Connector. From aa31d57d3fac362bef40c958b4c4f80cf0fad542 Mon Sep 17 00:00:00 2001 From: Jim Marino Date: Tue, 5 Mar 2024 17:21:53 +0100 Subject: [PATCH 039/100] Update docs/development/decision-records/2024-03-05_token_refresh/README.md Co-authored-by: Paul Latzelsperger <43503240+paullatzelsperger@users.noreply.github.com> --- .../decision-records/2024-03-05_token_refresh/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/development/decision-records/2024-03-05_token_refresh/README.md b/docs/development/decision-records/2024-03-05_token_refresh/README.md index 4a3209d79..d3f13985f 100644 --- a/docs/development/decision-records/2024-03-05_token_refresh/README.md +++ b/docs/development/decision-records/2024-03-05_token_refresh/README.md @@ -61,6 +61,6 @@ A client will be able to initiate a token refresh request in three ways: data plane management API to renew the access token. - Request data directly and handle access token renewal using OAuth 2 directly. -To support refresh token renewal, an DIM specific extension will be added that requests the authentication JWT to be +To support refresh token renewal, a DIM specific extension will be added that requests the authentication JWT to be signed using a key managed by DIM. This extension can use the same DIM API as the IATP extension. From edb07fc73b3d6d209e914848c637898a83833ef6 Mon Sep 17 00:00:00 2001 From: Paul Latzelsperger <43503240+paullatzelsperger@users.noreply.github.com> Date: Wed, 6 Mar 2024 07:36:11 +0100 Subject: [PATCH 040/100] docs: add support documentation for DataPlane Signaling (#1104) * docs: add support documentation for DataPlane Signaling * Update docs/development/dataplane-signaling/tx-signaling.extensions.md Co-authored-by: Jim Marino --------- Co-authored-by: Jim Marino --- .../AutomaticRefresh.drawio | 56 ++++++++ .../AutomaticRefresh.drawio.png | Bin 0 -> 41226 bytes .../dataplane-signaling/ManualRefresh.drawio | 53 ++++++++ .../ManualRefresh.drawio.png | Bin 0 -> 40718 bytes .../dataplane-signaling/TxSignaling.drawio | 125 ++++++++++++++++++ .../TxSignaling.drawio.png | Bin 0 -> 116120 bytes .../tx-signaling.extensions.md | 77 +++++++++++ 7 files changed, 311 insertions(+) create mode 100644 docs/development/dataplane-signaling/AutomaticRefresh.drawio create mode 100644 docs/development/dataplane-signaling/AutomaticRefresh.drawio.png create mode 100644 docs/development/dataplane-signaling/ManualRefresh.drawio create mode 100644 docs/development/dataplane-signaling/ManualRefresh.drawio.png create mode 100644 docs/development/dataplane-signaling/TxSignaling.drawio create mode 100644 docs/development/dataplane-signaling/TxSignaling.drawio.png create mode 100644 docs/development/dataplane-signaling/tx-signaling.extensions.md diff --git a/docs/development/dataplane-signaling/AutomaticRefresh.drawio b/docs/development/dataplane-signaling/AutomaticRefresh.drawio new file mode 100644 index 000000000..2c71d36ee --- /dev/null +++ b/docs/development/dataplane-signaling/AutomaticRefresh.drawio @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/development/dataplane-signaling/AutomaticRefresh.drawio.png b/docs/development/dataplane-signaling/AutomaticRefresh.drawio.png new file mode 100644 index 0000000000000000000000000000000000000000..4cb9e69cdd5c556c82e3ccd9df748d28c967e42e GIT binary patch literal 41226 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≀?k7O_9xL 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 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/development/dataplane-signaling/ManualRefresh.drawio.png b/docs/development/dataplane-signaling/ManualRefresh.drawio.png new file mode 100644 index 0000000000000000000000000000000000000000..ed0c3ee2b5031e618b6f59e243458de6c21c3fb1 GIT binary patch literal 40718 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 uz*L@L$>|JhM3WV*mOKap0|fCAoHGb>jp| + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/development/dataplane-signaling/TxSignaling.drawio.png b/docs/development/dataplane-signaling/TxSignaling.drawio.png new file mode 100644 index 0000000000000000000000000000000000000000..338559c312f9177c6bee96fafc7934fe53e73bdd GIT binary patch literal 116120 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 Date: Wed, 6 Mar 2024 18:34:44 +0100 Subject: [PATCH 041/100] chore: fixes after upstream changes (#1102) * chore: fixes after upstream changes * chore: fix tests * chore: fix upgradeability test with 0.6.0 * pr remarks * chore: dependencies file --- .github/workflows/upgradeability-test.yaml | 3 ++- DEPENDENCIES | 8 ++++++++ .../org/eclipse/tractusx/edc/api/edr/EdrApiTest.java | 10 +++++++++- .../edc/lifecycle/tx/iatp/DataspaceIssuer.java | 1 + 4 files changed, 20 insertions(+), 2 deletions(-) diff --git a/.github/workflows/upgradeability-test.yaml b/.github/workflows/upgradeability-test.yaml index 003ae0f74..df486e3fd 100644 --- a/.github/workflows/upgradeability-test.yaml +++ b/.github/workflows/upgradeability-test.yaml @@ -63,10 +63,11 @@ jobs: helm repo add tractusx https://eclipse-tractusx.github.io/charts/dev helm repo update tractusx + ## Skip 0.6.0 when doing the compatibility check ref https://github.com/eclipse-tractusx/tractusx-edc/issues/1082 - name: "Get latest released version" id: get-version run: | - RELEASED_VERSION=$(helm search repo tractusx/tractusx-connector -o json | jq -r '.[0].version') + RELEASED_VERSION=$(helm search repo tractusx/tractusx-connector -l -o json | jq -r 'map(select(.version !="0.6.0")) | first | .version') echo "Last official release is $RELEASED_VERSION" echo "RELEASE=$RELEASED_VERSION" >> $GITHUB_ENV exit 0 diff --git a/DEPENDENCIES b/DEPENDENCIES index dd69edb1b..b66f18352 100644 --- a/DEPENDENCIES +++ b/DEPENDENCIES @@ -52,8 +52,11 @@ maven/mavencentral/com.fasterxml.jackson/jackson-bom/2.15.1, Apache-2.0, approve maven/mavencentral/com.fasterxml.jackson/jackson-bom/2.16.1, Apache-2.0, approved, #11852 maven/mavencentral/com.fasterxml.woodstox/woodstox-core/6.5.1, Apache-2.0, approved, #7950 maven/mavencentral/com.github.docker-java/docker-java-api/3.3.5, Apache-2.0, approved, #10346 +maven/mavencentral/com.github.docker-java/docker-java-api/3.3.6, Apache-2.0, approved, #10346 maven/mavencentral/com.github.docker-java/docker-java-transport-zerodep/3.3.5, Apache-2.0 AND (Apache-2.0 AND BSD-3-Clause), approved, #7946 +maven/mavencentral/com.github.docker-java/docker-java-transport-zerodep/3.3.6, Apache-2.0 AND (Apache-2.0 AND BSD-3-Clause), approved, #7946 maven/mavencentral/com.github.docker-java/docker-java-transport/3.3.5, Apache-2.0, approved, #7942 +maven/mavencentral/com.github.docker-java/docker-java-transport/3.3.6, Apache-2.0, approved, #7942 maven/mavencentral/com.github.stephenc.jcip/jcip-annotations/1.0-1, Apache-2.0, approved, CQ21949 maven/mavencentral/com.google.code.findbugs/jsr305/3.0.2, Apache-2.0, approved, #20 maven/mavencentral/com.google.code.gson/gson/2.10.1, Apache-2.0, approved, #6159 @@ -478,10 +481,15 @@ maven/mavencentral/org.slf4j/slf4j-api/1.7.7, MIT, approved, CQ9827 maven/mavencentral/org.slf4j/slf4j-api/2.0.12, MIT, approved, #5915 maven/mavencentral/org.slf4j/slf4j-api/2.0.9, MIT, approved, #5915 maven/mavencentral/org.testcontainers/database-commons/1.19.6, Apache-2.0, approved, #10345 +maven/mavencentral/org.testcontainers/database-commons/1.19.7, Apache-2.0, approved, #10345 maven/mavencentral/org.testcontainers/jdbc/1.19.6, Apache-2.0, approved, #10348 +maven/mavencentral/org.testcontainers/jdbc/1.19.7, Apache-2.0, approved, #10348 maven/mavencentral/org.testcontainers/junit-jupiter/1.19.6, MIT, approved, #10344 +maven/mavencentral/org.testcontainers/junit-jupiter/1.19.7, MIT, approved, #10344 maven/mavencentral/org.testcontainers/postgresql/1.19.6, MIT, approved, #10350 +maven/mavencentral/org.testcontainers/postgresql/1.19.7, MIT, approved, #10350 maven/mavencentral/org.testcontainers/testcontainers/1.19.6, Apache-2.0 AND MIT, approved, #10347 +maven/mavencentral/org.testcontainers/testcontainers/1.19.7, Apache-2.0 AND MIT, approved, #10347 maven/mavencentral/org.testcontainers/vault/1.19.6, MIT, approved, #10852 maven/mavencentral/org.xmlresolver/xmlresolver/5.2.2, Apache-2.0, approved, clearlydefined maven/mavencentral/org.yaml/snakeyaml/2.0, Apache-2.0 AND (Apache-2.0 OR BSD-3-Clause OR EPL-1.0 OR GPL-2.0-or-later OR LGPL-2.1-or-later), approved, #7275 diff --git a/edc-extensions/edr/edr-api/src/test/java/org/eclipse/tractusx/edc/api/edr/EdrApiTest.java b/edc-extensions/edr/edr-api/src/test/java/org/eclipse/tractusx/edc/api/edr/EdrApiTest.java index 27a0a03dd..cf29fd7d8 100644 --- a/edc-extensions/edr/edr-api/src/test/java/org/eclipse/tractusx/edc/api/edr/EdrApiTest.java +++ b/edc-extensions/edr/edr-api/src/test/java/org/eclipse/tractusx/edc/api/edr/EdrApiTest.java @@ -31,6 +31,7 @@ import org.eclipse.edc.jsonld.spi.JsonLd; import org.eclipse.edc.jsonld.util.JacksonJsonLd; import org.eclipse.edc.junit.assertions.AbstractResultAssert; +import org.eclipse.edc.spi.agent.ParticipantIdMapper; import org.eclipse.edc.transform.spi.TypeTransformerRegistry; import org.eclipse.tractusx.edc.api.edr.dto.NegotiateEdrRequestDto; import org.eclipse.tractusx.edc.api.edr.transform.JsonObjectToNegotiateEdrRequestDtoTransformer; @@ -49,6 +50,9 @@ import static org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntry.EDR_ENTRY_PROVIDER_ID; import static org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntry.EDR_ENTRY_STATE; import static org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntry.EDR_ENTRY_TRANSFER_PROCESS_ID; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; public class EdrApiTest { @@ -64,7 +68,11 @@ void setUp() { transformer.register(new JsonObjectToContractOfferDescriptionTransformer()); transformer.register(new JsonObjectToCallbackAddressTransformer()); transformer.register(new JsonObjectToNegotiateEdrRequestDtoTransformer()); - OdrlTransformersFactory.jsonObjectToOdrlTransformers().forEach(transformer::register); + var mapper = mock(ParticipantIdMapper.class); + + when(mapper.fromIri(any())).thenAnswer(a -> a.getArgument(0)); + when(mapper.toIri(any())).thenAnswer(a -> a.getArgument(0)); + OdrlTransformersFactory.jsonObjectToOdrlTransformers(mapper).forEach(transformer::register); } @Test diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/tx/iatp/DataspaceIssuer.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/tx/iatp/DataspaceIssuer.java index 8bb537034..829291808 100644 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/tx/iatp/DataspaceIssuer.java +++ b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/tx/iatp/DataspaceIssuer.java @@ -95,6 +95,7 @@ public VerifiableCredentialResource issueCredential(IatpParticipant participant, var rawVc = createLdpVc(jsonLd, type, subjectSupplier); return VerifiableCredentialResource.Builder.newInstance() .issuerId(didUrl()) + .participantId(participant.didUrl()) .holderId(participant.getBpn()) .credential(new VerifiableCredentialContainer(rawVc, CredentialFormat.JSON_LD, credential)) .build(); From e913a447e3e0c635cd23b413418518284dd39d45 Mon Sep 17 00:00:00 2001 From: Paul Latzelsperger <43503240+paullatzelsperger@users.noreply.github.com> Date: Fri, 8 Mar 2024 15:20:59 +0100 Subject: [PATCH 042/100] feat: implement Tractus-X-specific `DataPlaneAccessTokenService` (#1115) * feat: implement Tractus-X-specific `DataPlaneAccessTokenService` * avoid SonarQube complaints * lic headers * trigger ci * DEPENDENCIES * fix compile errors --- DEPENDENCIES | 6 +- .../edc-controlplane-base/build.gradle.kts | 2 +- .../edc-dataplane-base/build.gradle.kts | 10 +- .../bpn/BusinessPartnerGroupApiExtension.java | 3 - ...BusinessPartnerGroupApiControllerTest.java | 2 - edc-extensions/build.gradle.kts | 2 +- .../README.md | 0 .../build.gradle.kts | 0 .../DataPlaneProxyConsumerApiExtension.java | 0 .../api/asset/ClientErrorExceptionMapper.java | 0 .../api/asset/ConsumerAssetRequestApi.java | 0 .../asset/ConsumerAssetRequestController.java | 0 .../asset/PreconditionFailedException.java | 0 .../api/asset/model/AssetRequest.java | 0 ...rg.eclipse.edc.spi.system.ServiceExtension | 0 .../api/asset/model/AssetRequestTest.java | 0 .../ConsumerAssetRequestControllerTest.java | 0 .../README.md | 0 .../build.gradle.kts | 2 +- .../DataPlaneProxyProviderApiExtension.java | 0 .../api/gateway/ProviderGatewayApi.java | 0 .../gateway/ProviderGatewayController.java | 0 .../provider/api/response/ResponseHelper.java | 0 .../ProxyProviderDataAddressResolver.java | 0 ...rg.eclipse.edc.spi.system.ServiceExtension | 0 ...ataPlaneProxyProviderApiExtensionTest.java | 0 .../ProxyProviderDataAddressResolverTest.java | 0 .../api/response/ResponseHelperTest.java | 0 .../README.md | 0 .../build.gradle.kts | 2 +- .../core/ProxyProviderCoreExtension.java | 0 .../AuthorizationHandlerRegistryImpl.java | 0 .../GatewayConfigurationLoader.java | 0 .../GatewayConfigurationRegistryImpl.java | 0 ...rg.eclipse.edc.spi.system.ServiceExtension | 0 .../AuthorizationHandlerRegistryImplTest.java | 0 .../GatewayConfigurationLoaderTest.java | 0 .../GatewayConfigurationRegistryImplTest.java | 0 .../build.gradle.kts | 0 .../authorization/AuthorizationExtension.java | 0 .../authorization/AuthorizationHandler.java | 0 .../AuthorizationHandlerRegistry.java | 0 .../configuration/GatewayConfiguration.java | 0 .../GatewayConfigurationRegistry.java | 0 .../README.md | 0 .../build.gradle.kts | 0 ...SelectorConfigurationServiceExtension.java | 0 ...rg.eclipse.edc.spi.system.ServiceExtension | 0 ...ationServiceExtensionEdcExtensionTest.java | 0 ...ctorConfigurationServiceExtensionTest.java | 0 .../token-refresh-core/build.gradle.kts | 36 +++ ...DataPlaneTokenRefreshServiceExtension.java | 75 +++++ .../DataPlaneTokenRefreshServiceImpl.java | 235 ++++++++++++++ .../core/rules/ClaimIsPresentRule.java | 43 +++ .../core/rules/IssuerEqualsSubjectRule.java | 44 +++ .../core/rules/RefreshTokenMustExistRule.java | 76 +++++ ...rg.eclipse.edc.spi.system.ServiceExtension | 20 ++ ...eTokenRefreshServiceImplComponentTest.java | 246 +++++++++++++++ .../DataPlaneTokenRefreshServiceImplTest.java | 292 ++++++++++++++++++ .../core/rules/ClaimIsPresentRuleTest.java | 42 +++ .../rules/RefreshTokenMustExistRuleTest.java | 121 ++++++++ .../tractusx/edc/api/edr/EdrApiExtension.java | 15 +- .../tractusx/edc/api/edr/EdrController.java | 6 +- .../edc/api/edr/EdrApiExtensionTest.java | 8 +- .../edc/api/edr/EdrControllerTest.java | 4 +- ...nalHeadersResourceDefinitionGenerator.java | 19 +- ...eadersResourceDefinitionGeneratorTest.java | 30 +- ...tpProviderResourceDefinitionGenerator.java | 6 +- ...oviderResourceDefinitionGeneratorTest.java | 8 +- .../edc-dataplane-proxy-e2e/build.gradle.kts | 6 +- .../build.gradle.kts | 35 +++ .../DataPlaneTokenRefreshEndToEndTest.java | 45 +++ .../tokenrefresh/e2e/RuntimeConfig.java | 51 +++ gradle/libs.versions.toml | 6 + resources/java.header | 4 +- settings.gradle.kts | 19 +- spi/tokenrefresh-spi/build.gradle.kts | 28 ++ .../spi/DataPlaneTokenRefreshService.java | 37 +++ .../tokenrefresh/spi/model/TokenResponse.java | 28 ++ 79 files changed, 1547 insertions(+), 67 deletions(-) rename edc-extensions/{ => dataplane}/dataplane-proxy/edc-dataplane-proxy-consumer-api/README.md (100%) rename edc-extensions/{ => dataplane}/dataplane-proxy/edc-dataplane-proxy-consumer-api/build.gradle.kts (100%) rename edc-extensions/{ => dataplane}/dataplane-proxy/edc-dataplane-proxy-consumer-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/consumer/api/DataPlaneProxyConsumerApiExtension.java (100%) rename edc-extensions/{ => dataplane}/dataplane-proxy/edc-dataplane-proxy-consumer-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/consumer/api/asset/ClientErrorExceptionMapper.java (100%) rename edc-extensions/{ => dataplane}/dataplane-proxy/edc-dataplane-proxy-consumer-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/consumer/api/asset/ConsumerAssetRequestApi.java (100%) rename edc-extensions/{ => dataplane}/dataplane-proxy/edc-dataplane-proxy-consumer-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/consumer/api/asset/ConsumerAssetRequestController.java (100%) rename edc-extensions/{ => dataplane}/dataplane-proxy/edc-dataplane-proxy-consumer-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/consumer/api/asset/PreconditionFailedException.java (100%) rename edc-extensions/{ => dataplane}/dataplane-proxy/edc-dataplane-proxy-consumer-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/consumer/api/asset/model/AssetRequest.java (100%) rename edc-extensions/{ => dataplane}/dataplane-proxy/edc-dataplane-proxy-consumer-api/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension (100%) rename edc-extensions/{ => dataplane}/dataplane-proxy/edc-dataplane-proxy-consumer-api/src/test/java/org/eclipse/tractusx/edc/dataplane/proxy/consumer/api/asset/model/AssetRequestTest.java (100%) rename edc-extensions/{ => dataplane}/dataplane-proxy/edc-dataplane-proxy-consumer-api/src/test/java/org/eclipse/tractusx/edc/dataplane/proxy/consumer/api/asset/model/ConsumerAssetRequestControllerTest.java (100%) rename edc-extensions/{ => dataplane}/dataplane-proxy/edc-dataplane-proxy-provider-api/README.md (100%) rename edc-extensions/{ => dataplane}/dataplane-proxy/edc-dataplane-proxy-provider-api/build.gradle.kts (93%) rename edc-extensions/{ => dataplane}/dataplane-proxy/edc-dataplane-proxy-provider-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/api/DataPlaneProxyProviderApiExtension.java (100%) rename edc-extensions/{ => dataplane}/dataplane-proxy/edc-dataplane-proxy-provider-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/api/gateway/ProviderGatewayApi.java (100%) rename edc-extensions/{ => dataplane}/dataplane-proxy/edc-dataplane-proxy-provider-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/api/gateway/ProviderGatewayController.java (100%) rename edc-extensions/{ => dataplane}/dataplane-proxy/edc-dataplane-proxy-provider-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/api/response/ResponseHelper.java (100%) rename edc-extensions/{ => dataplane}/dataplane-proxy/edc-dataplane-proxy-provider-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/api/validation/ProxyProviderDataAddressResolver.java (100%) rename edc-extensions/{ => dataplane}/dataplane-proxy/edc-dataplane-proxy-provider-api/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension (100%) rename edc-extensions/{ => dataplane}/dataplane-proxy/edc-dataplane-proxy-provider-api/src/test/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/api/response/DataPlaneProxyProviderApiExtensionTest.java (100%) rename edc-extensions/{ => dataplane}/dataplane-proxy/edc-dataplane-proxy-provider-api/src/test/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/api/response/ProxyProviderDataAddressResolverTest.java (100%) rename edc-extensions/{ => dataplane}/dataplane-proxy/edc-dataplane-proxy-provider-api/src/test/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/api/response/ResponseHelperTest.java (100%) rename edc-extensions/{ => dataplane}/dataplane-proxy/edc-dataplane-proxy-provider-core/README.md (100%) rename edc-extensions/{ => dataplane}/dataplane-proxy/edc-dataplane-proxy-provider-core/build.gradle.kts (92%) rename edc-extensions/{ => dataplane}/dataplane-proxy/edc-dataplane-proxy-provider-core/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/core/ProxyProviderCoreExtension.java (100%) rename edc-extensions/{ => dataplane}/dataplane-proxy/edc-dataplane-proxy-provider-core/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/core/gateway/auth/AuthorizationHandlerRegistryImpl.java (100%) rename edc-extensions/{ => dataplane}/dataplane-proxy/edc-dataplane-proxy-provider-core/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/core/gateway/configuration/GatewayConfigurationLoader.java (100%) rename edc-extensions/{ => dataplane}/dataplane-proxy/edc-dataplane-proxy-provider-core/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/core/gateway/configuration/GatewayConfigurationRegistryImpl.java (100%) rename edc-extensions/{ => dataplane}/dataplane-proxy/edc-dataplane-proxy-provider-core/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension (100%) rename edc-extensions/{ => dataplane}/dataplane-proxy/edc-dataplane-proxy-provider-core/src/test/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/core/gateway/auth/AuthorizationHandlerRegistryImplTest.java (100%) rename edc-extensions/{ => dataplane}/dataplane-proxy/edc-dataplane-proxy-provider-core/src/test/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/core/gateway/configuration/GatewayConfigurationLoaderTest.java (100%) rename edc-extensions/{ => dataplane}/dataplane-proxy/edc-dataplane-proxy-provider-core/src/test/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/core/gateway/configuration/GatewayConfigurationRegistryImplTest.java (100%) rename edc-extensions/{ => dataplane}/dataplane-proxy/edc-dataplane-proxy-provider-spi/build.gradle.kts (100%) rename edc-extensions/{ => dataplane}/dataplane-proxy/edc-dataplane-proxy-provider-spi/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/spi/provider/gateway/authorization/AuthorizationExtension.java (100%) rename edc-extensions/{ => dataplane}/dataplane-proxy/edc-dataplane-proxy-provider-spi/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/spi/provider/gateway/authorization/AuthorizationHandler.java (100%) rename edc-extensions/{ => dataplane}/dataplane-proxy/edc-dataplane-proxy-provider-spi/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/spi/provider/gateway/authorization/AuthorizationHandlerRegistry.java (100%) rename edc-extensions/{ => dataplane}/dataplane-proxy/edc-dataplane-proxy-provider-spi/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/spi/provider/gateway/configuration/GatewayConfiguration.java (100%) rename edc-extensions/{ => dataplane}/dataplane-proxy/edc-dataplane-proxy-provider-spi/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/spi/provider/gateway/configuration/GatewayConfigurationRegistry.java (100%) rename edc-extensions/{ => dataplane}/dataplane-selector-configuration/README.md (100%) rename edc-extensions/{ => dataplane}/dataplane-selector-configuration/build.gradle.kts (100%) rename edc-extensions/{ => dataplane}/dataplane-selector-configuration/src/main/java/org/eclipse/tractusx/edc/dataplane/selector/configuration/DataPlaneSelectorConfigurationServiceExtension.java (100%) rename edc-extensions/{ => dataplane}/dataplane-selector-configuration/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension (100%) rename edc-extensions/{ => dataplane}/dataplane-selector-configuration/src/test/java/org/eclipse/tractusx/edc/dataplane/selector/configuration/DataPlaneSelectorConfigurationServiceExtensionEdcExtensionTest.java (100%) rename edc-extensions/{ => dataplane}/dataplane-selector-configuration/src/test/java/org/eclipse/tractusx/edc/dataplane/selector/configuration/DataPlaneSelectorConfigurationServiceExtensionTest.java (100%) create mode 100644 edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/build.gradle.kts create mode 100644 edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceExtension.java create mode 100644 edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImpl.java create mode 100644 edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/rules/ClaimIsPresentRule.java create mode 100644 edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/rules/IssuerEqualsSubjectRule.java create mode 100644 edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/rules/RefreshTokenMustExistRule.java create mode 100644 edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension create mode 100644 edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImplComponentTest.java create mode 100644 edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImplTest.java create mode 100644 edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/rules/ClaimIsPresentRuleTest.java create mode 100644 edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/rules/RefreshTokenMustExistRuleTest.java create mode 100644 edc-tests/edc-dataplane/edc-dataplane-tokenrefresh-tests/build.gradle.kts create mode 100644 edc-tests/edc-dataplane/edc-dataplane-tokenrefresh-tests/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/e2e/DataPlaneTokenRefreshEndToEndTest.java create mode 100644 edc-tests/edc-dataplane/edc-dataplane-tokenrefresh-tests/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/e2e/RuntimeConfig.java create mode 100644 spi/tokenrefresh-spi/build.gradle.kts create mode 100644 spi/tokenrefresh-spi/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/spi/DataPlaneTokenRefreshService.java create mode 100644 spi/tokenrefresh-spi/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/spi/model/TokenResponse.java diff --git a/DEPENDENCIES b/DEPENDENCIES index b66f18352..60308d844 100644 --- a/DEPENDENCIES +++ b/DEPENDENCIES @@ -76,7 +76,7 @@ maven/mavencentral/com.nimbusds/lang-tag/1.7, Apache-2.0, approved, clearlydefin maven/mavencentral/com.nimbusds/nimbus-jose-jwt/9.30.2, Apache-2.0, approved, clearlydefined maven/mavencentral/com.nimbusds/nimbus-jose-jwt/9.37.3, Apache-2.0, approved, #11701 maven/mavencentral/com.nimbusds/oauth2-oidc-sdk/10.7.1, Apache-2.0, approved, clearlydefined -maven/mavencentral/com.puppycrawl.tools/checkstyle/10.14.0, , restricted, clearlydefined +maven/mavencentral/com.puppycrawl.tools/checkstyle/10.14.0, LGPL-2.1-or-later AND (Apache-2.0 AND LGPL-2.1-or-later) AND Apache-2.0, approved, #13562 maven/mavencentral/com.squareup.okhttp3/mockwebserver/5.0.0-alpha.12, Apache-2.0, approved, clearlydefined maven/mavencentral/com.squareup.okhttp3/mockwebserver3/5.0.0-alpha.12, Apache-2.0, approved, clearlydefined maven/mavencentral/com.squareup.okhttp3/okhttp-dnsoverhttps/4.12.0, Apache-2.0, approved, #11159 @@ -280,6 +280,9 @@ maven/mavencentral/org.eclipse.edc/data-plane-http/0.5.2-SNAPSHOT, Apache-2.0, a maven/mavencentral/org.eclipse.edc/data-plane-public-api/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/data-plane-selector-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/data-plane-selector-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-signaling-api-configuration/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-signaling-api/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-signaling-transform/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/data-plane-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/data-plane-util/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/dsp-api-configuration/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc @@ -372,6 +375,7 @@ maven/mavencentral/org.eclipse.edc/transfer-process-store-sql/0.5.2-SNAPSHOT, Ap maven/mavencentral/org.eclipse.edc/transfer-pull-http-dynamic-receiver/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/transfer-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/transform-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/transform-dspace/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/transform-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/util/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/validator-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc diff --git a/edc-controlplane/edc-controlplane-base/build.gradle.kts b/edc-controlplane/edc-controlplane-base/build.gradle.kts index b4584ccc6..64f2ccabf 100644 --- a/edc-controlplane/edc-controlplane-base/build.gradle.kts +++ b/edc-controlplane/edc-controlplane-base/build.gradle.kts @@ -25,7 +25,7 @@ plugins { dependencies { runtimeOnly(project(":core:edr-cache-core")) runtimeOnly(project(":core:edr-core")) - runtimeOnly(project(":edc-extensions:dataplane-selector-configuration")) + runtimeOnly(project(":edc-extensions:dataplane:dataplane-selector-configuration")) runtimeOnly(project(":edc-extensions:data-encryption")) runtimeOnly(project(":edc-extensions:provision-additional-headers")) diff --git a/edc-dataplane/edc-dataplane-base/build.gradle.kts b/edc-dataplane/edc-dataplane-base/build.gradle.kts index f7b498f74..85af80bb9 100644 --- a/edc-dataplane/edc-dataplane-base/build.gradle.kts +++ b/edc-dataplane/edc-dataplane-base/build.gradle.kts @@ -24,10 +24,13 @@ plugins { dependencies { runtimeOnly(project(":core:edr-cache-core")) - runtimeOnly(project(":edc-extensions:dataplane-proxy:edc-dataplane-proxy-consumer-api")) - runtimeOnly(project(":edc-extensions:dataplane-proxy:edc-dataplane-proxy-provider-api")) - runtimeOnly(project(":edc-extensions:dataplane-proxy:edc-dataplane-proxy-provider-core")) + runtimeOnly(project(":edc-extensions:dataplane:dataplane-proxy:edc-dataplane-proxy-consumer-api")) + runtimeOnly(project(":edc-extensions:dataplane:dataplane-proxy:edc-dataplane-proxy-provider-api")) + runtimeOnly(project(":edc-extensions:dataplane:dataplane-proxy:edc-dataplane-proxy-provider-core")) + runtimeOnly(project(":edc-extensions:dataplane:dataplane-token-refresh:token-refresh-core")) + runtimeOnly(libs.edc.jsonld) // needed by the DataPlaneSignalingApi + runtimeOnly(libs.edc.identity.core.did) // for the DID Public Key Resolver runtimeOnly(libs.edc.config.filesystem) runtimeOnly(libs.edc.auth.tokenbased) runtimeOnly(libs.edc.dpf.awss3) @@ -39,6 +42,7 @@ dependencies { runtimeOnly(libs.edc.controlplane.apiclient) runtimeOnly(libs.edc.dpf.api.control) + runtimeOnly(libs.edc.dpf.api.signaling) runtimeOnly(libs.edc.dpf.api.public) runtimeOnly(libs.edc.core.connector) runtimeOnly(libs.edc.boot) diff --git a/edc-extensions/bpn-validation/bpn-validation-api/src/main/java/org/eclipse/tractusx/edc/api/bpn/BusinessPartnerGroupApiExtension.java b/edc-extensions/bpn-validation/bpn-validation-api/src/main/java/org/eclipse/tractusx/edc/api/bpn/BusinessPartnerGroupApiExtension.java index 868719218..f6bef816f 100644 --- a/edc-extensions/bpn-validation/bpn-validation-api/src/main/java/org/eclipse/tractusx/edc/api/bpn/BusinessPartnerGroupApiExtension.java +++ b/edc-extensions/bpn-validation/bpn-validation-api/src/main/java/org/eclipse/tractusx/edc/api/bpn/BusinessPartnerGroupApiExtension.java @@ -20,7 +20,6 @@ package org.eclipse.tractusx.edc.api.bpn; import org.eclipse.edc.connector.api.management.configuration.ManagementApiConfiguration; -import org.eclipse.edc.connector.api.management.configuration.transform.ManagementApiTypeTransformerRegistry; import org.eclipse.edc.jsonld.spi.JsonLd; import org.eclipse.edc.runtime.metamodel.annotation.Extension; import org.eclipse.edc.runtime.metamodel.annotation.Inject; @@ -40,8 +39,6 @@ public class BusinessPartnerGroupApiExtension implements ServiceExtension { @Inject private ManagementApiConfiguration apiConfiguration; @Inject - private ManagementApiTypeTransformerRegistry transformerRegistry; - @Inject private JsonLd jsonLdService; @Inject private BusinessPartnerStore businessPartnerStore; diff --git a/edc-extensions/bpn-validation/bpn-validation-api/src/test/java/org/eclipse/tractusx/edc/api/bpn/BusinessPartnerGroupApiControllerTest.java b/edc-extensions/bpn-validation/bpn-validation-api/src/test/java/org/eclipse/tractusx/edc/api/bpn/BusinessPartnerGroupApiControllerTest.java index 4c067d033..a1b93e882 100644 --- a/edc-extensions/bpn-validation/bpn-validation-api/src/test/java/org/eclipse/tractusx/edc/api/bpn/BusinessPartnerGroupApiControllerTest.java +++ b/edc-extensions/bpn-validation/bpn-validation-api/src/test/java/org/eclipse/tractusx/edc/api/bpn/BusinessPartnerGroupApiControllerTest.java @@ -22,7 +22,6 @@ import io.restassured.specification.RequestSpecification; import jakarta.json.Json; import jakarta.json.JsonObject; -import org.eclipse.edc.connector.api.management.configuration.transform.ManagementApiTypeTransformerRegistry; import org.eclipse.edc.jsonld.TitaniumJsonLd; import org.eclipse.edc.jsonld.spi.JsonLd; import org.eclipse.edc.junit.annotations.ApiTest; @@ -52,7 +51,6 @@ class BusinessPartnerGroupApiControllerTest extends RestControllerTestBase { private final JsonLd jsonLdService = new TitaniumJsonLd(mock()); private final BusinessPartnerStore businessPartnerStore = mock(); - private final ManagementApiTypeTransformerRegistry transformerRegistry = mock(); @BeforeEach void setUp() { diff --git a/edc-extensions/build.gradle.kts b/edc-extensions/build.gradle.kts index d6b1be67f..a62e89ac7 100644 --- a/edc-extensions/build.gradle.kts +++ b/edc-extensions/build.gradle.kts @@ -24,7 +24,7 @@ plugins { dependencies { implementation(project(":edc-extensions:bpn-validation")) implementation(project(":edc-extensions:data-encryption")) - implementation(project(":edc-extensions:dataplane-selector-configuration")) + implementation(project(":edc-extensions:dataplane:dataplane-selector-configuration")) implementation(project(":edc-extensions:postgresql-migration")) implementation(project(":edc-extensions:provision-additional-headers")) implementation(project(":edc-extensions:transferprocess-sftp-client")) diff --git a/edc-extensions/dataplane-proxy/edc-dataplane-proxy-consumer-api/README.md b/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-consumer-api/README.md similarity index 100% rename from edc-extensions/dataplane-proxy/edc-dataplane-proxy-consumer-api/README.md rename to edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-consumer-api/README.md diff --git a/edc-extensions/dataplane-proxy/edc-dataplane-proxy-consumer-api/build.gradle.kts b/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-consumer-api/build.gradle.kts similarity index 100% rename from edc-extensions/dataplane-proxy/edc-dataplane-proxy-consumer-api/build.gradle.kts rename to edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-consumer-api/build.gradle.kts diff --git a/edc-extensions/dataplane-proxy/edc-dataplane-proxy-consumer-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/consumer/api/DataPlaneProxyConsumerApiExtension.java b/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-consumer-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/consumer/api/DataPlaneProxyConsumerApiExtension.java similarity index 100% rename from edc-extensions/dataplane-proxy/edc-dataplane-proxy-consumer-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/consumer/api/DataPlaneProxyConsumerApiExtension.java rename to edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-consumer-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/consumer/api/DataPlaneProxyConsumerApiExtension.java diff --git a/edc-extensions/dataplane-proxy/edc-dataplane-proxy-consumer-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/consumer/api/asset/ClientErrorExceptionMapper.java b/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-consumer-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/consumer/api/asset/ClientErrorExceptionMapper.java similarity index 100% rename from edc-extensions/dataplane-proxy/edc-dataplane-proxy-consumer-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/consumer/api/asset/ClientErrorExceptionMapper.java rename to edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-consumer-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/consumer/api/asset/ClientErrorExceptionMapper.java diff --git a/edc-extensions/dataplane-proxy/edc-dataplane-proxy-consumer-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/consumer/api/asset/ConsumerAssetRequestApi.java b/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-consumer-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/consumer/api/asset/ConsumerAssetRequestApi.java similarity index 100% rename from edc-extensions/dataplane-proxy/edc-dataplane-proxy-consumer-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/consumer/api/asset/ConsumerAssetRequestApi.java rename to edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-consumer-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/consumer/api/asset/ConsumerAssetRequestApi.java diff --git a/edc-extensions/dataplane-proxy/edc-dataplane-proxy-consumer-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/consumer/api/asset/ConsumerAssetRequestController.java b/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-consumer-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/consumer/api/asset/ConsumerAssetRequestController.java similarity index 100% rename from edc-extensions/dataplane-proxy/edc-dataplane-proxy-consumer-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/consumer/api/asset/ConsumerAssetRequestController.java rename to edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-consumer-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/consumer/api/asset/ConsumerAssetRequestController.java diff --git a/edc-extensions/dataplane-proxy/edc-dataplane-proxy-consumer-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/consumer/api/asset/PreconditionFailedException.java b/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-consumer-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/consumer/api/asset/PreconditionFailedException.java similarity index 100% rename from edc-extensions/dataplane-proxy/edc-dataplane-proxy-consumer-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/consumer/api/asset/PreconditionFailedException.java rename to edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-consumer-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/consumer/api/asset/PreconditionFailedException.java diff --git a/edc-extensions/dataplane-proxy/edc-dataplane-proxy-consumer-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/consumer/api/asset/model/AssetRequest.java b/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-consumer-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/consumer/api/asset/model/AssetRequest.java similarity index 100% rename from edc-extensions/dataplane-proxy/edc-dataplane-proxy-consumer-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/consumer/api/asset/model/AssetRequest.java rename to edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-consumer-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/consumer/api/asset/model/AssetRequest.java diff --git a/edc-extensions/dataplane-proxy/edc-dataplane-proxy-consumer-api/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension b/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-consumer-api/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension similarity index 100% rename from edc-extensions/dataplane-proxy/edc-dataplane-proxy-consumer-api/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension rename to edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-consumer-api/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension diff --git a/edc-extensions/dataplane-proxy/edc-dataplane-proxy-consumer-api/src/test/java/org/eclipse/tractusx/edc/dataplane/proxy/consumer/api/asset/model/AssetRequestTest.java b/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-consumer-api/src/test/java/org/eclipse/tractusx/edc/dataplane/proxy/consumer/api/asset/model/AssetRequestTest.java similarity index 100% rename from edc-extensions/dataplane-proxy/edc-dataplane-proxy-consumer-api/src/test/java/org/eclipse/tractusx/edc/dataplane/proxy/consumer/api/asset/model/AssetRequestTest.java rename to edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-consumer-api/src/test/java/org/eclipse/tractusx/edc/dataplane/proxy/consumer/api/asset/model/AssetRequestTest.java diff --git a/edc-extensions/dataplane-proxy/edc-dataplane-proxy-consumer-api/src/test/java/org/eclipse/tractusx/edc/dataplane/proxy/consumer/api/asset/model/ConsumerAssetRequestControllerTest.java b/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-consumer-api/src/test/java/org/eclipse/tractusx/edc/dataplane/proxy/consumer/api/asset/model/ConsumerAssetRequestControllerTest.java similarity index 100% rename from edc-extensions/dataplane-proxy/edc-dataplane-proxy-consumer-api/src/test/java/org/eclipse/tractusx/edc/dataplane/proxy/consumer/api/asset/model/ConsumerAssetRequestControllerTest.java rename to edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-consumer-api/src/test/java/org/eclipse/tractusx/edc/dataplane/proxy/consumer/api/asset/model/ConsumerAssetRequestControllerTest.java diff --git a/edc-extensions/dataplane-proxy/edc-dataplane-proxy-provider-api/README.md b/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-api/README.md similarity index 100% rename from edc-extensions/dataplane-proxy/edc-dataplane-proxy-provider-api/README.md rename to edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-api/README.md diff --git a/edc-extensions/dataplane-proxy/edc-dataplane-proxy-provider-api/build.gradle.kts b/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-api/build.gradle.kts similarity index 93% rename from edc-extensions/dataplane-proxy/edc-dataplane-proxy-provider-api/build.gradle.kts rename to edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-api/build.gradle.kts index 4244a6162..cfaa05daa 100644 --- a/edc-extensions/dataplane-proxy/edc-dataplane-proxy-provider-api/build.gradle.kts +++ b/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-api/build.gradle.kts @@ -35,7 +35,7 @@ dependencies { implementation(libs.jakarta.rsApi) implementation(libs.nimbus.jwt) - implementation(project(":edc-extensions:dataplane-proxy:edc-dataplane-proxy-provider-spi")) + implementation(project(":edc-extensions:dataplane:dataplane-proxy:edc-dataplane-proxy-provider-spi")) testImplementation(libs.edc.junit) testImplementation(libs.okhttp.mockwebserver) diff --git a/edc-extensions/dataplane-proxy/edc-dataplane-proxy-provider-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/api/DataPlaneProxyProviderApiExtension.java b/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/api/DataPlaneProxyProviderApiExtension.java similarity index 100% rename from edc-extensions/dataplane-proxy/edc-dataplane-proxy-provider-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/api/DataPlaneProxyProviderApiExtension.java rename to edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/api/DataPlaneProxyProviderApiExtension.java diff --git a/edc-extensions/dataplane-proxy/edc-dataplane-proxy-provider-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/api/gateway/ProviderGatewayApi.java b/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/api/gateway/ProviderGatewayApi.java similarity index 100% rename from edc-extensions/dataplane-proxy/edc-dataplane-proxy-provider-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/api/gateway/ProviderGatewayApi.java rename to edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/api/gateway/ProviderGatewayApi.java diff --git a/edc-extensions/dataplane-proxy/edc-dataplane-proxy-provider-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/api/gateway/ProviderGatewayController.java b/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/api/gateway/ProviderGatewayController.java similarity index 100% rename from edc-extensions/dataplane-proxy/edc-dataplane-proxy-provider-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/api/gateway/ProviderGatewayController.java rename to edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/api/gateway/ProviderGatewayController.java diff --git a/edc-extensions/dataplane-proxy/edc-dataplane-proxy-provider-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/api/response/ResponseHelper.java b/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/api/response/ResponseHelper.java similarity index 100% rename from edc-extensions/dataplane-proxy/edc-dataplane-proxy-provider-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/api/response/ResponseHelper.java rename to edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/api/response/ResponseHelper.java diff --git a/edc-extensions/dataplane-proxy/edc-dataplane-proxy-provider-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/api/validation/ProxyProviderDataAddressResolver.java b/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/api/validation/ProxyProviderDataAddressResolver.java similarity index 100% rename from edc-extensions/dataplane-proxy/edc-dataplane-proxy-provider-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/api/validation/ProxyProviderDataAddressResolver.java rename to edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/api/validation/ProxyProviderDataAddressResolver.java diff --git a/edc-extensions/dataplane-proxy/edc-dataplane-proxy-provider-api/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension b/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-api/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension similarity index 100% rename from edc-extensions/dataplane-proxy/edc-dataplane-proxy-provider-api/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension rename to edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-api/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension diff --git a/edc-extensions/dataplane-proxy/edc-dataplane-proxy-provider-api/src/test/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/api/response/DataPlaneProxyProviderApiExtensionTest.java b/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-api/src/test/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/api/response/DataPlaneProxyProviderApiExtensionTest.java similarity index 100% rename from edc-extensions/dataplane-proxy/edc-dataplane-proxy-provider-api/src/test/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/api/response/DataPlaneProxyProviderApiExtensionTest.java rename to edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-api/src/test/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/api/response/DataPlaneProxyProviderApiExtensionTest.java diff --git a/edc-extensions/dataplane-proxy/edc-dataplane-proxy-provider-api/src/test/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/api/response/ProxyProviderDataAddressResolverTest.java b/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-api/src/test/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/api/response/ProxyProviderDataAddressResolverTest.java similarity index 100% rename from edc-extensions/dataplane-proxy/edc-dataplane-proxy-provider-api/src/test/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/api/response/ProxyProviderDataAddressResolverTest.java rename to edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-api/src/test/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/api/response/ProxyProviderDataAddressResolverTest.java diff --git a/edc-extensions/dataplane-proxy/edc-dataplane-proxy-provider-api/src/test/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/api/response/ResponseHelperTest.java b/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-api/src/test/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/api/response/ResponseHelperTest.java similarity index 100% rename from edc-extensions/dataplane-proxy/edc-dataplane-proxy-provider-api/src/test/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/api/response/ResponseHelperTest.java rename to edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-api/src/test/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/api/response/ResponseHelperTest.java diff --git a/edc-extensions/dataplane-proxy/edc-dataplane-proxy-provider-core/README.md b/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-core/README.md similarity index 100% rename from edc-extensions/dataplane-proxy/edc-dataplane-proxy-provider-core/README.md rename to edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-core/README.md diff --git a/edc-extensions/dataplane-proxy/edc-dataplane-proxy-provider-core/build.gradle.kts b/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-core/build.gradle.kts similarity index 92% rename from edc-extensions/dataplane-proxy/edc-dataplane-proxy-provider-core/build.gradle.kts rename to edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-core/build.gradle.kts index c9b7004e2..7a0d9b578 100644 --- a/edc-extensions/dataplane-proxy/edc-dataplane-proxy-provider-core/build.gradle.kts +++ b/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-core/build.gradle.kts @@ -34,6 +34,6 @@ dependencies { implementation(libs.jakarta.rsApi) implementation(libs.nimbus.jwt) - implementation(project(":edc-extensions:dataplane-proxy:edc-dataplane-proxy-provider-spi")) + implementation(project(":edc-extensions:dataplane:dataplane-proxy:edc-dataplane-proxy-provider-spi")) } diff --git a/edc-extensions/dataplane-proxy/edc-dataplane-proxy-provider-core/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/core/ProxyProviderCoreExtension.java b/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-core/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/core/ProxyProviderCoreExtension.java similarity index 100% rename from edc-extensions/dataplane-proxy/edc-dataplane-proxy-provider-core/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/core/ProxyProviderCoreExtension.java rename to edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-core/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/core/ProxyProviderCoreExtension.java diff --git a/edc-extensions/dataplane-proxy/edc-dataplane-proxy-provider-core/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/core/gateway/auth/AuthorizationHandlerRegistryImpl.java b/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-core/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/core/gateway/auth/AuthorizationHandlerRegistryImpl.java similarity index 100% rename from edc-extensions/dataplane-proxy/edc-dataplane-proxy-provider-core/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/core/gateway/auth/AuthorizationHandlerRegistryImpl.java rename to edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-core/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/core/gateway/auth/AuthorizationHandlerRegistryImpl.java diff --git a/edc-extensions/dataplane-proxy/edc-dataplane-proxy-provider-core/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/core/gateway/configuration/GatewayConfigurationLoader.java b/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-core/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/core/gateway/configuration/GatewayConfigurationLoader.java similarity index 100% rename from edc-extensions/dataplane-proxy/edc-dataplane-proxy-provider-core/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/core/gateway/configuration/GatewayConfigurationLoader.java rename to edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-core/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/core/gateway/configuration/GatewayConfigurationLoader.java diff --git a/edc-extensions/dataplane-proxy/edc-dataplane-proxy-provider-core/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/core/gateway/configuration/GatewayConfigurationRegistryImpl.java b/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-core/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/core/gateway/configuration/GatewayConfigurationRegistryImpl.java similarity index 100% rename from edc-extensions/dataplane-proxy/edc-dataplane-proxy-provider-core/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/core/gateway/configuration/GatewayConfigurationRegistryImpl.java rename to edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-core/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/core/gateway/configuration/GatewayConfigurationRegistryImpl.java diff --git a/edc-extensions/dataplane-proxy/edc-dataplane-proxy-provider-core/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension b/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-core/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension similarity index 100% rename from edc-extensions/dataplane-proxy/edc-dataplane-proxy-provider-core/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension rename to edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-core/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension diff --git a/edc-extensions/dataplane-proxy/edc-dataplane-proxy-provider-core/src/test/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/core/gateway/auth/AuthorizationHandlerRegistryImplTest.java b/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-core/src/test/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/core/gateway/auth/AuthorizationHandlerRegistryImplTest.java similarity index 100% rename from edc-extensions/dataplane-proxy/edc-dataplane-proxy-provider-core/src/test/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/core/gateway/auth/AuthorizationHandlerRegistryImplTest.java rename to edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-core/src/test/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/core/gateway/auth/AuthorizationHandlerRegistryImplTest.java diff --git a/edc-extensions/dataplane-proxy/edc-dataplane-proxy-provider-core/src/test/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/core/gateway/configuration/GatewayConfigurationLoaderTest.java b/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-core/src/test/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/core/gateway/configuration/GatewayConfigurationLoaderTest.java similarity index 100% rename from edc-extensions/dataplane-proxy/edc-dataplane-proxy-provider-core/src/test/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/core/gateway/configuration/GatewayConfigurationLoaderTest.java rename to edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-core/src/test/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/core/gateway/configuration/GatewayConfigurationLoaderTest.java diff --git a/edc-extensions/dataplane-proxy/edc-dataplane-proxy-provider-core/src/test/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/core/gateway/configuration/GatewayConfigurationRegistryImplTest.java b/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-core/src/test/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/core/gateway/configuration/GatewayConfigurationRegistryImplTest.java similarity index 100% rename from edc-extensions/dataplane-proxy/edc-dataplane-proxy-provider-core/src/test/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/core/gateway/configuration/GatewayConfigurationRegistryImplTest.java rename to edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-core/src/test/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/core/gateway/configuration/GatewayConfigurationRegistryImplTest.java diff --git a/edc-extensions/dataplane-proxy/edc-dataplane-proxy-provider-spi/build.gradle.kts b/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-spi/build.gradle.kts similarity index 100% rename from edc-extensions/dataplane-proxy/edc-dataplane-proxy-provider-spi/build.gradle.kts rename to edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-spi/build.gradle.kts diff --git a/edc-extensions/dataplane-proxy/edc-dataplane-proxy-provider-spi/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/spi/provider/gateway/authorization/AuthorizationExtension.java b/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-spi/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/spi/provider/gateway/authorization/AuthorizationExtension.java similarity index 100% rename from edc-extensions/dataplane-proxy/edc-dataplane-proxy-provider-spi/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/spi/provider/gateway/authorization/AuthorizationExtension.java rename to edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-spi/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/spi/provider/gateway/authorization/AuthorizationExtension.java diff --git a/edc-extensions/dataplane-proxy/edc-dataplane-proxy-provider-spi/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/spi/provider/gateway/authorization/AuthorizationHandler.java b/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-spi/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/spi/provider/gateway/authorization/AuthorizationHandler.java similarity index 100% rename from edc-extensions/dataplane-proxy/edc-dataplane-proxy-provider-spi/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/spi/provider/gateway/authorization/AuthorizationHandler.java rename to edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-spi/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/spi/provider/gateway/authorization/AuthorizationHandler.java diff --git a/edc-extensions/dataplane-proxy/edc-dataplane-proxy-provider-spi/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/spi/provider/gateway/authorization/AuthorizationHandlerRegistry.java b/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-spi/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/spi/provider/gateway/authorization/AuthorizationHandlerRegistry.java similarity index 100% rename from edc-extensions/dataplane-proxy/edc-dataplane-proxy-provider-spi/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/spi/provider/gateway/authorization/AuthorizationHandlerRegistry.java rename to edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-spi/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/spi/provider/gateway/authorization/AuthorizationHandlerRegistry.java diff --git a/edc-extensions/dataplane-proxy/edc-dataplane-proxy-provider-spi/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/spi/provider/gateway/configuration/GatewayConfiguration.java b/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-spi/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/spi/provider/gateway/configuration/GatewayConfiguration.java similarity index 100% rename from edc-extensions/dataplane-proxy/edc-dataplane-proxy-provider-spi/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/spi/provider/gateway/configuration/GatewayConfiguration.java rename to edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-spi/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/spi/provider/gateway/configuration/GatewayConfiguration.java diff --git a/edc-extensions/dataplane-proxy/edc-dataplane-proxy-provider-spi/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/spi/provider/gateway/configuration/GatewayConfigurationRegistry.java b/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-spi/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/spi/provider/gateway/configuration/GatewayConfigurationRegistry.java similarity index 100% rename from edc-extensions/dataplane-proxy/edc-dataplane-proxy-provider-spi/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/spi/provider/gateway/configuration/GatewayConfigurationRegistry.java rename to edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-spi/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/spi/provider/gateway/configuration/GatewayConfigurationRegistry.java diff --git a/edc-extensions/dataplane-selector-configuration/README.md b/edc-extensions/dataplane/dataplane-selector-configuration/README.md similarity index 100% rename from edc-extensions/dataplane-selector-configuration/README.md rename to edc-extensions/dataplane/dataplane-selector-configuration/README.md diff --git a/edc-extensions/dataplane-selector-configuration/build.gradle.kts b/edc-extensions/dataplane/dataplane-selector-configuration/build.gradle.kts similarity index 100% rename from edc-extensions/dataplane-selector-configuration/build.gradle.kts rename to edc-extensions/dataplane/dataplane-selector-configuration/build.gradle.kts diff --git a/edc-extensions/dataplane-selector-configuration/src/main/java/org/eclipse/tractusx/edc/dataplane/selector/configuration/DataPlaneSelectorConfigurationServiceExtension.java b/edc-extensions/dataplane/dataplane-selector-configuration/src/main/java/org/eclipse/tractusx/edc/dataplane/selector/configuration/DataPlaneSelectorConfigurationServiceExtension.java similarity index 100% rename from edc-extensions/dataplane-selector-configuration/src/main/java/org/eclipse/tractusx/edc/dataplane/selector/configuration/DataPlaneSelectorConfigurationServiceExtension.java rename to edc-extensions/dataplane/dataplane-selector-configuration/src/main/java/org/eclipse/tractusx/edc/dataplane/selector/configuration/DataPlaneSelectorConfigurationServiceExtension.java diff --git a/edc-extensions/dataplane-selector-configuration/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension b/edc-extensions/dataplane/dataplane-selector-configuration/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension similarity index 100% rename from edc-extensions/dataplane-selector-configuration/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension rename to edc-extensions/dataplane/dataplane-selector-configuration/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension diff --git a/edc-extensions/dataplane-selector-configuration/src/test/java/org/eclipse/tractusx/edc/dataplane/selector/configuration/DataPlaneSelectorConfigurationServiceExtensionEdcExtensionTest.java b/edc-extensions/dataplane/dataplane-selector-configuration/src/test/java/org/eclipse/tractusx/edc/dataplane/selector/configuration/DataPlaneSelectorConfigurationServiceExtensionEdcExtensionTest.java similarity index 100% rename from edc-extensions/dataplane-selector-configuration/src/test/java/org/eclipse/tractusx/edc/dataplane/selector/configuration/DataPlaneSelectorConfigurationServiceExtensionEdcExtensionTest.java rename to edc-extensions/dataplane/dataplane-selector-configuration/src/test/java/org/eclipse/tractusx/edc/dataplane/selector/configuration/DataPlaneSelectorConfigurationServiceExtensionEdcExtensionTest.java diff --git a/edc-extensions/dataplane-selector-configuration/src/test/java/org/eclipse/tractusx/edc/dataplane/selector/configuration/DataPlaneSelectorConfigurationServiceExtensionTest.java b/edc-extensions/dataplane/dataplane-selector-configuration/src/test/java/org/eclipse/tractusx/edc/dataplane/selector/configuration/DataPlaneSelectorConfigurationServiceExtensionTest.java similarity index 100% rename from edc-extensions/dataplane-selector-configuration/src/test/java/org/eclipse/tractusx/edc/dataplane/selector/configuration/DataPlaneSelectorConfigurationServiceExtensionTest.java rename to edc-extensions/dataplane/dataplane-selector-configuration/src/test/java/org/eclipse/tractusx/edc/dataplane/selector/configuration/DataPlaneSelectorConfigurationServiceExtensionTest.java diff --git a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/build.gradle.kts b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/build.gradle.kts new file mode 100644 index 000000000..1597ed047 --- /dev/null +++ b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/build.gradle.kts @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +plugins { + `java-library` +} + +dependencies { + api(project(":spi:tokenrefresh-spi")) + implementation(libs.edc.spi.core) + implementation(libs.edc.spi.token) + implementation(libs.edc.spi.identity.did) + implementation(libs.edc.spi.dataplane.dataplane) + implementation(libs.edc.core.token) + + testImplementation(libs.edc.junit) + testImplementation(libs.edc.dpf.core) + testImplementation(libs.edc.common.crypto) +} + diff --git a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceExtension.java b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceExtension.java new file mode 100644 index 000000000..0acc3a818 --- /dev/null +++ b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceExtension.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.eclipse.tractusx.edc.dataplane.tokenrefresh.core; + +import org.eclipse.edc.connector.dataplane.spi.iam.DataPlaneAccessTokenService; +import org.eclipse.edc.connector.dataplane.spi.store.AccessTokenDataStore; +import org.eclipse.edc.iam.did.spi.resolution.DidPublicKeyResolver; +import org.eclipse.edc.runtime.metamodel.annotation.Extension; +import org.eclipse.edc.runtime.metamodel.annotation.Inject; +import org.eclipse.edc.runtime.metamodel.annotation.Provider; +import org.eclipse.edc.spi.security.PrivateKeyResolver; +import org.eclipse.edc.spi.system.ServiceExtension; +import org.eclipse.edc.spi.system.ServiceExtensionContext; +import org.eclipse.edc.token.JwtGenerationService; +import org.eclipse.edc.token.spi.TokenValidationService; +import org.jetbrains.annotations.NotNull; + +import java.security.PrivateKey; +import java.util.function.Supplier; + +import static org.eclipse.edc.connector.dataplane.spi.TransferDataPlaneConfig.TOKEN_SIGNER_PRIVATE_KEY_ALIAS; +import static org.eclipse.tractusx.edc.dataplane.tokenrefresh.core.DataPlaneTokenRefreshServiceExtension.NAME; + +@Extension(value = NAME) +public class DataPlaneTokenRefreshServiceExtension implements ServiceExtension { + public static final String NAME = "DataPlane Token Refresh Service extension"; + @Inject + private TokenValidationService tokenValidationService; + @Inject + private DidPublicKeyResolver didPkResolver; + @Inject + private AccessTokenDataStore accessTokenDataStore; + + @Inject + private PrivateKeyResolver privateKeyResolver; + + @Override + public String name() { + return NAME; + } + + @Provider + public DataPlaneAccessTokenService createRefreshAccessTokenService(ServiceExtensionContext context) { + return new DataPlaneTokenRefreshServiceImpl(tokenValidationService, didPkResolver, accessTokenDataStore, new JwtGenerationService(), getPrivateKeySupplier(context), context.getMonitor(), "foo.bar"); + } + + @NotNull + private Supplier getPrivateKeySupplier(ServiceExtensionContext context) { + return () -> { + var alias = context.getConfig().getString(TOKEN_SIGNER_PRIVATE_KEY_ALIAS); + return privateKeyResolver.resolvePrivateKey(alias) + .orElse(f -> { + context.getMonitor().warning("Cannot resolve private key: " + f.getFailureDetail()); + return null; + }); + }; + } +} diff --git a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImpl.java b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImpl.java new file mode 100644 index 000000000..ea47788c9 --- /dev/null +++ b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImpl.java @@ -0,0 +1,235 @@ +/* + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.eclipse.tractusx.edc.dataplane.tokenrefresh.core; + +import org.eclipse.edc.connector.dataplane.spi.AccessTokenData; +import org.eclipse.edc.connector.dataplane.spi.iam.DataPlaneAccessTokenService; +import org.eclipse.edc.connector.dataplane.spi.store.AccessTokenDataStore; +import org.eclipse.edc.iam.did.spi.resolution.DidPublicKeyResolver; +import org.eclipse.edc.spi.iam.ClaimToken; +import org.eclipse.edc.spi.iam.TokenParameters; +import org.eclipse.edc.spi.iam.TokenRepresentation; +import org.eclipse.edc.spi.monitor.Monitor; +import org.eclipse.edc.spi.result.Result; +import org.eclipse.edc.spi.types.domain.DataAddress; +import org.eclipse.edc.token.spi.TokenDecorator; +import org.eclipse.edc.token.spi.TokenGenerationService; +import org.eclipse.edc.token.spi.TokenValidationRule; +import org.eclipse.edc.token.spi.TokenValidationService; +import org.eclipse.tractusx.edc.dataplane.tokenrefresh.core.rules.ClaimIsPresentRule; +import org.eclipse.tractusx.edc.dataplane.tokenrefresh.core.rules.IssuerEqualsSubjectRule; +import org.eclipse.tractusx.edc.dataplane.tokenrefresh.core.rules.RefreshTokenMustExistRule; +import org.eclipse.tractusx.edc.dataplane.tokenrefresh.spi.DataPlaneTokenRefreshService; +import org.eclipse.tractusx.edc.dataplane.tokenrefresh.spi.model.TokenResponse; + +import java.security.PrivateKey; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.UUID; +import java.util.concurrent.atomic.AtomicReference; +import java.util.function.Supplier; +import java.util.stream.Stream; + +/** + * This implementation of the {@link DataPlaneTokenRefreshService} validates an incoming authentication token. + */ +public class DataPlaneTokenRefreshServiceImpl implements DataPlaneTokenRefreshService, DataPlaneAccessTokenService { + public static final String ACCESS_TOKEN_CLAIM = "access_token"; + public static final String TOKEN_ID_CLAIM = "jti"; + public static final String REFRESH_TOKEN_PROPERTY = "refreshToken"; + private static final Long DEFAULT_EXPIRY_IN_SECONDS = 60 * 5L; + private final List tokenValidationRules = List.of(new IssuerEqualsSubjectRule(), new ClaimIsPresentRule(ACCESS_TOKEN_CLAIM), new ClaimIsPresentRule(TOKEN_ID_CLAIM)); + private final TokenValidationService tokenValidationService; + private final DidPublicKeyResolver publicKeyResolver; + private final AccessTokenDataStore accessTokenDataStore; + private final TokenGenerationService tokenGenerationService; + private final Supplier privateKeySupplier; + private final Monitor monitor; + private final String refreshEndpoint; + + + public DataPlaneTokenRefreshServiceImpl(TokenValidationService tokenValidationService, + DidPublicKeyResolver publicKeyResolver, + AccessTokenDataStore accessTokenDataStore, + TokenGenerationService tokenGenerationService, Supplier privateKeySupplier, Monitor monitor, String refreshEndpoint) { + this.tokenValidationService = tokenValidationService; + this.publicKeyResolver = publicKeyResolver; + this.accessTokenDataStore = accessTokenDataStore; + this.tokenGenerationService = tokenGenerationService; + this.privateKeySupplier = privateKeySupplier; + this.monitor = monitor; + this.refreshEndpoint = refreshEndpoint; + } + + /** + * Refreshes an incoming refresh token and authentication token. During validation of those tokens, the following steps are performed: + * + *
      + *
    • parse the {@code authenticationToken} into a {@link com.nimbusds.jwt.JWT}
    • + *
    • resolve the DID based on the {@code iss} claim
    • + *
    • resolve the public key material in the DID Document identified by the {@code kid} header
    • + *
    • verify the token's signature
    • + *
    • assert {@code iss} and {@code sub} claims are identical
    • + *
    • assert the the token contains an {@code access_token} claim, and that the value is identical to the access token we have on record
    • + *
    • assert that the {@code refreshToken} parameter is identical to the refresh token we have on record
    • + *
    + * + * @param refreshToken The refresh token that was issued in the original/previous token request. + * @param authenticationToken A
    client authentication token + */ + @Override + public Result refreshToken(String refreshToken, String authenticationToken) { + + var allRules = new ArrayList<>(tokenValidationRules); + allRules.add(new RefreshTokenMustExistRule(accessTokenDataStore, refreshToken)); + + var accessTokenDataResult = resolveToken(authenticationToken, allRules); + if (accessTokenDataResult.failed()) { + return accessTokenDataResult.mapTo(); + } + + var existingAccessTokenData = accessTokenDataResult.getContent(); + + var newTokenParams = TokenParameters.Builder.newInstance() + .claims(existingAccessTokenData.claimToken().getClaims()) + .build(); + + var newAccessToken = createToken(newTokenParams).map(tr -> tr.tokenRepresentation().getToken()); + var newRefreshToken = createToken(TokenParameters.Builder.newInstance().build()).map(tr -> tr.tokenRepresentation().getToken()); + if (newAccessToken.failed() || newRefreshToken.failed()) { + var errors = new ArrayList<>(newAccessToken.getFailureMessages()); + errors.addAll(newRefreshToken.getFailureMessages()); + return Result.failure("Failed to regenerate access/refresh token pair: %s".formatted(errors)); + } + + // additional token information will be added to the TokenRepresentation, which will be returned to the caller + // note: can't use DBI (double-bracket initialization) here, because SonarCloud will complain about it + var accessTokenAdditional = new HashMap<>(existingAccessTokenData.additionalProperties()); + accessTokenAdditional.put(REFRESH_TOKEN_PROPERTY, newRefreshToken.getContent()); + accessTokenAdditional.put("expiresIn", DEFAULT_EXPIRY_IN_SECONDS); + accessTokenAdditional.put("refreshEndpoint", refreshEndpoint); + accessTokenAdditional.put("authType", "bearer"); + + // the ClaimToken is created based solely on the TokenParameters. The additional information (refresh token...) is persisted separately + var claimToken = ClaimToken.Builder.newInstance().claims(newTokenParams.getClaims()).build(); + var accessTokenData = new AccessTokenData(existingAccessTokenData.id(), claimToken, existingAccessTokenData.dataAddress(), accessTokenAdditional); + + var storeResult = accessTokenDataStore.update(accessTokenData); + return storeResult.succeeded() ? + Result.success(new TokenResponse(newAccessToken.getContent(), + newRefreshToken.getContent(), DEFAULT_EXPIRY_IN_SECONDS, "bearer")) : + Result.failure(storeResult.getFailureMessages()); + } + + @Override + public Result obtainToken(TokenParameters tokenParameters, DataAddress backendDataAddress, Map additionalTokenData) { + Objects.requireNonNull(tokenParameters, "TokenParameters must be non-null."); + Objects.requireNonNull(backendDataAddress, "DataAddress must be non-null."); + + + //create a refresh token + var refreshTokenResult = createToken(TokenParameters.Builder.newInstance().build()); + if (refreshTokenResult.failed()) { + return Result.failure("Could not generate refresh token: %s".formatted(refreshTokenResult.getFailureDetail())); + } + + var accessTokenResult = createToken(tokenParameters); + if (accessTokenResult.failed()) { + return Result.failure("Could not generate access token: %s".formatted(accessTokenResult.getFailureDetail())); + } + + // additional token information will be added to the TokenRepresentation, which will be returned to the caller + // note: can't use DBI (double-bracket initialization) here, because SonarCloud will complain about it + var accessTokenAdditional = new HashMap<>(additionalTokenData); + accessTokenAdditional.put("refreshToken", refreshTokenResult.getContent().tokenRepresentation().getToken()); + accessTokenAdditional.put("expiresIn", DEFAULT_EXPIRY_IN_SECONDS); + accessTokenAdditional.put("refreshEndpoint", refreshEndpoint); + accessTokenAdditional.put("authType", "bearer"); + + var accessToken = TokenRepresentation.Builder.newInstance() + .token(accessTokenResult.getContent().tokenRepresentation().getToken()) // the access token + .additional(accessTokenAdditional) //contains additional properties and the refresh token + .expiresIn(DEFAULT_EXPIRY_IN_SECONDS) //todo: needed? + .build(); + + // the ClaimToken is created based solely on the TokenParameters. The additional information (refresh token...) is persisted separately + var claimToken = ClaimToken.Builder.newInstance().claims(tokenParameters.getClaims()).build(); + var accessTokenData = new AccessTokenData(accessTokenResult.getContent().id(), claimToken, backendDataAddress, accessTokenAdditional); + + var storeResult = accessTokenDataStore.store(accessTokenData); + return storeResult.succeeded() ? Result.success(accessToken) : Result.failure(storeResult.getFailureMessages()); + } + + @Override + public Result resolve(String token) { + return resolveToken(token, tokenValidationRules); + } + + /** + * Creates a token that has an ID based on the given token parameters. If the token parameters don't contain a "jti" claim, one + * will be generated at random. + */ + private Result createToken(TokenParameters tokenParameters) { + var claimDecorators = tokenParameters.getClaims().entrySet().stream().map(e -> (TokenDecorator) claimDecorator -> claimDecorator.claims(e.getKey(), e.getValue())); + var headerDecorators = tokenParameters.getHeaders().entrySet().stream().map(e -> (TokenDecorator) headerDecorator -> headerDecorator.header(e.getKey(), e.getValue())); + + var tokenId = new AtomicReference<>(tokenParameters.getStringClaim(TOKEN_ID_CLAIM)); + var allDecorators = new ArrayList<>(Stream.concat(claimDecorators, headerDecorators).toList()); + + // if there is no "jti" header on the token params, we'll assign a random one, and add it back to the decorators + if (tokenId.get() == null) { + monitor.info("No '%s' claim found on TokenParameters. Will generate a random one.".formatted(TOKEN_ID_CLAIM)); + tokenId.set(UUID.randomUUID().toString()); + TokenDecorator tokenIdDecorator = params -> params.claims(TOKEN_ID_CLAIM, tokenId.get()); + allDecorators.add(tokenIdDecorator); + } + + return tokenGenerationService.generate(privateKeySupplier, allDecorators.toArray(new TokenDecorator[0])) + .map(tr -> new TokenRepresentationWithId(tokenId.get(), tr)); + } + + /** + * Parses the given token, and validates it against the given rules. For that, the publicKeyResolver is used. + * Once the token is deemed valid, the "jti" claim (which is mandatory) is extracted and used as key for a lookup in the + * {@link AccessTokenDataStore}. The result of that is then returned. + */ + private Result resolveToken(String token, List rules) { + var validationResult = tokenValidationService.validate(token, publicKeyResolver, rules); + if (validationResult.failed()) { + return validationResult.mapTo(); + } + var tokenId = validationResult.getContent().getStringClaim(TOKEN_ID_CLAIM); + var existingAccessToken = accessTokenDataStore.getById(tokenId); + + return existingAccessToken == null ? + Result.failure("AccessTokenData with ID '%s' does not exist.".formatted(tokenId)) : + Result.success(existingAccessToken); + } + + /** + * container object for a TokenRepresentation and an ID + */ + private record TokenRepresentationWithId(String id, TokenRepresentation tokenRepresentation) { + + } +} diff --git a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/rules/ClaimIsPresentRule.java b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/rules/ClaimIsPresentRule.java new file mode 100644 index 000000000..11cbe8dae --- /dev/null +++ b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/rules/ClaimIsPresentRule.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.eclipse.tractusx.edc.dataplane.tokenrefresh.core.rules; + +import org.eclipse.edc.spi.iam.ClaimToken; +import org.eclipse.edc.spi.result.Result; +import org.eclipse.edc.token.spi.TokenValidationRule; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Map; + +public class ClaimIsPresentRule implements TokenValidationRule { + private final String claimName; + + public ClaimIsPresentRule(String claimName) { + this.claimName = claimName; + } + + @Override + public Result checkRule(@NotNull ClaimToken toVerify, @Nullable Map additional) { + return toVerify.getClaims().containsKey(claimName) ? + Result.success() : + Result.failure("Required claim '%s' not present on token.".formatted(claimName)); + } +} diff --git a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/rules/IssuerEqualsSubjectRule.java b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/rules/IssuerEqualsSubjectRule.java new file mode 100644 index 000000000..6eba164cc --- /dev/null +++ b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/rules/IssuerEqualsSubjectRule.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.eclipse.tractusx.edc.dataplane.tokenrefresh.core.rules; + +import com.nimbusds.jwt.JWTClaimNames; +import org.eclipse.edc.spi.iam.ClaimToken; +import org.eclipse.edc.spi.result.Result; +import org.eclipse.edc.token.spi.TokenValidationRule; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Map; +import java.util.Objects; + +import static org.eclipse.edc.spi.result.Result.failure; + +public class IssuerEqualsSubjectRule implements TokenValidationRule { + @Override + public Result checkRule(@NotNull ClaimToken toVerify, @Nullable Map additional) { + var iss = toVerify.getStringClaim(JWTClaimNames.ISSUER); + var sub = toVerify.getStringClaim(JWTClaimNames.SUBJECT); + + return iss != null && Objects.equals(iss, sub) ? + Result.success() : + failure("The 'iss' and 'sub' claims must be non-null and identical."); + } +} diff --git a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/rules/RefreshTokenMustExistRule.java b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/rules/RefreshTokenMustExistRule.java new file mode 100644 index 000000000..ccf42c31d --- /dev/null +++ b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/rules/RefreshTokenMustExistRule.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.eclipse.tractusx.edc.dataplane.tokenrefresh.core.rules; + +import com.nimbusds.jwt.JWTClaimNames; +import org.eclipse.edc.connector.dataplane.spi.AccessTokenData; +import org.eclipse.edc.connector.dataplane.spi.store.AccessTokenDataStore; +import org.eclipse.edc.spi.iam.ClaimToken; +import org.eclipse.edc.spi.result.Result; +import org.eclipse.edc.token.spi.TokenValidationRule; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Map; +import java.util.Optional; + +import static org.eclipse.tractusx.edc.dataplane.tokenrefresh.core.DataPlaneTokenRefreshServiceImpl.ACCESS_TOKEN_CLAIM; +import static org.eclipse.tractusx.edc.dataplane.tokenrefresh.core.DataPlaneTokenRefreshServiceImpl.REFRESH_TOKEN_PROPERTY; + +public class RefreshTokenMustExistRule implements TokenValidationRule { + private static final String AUDIENCE_PROPERTY = "audience"; + private final AccessTokenDataStore accessTokenDataStore; + private final String refreshToken; + + public RefreshTokenMustExistRule(AccessTokenDataStore accessTokenDataStore, String refreshToken) { + this.accessTokenDataStore = accessTokenDataStore; + this.refreshToken = refreshToken; + } + + @Override + public Result checkRule(@NotNull ClaimToken toVerify, @Nullable Map additional) { + var oldAccessToken = toVerify.getStringClaim(ACCESS_TOKEN_CLAIM); + var tokenId = toVerify.getStringClaim(JWTClaimNames.JWT_ID); + var issuer = toVerify.getStringClaim(JWTClaimNames.ISSUER); + return Optional.ofNullable(accessTokenDataStore.getById(tokenId)) + .map(accessTokenData -> checkExists(accessTokenData, refreshToken, issuer)) + .orElse(Result.failure("No AccessTokenData entry found for token-ID '%s'.".formatted(tokenId))); + } + + private Result checkExists(AccessTokenData accessTokenData, String refreshToken, String issuer) { + var storedRefreshToken = accessTokenData.additionalProperties().getOrDefault(REFRESH_TOKEN_PROPERTY, null); + if (!(storedRefreshToken instanceof String)) { + return Result.failure("Property '%s' expected to be String but was %s".formatted(REFRESH_TOKEN_PROPERTY, storedRefreshToken == null ? "null" : storedRefreshToken.getClass())); + } + if (!refreshToken.equals(storedRefreshToken)) { + return Result.failure("Provided refresh token does not match the stored refresh token."); + } + var audience = accessTokenData.additionalProperties().getOrDefault(AUDIENCE_PROPERTY, null); + if (!(audience instanceof String)) { + return Result.failure("Property '%s' expected to be String but was %s".formatted(AUDIENCE_PROPERTY, audience == null ? "null" : audience.getClass())); + } + + if (!audience.equals(issuer)) { + return Result.failure("Principal '%s' is not authorized to refresh this token.".formatted(issuer)); + } + + return Result.success(); + } +} diff --git a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension new file mode 100644 index 000000000..99b6a2cb5 --- /dev/null +++ b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension @@ -0,0 +1,20 @@ +################################################################################# +# Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License, Version 2.0 which is available at +# https://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. +# +# SPDX-License-Identifier: Apache-2.0 +################################################################################# + +org.eclipse.tractusx.edc.dataplane.tokenrefresh.core.DataPlaneTokenRefreshServiceExtension \ No newline at end of file diff --git a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImplComponentTest.java b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImplComponentTest.java new file mode 100644 index 000000000..28240b505 --- /dev/null +++ b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImplComponentTest.java @@ -0,0 +1,246 @@ +/* + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.eclipse.tractusx.edc.dataplane.tokenrefresh.core; + +import com.nimbusds.jose.JOSEException; +import com.nimbusds.jose.JWSAlgorithm; +import com.nimbusds.jose.JWSHeader; +import com.nimbusds.jose.jwk.Curve; +import com.nimbusds.jose.jwk.ECKey; +import com.nimbusds.jose.jwk.KeyUse; +import com.nimbusds.jose.jwk.gen.ECKeyGenerator; +import com.nimbusds.jwt.JWTClaimsSet; +import com.nimbusds.jwt.SignedJWT; +import org.eclipse.edc.connector.core.store.CriterionOperatorRegistryImpl; +import org.eclipse.edc.connector.dataplane.framework.store.InMemoryAccessTokenDataStore; +import org.eclipse.edc.iam.did.spi.resolution.DidPublicKeyResolver; +import org.eclipse.edc.junit.annotations.ComponentTest; +import org.eclipse.edc.jwt.spi.JwtRegisteredClaimNames; +import org.eclipse.edc.security.token.jwt.CryptoConverter; +import org.eclipse.edc.spi.iam.TokenParameters; +import org.eclipse.edc.spi.result.Result; +import org.eclipse.edc.spi.types.domain.DataAddress; +import org.eclipse.edc.spi.types.domain.transfer.FlowType; +import org.eclipse.edc.token.JwtGenerationService; +import org.eclipse.edc.token.TokenValidationServiceImpl; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.text.ParseException; +import java.time.Instant; +import java.util.List; +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.eclipse.edc.connector.dataplane.framework.iam.DataPlaneAuthorizationServiceImpl.CLAIM_AGREEMENT_ID; +import static org.eclipse.edc.connector.dataplane.framework.iam.DataPlaneAuthorizationServiceImpl.CLAIM_ASSET_ID; +import static org.eclipse.edc.connector.dataplane.framework.iam.DataPlaneAuthorizationServiceImpl.CLAIM_FLOW_TYPE; +import static org.eclipse.edc.connector.dataplane.framework.iam.DataPlaneAuthorizationServiceImpl.CLAIM_PROCESS_ID; +import static org.eclipse.edc.junit.assertions.AbstractResultAssert.assertThat; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +@ComponentTest +class DataPlaneTokenRefreshServiceImplComponentTest { + + public static final String PROVIDER_BPN = "BPN0000ALICE"; + public static final String CONSUMER_BPN = "BPN0000BOB"; + public static final String TEST_REFRESH_ENDPOINT = "https://fizz.buzz.com"; + public static final String CONSUMER_DID = "did:web:bob"; + public static final String PROVIDER_DID = "did:web:alice"; + private final DidPublicKeyResolver didPkResolverMock = mock(); + private DataPlaneTokenRefreshServiceImpl tokenRefreshService; + private InMemoryAccessTokenDataStore tokenDataStore; + private ECKey consumerKey; + + @BeforeEach + void setup() throws JOSEException { + + var providerKey = new ECKeyGenerator(Curve.P_384).keyID(PROVIDER_BPN + "#provider-key").keyUse(KeyUse.SIGNATURE).generate(); + consumerKey = new ECKeyGenerator(Curve.P_384).keyID(CONSUMER_DID + "#consumer-key").keyUse(KeyUse.SIGNATURE).generate(); + + var privateKey = providerKey.toPrivateKey(); + + tokenDataStore = new InMemoryAccessTokenDataStore(CriterionOperatorRegistryImpl.ofDefaults()); + tokenRefreshService = new DataPlaneTokenRefreshServiceImpl(new TokenValidationServiceImpl(), + didPkResolverMock, + tokenDataStore, + new JwtGenerationService(), + () -> privateKey, + mock(), + TEST_REFRESH_ENDPOINT); + + when(didPkResolverMock.resolveKey(eq(consumerKey.getKeyID()))).thenReturn(Result.success(consumerKey.toPublicKey())); + when(didPkResolverMock.resolveKey(eq(providerKey.getKeyID()))).thenReturn(Result.success(providerKey.toPublicKey())); + } + + @DisplayName("Verify that a correct EDR is obtained") + @Test + void obtainToken() { + var tokenId = "test-token-id"; + var edr = tokenRefreshService.obtainToken(tokenParams(tokenId), DataAddress.Builder.newInstance().type("test-type").build(), Map.of("audience", CONSUMER_DID)); + assertThat(edr).isSucceeded(); + // assert access token contents + assertThat(asClaims(edr.getContent().getToken())) + .containsKey("asset_id") + .containsKey("process_id") + .containsKey("agreement_id") + .containsEntry("iss", PROVIDER_BPN) + .containsEntry("sub", PROVIDER_BPN) + .containsEntry("aud", List.of(CONSUMER_BPN)); + + // assert additional properties -> refresh token + assertThat(edr.getContent().getAdditional()) + .containsEntry("refreshEndpoint", TEST_REFRESH_ENDPOINT) + .containsKey("refreshToken") + .containsKey("expiresIn"); + + // verify that the correct data was stored + var storedData = tokenDataStore.getById(tokenId); + assertThat(storedData).isNotNull(); + assertThat(storedData.additionalProperties()) + .containsEntry("audience", CONSUMER_DID) + .containsEntry("refreshEndpoint", TEST_REFRESH_ENDPOINT) + .containsKey("refreshToken") + .containsKey("expiresIn") + .containsEntry("authType", "bearer"); + + } + + @DisplayName("Verify that a token can be refreshed") + @Test + void refresh_success() throws JOSEException { + + var tokenId = "test-token-id"; + var edr = tokenRefreshService.obtainToken(tokenParams(tokenId), DataAddress.Builder.newInstance().type("test-type").build(), Map.of("audience", CONSUMER_DID)) + .orElseThrow(f -> new RuntimeException(f.getFailureDetail())); + + var accessToken = edr.getToken(); + var jwsHeader = new JWSHeader.Builder(JWSAlgorithm.ES384).keyID(consumerKey.getKeyID()).build(); + var claimsSet = getAuthTokenClaims(tokenId, accessToken).build(); + + var signedAuthToken = new SignedJWT(jwsHeader, claimsSet); + signedAuthToken.sign(CryptoConverter.createSigner(consumerKey)); + var tokenResponse = tokenRefreshService.refreshToken(edr.getAdditional().get("refreshToken").toString(), signedAuthToken.serialize()); + + assertThat(tokenResponse).withFailMessage(tokenResponse::getFailureDetail).isSucceeded() + .satisfies(tr -> assertThat(tr.refreshToken()).isNotNull()) + .satisfies(tr -> assertThat(tr.accessToken()).isNotNull()); + } + + @DisplayName("Verify that a refresh token can only be refreshed by the original recipient") + @Test + void refresh_originalTokenWasIssuedToDifferentPrincipal() throws JOSEException { + var trudyKey = new ECKeyGenerator(Curve.P_256).keyID("did:web:trudy#trudy-key").generate(); + when(didPkResolverMock.resolveKey(eq("did:web:trudy#trudy-key"))).thenReturn(Result.success(trudyKey.toPublicKey())); + + + var tokenId = "test-token-id"; + var edr = tokenRefreshService.obtainToken(tokenParams(tokenId), DataAddress.Builder.newInstance().type("test-type").build(), Map.of("audience", "did:web:trudy")) + .orElseThrow(f -> new RuntimeException(f.getFailureDetail())); + + // bob attempts to create an auth token with an EDR he stole from trudy + var accessToken = edr.getToken(); + var jwsHeader = new JWSHeader.Builder(JWSAlgorithm.ES384).keyID(consumerKey.getKeyID()).build(); + var claimsSet = getAuthTokenClaims(tokenId, accessToken).build(); + + var signedAuthToken = new SignedJWT(jwsHeader, claimsSet); + signedAuthToken.sign(CryptoConverter.createSigner(consumerKey)); + var tokenResponse = tokenRefreshService.refreshToken(edr.getAdditional().get("refreshToken").toString(), signedAuthToken.serialize()); + + assertThat(tokenResponse).isFailed().detail().isEqualTo("Principal 'did:web:bob' is not authorized to refresh this token."); + } + + @DisplayName("Verify that a spoofed refresh attempt is rejected ") + @Test + void refresh_issuerNotVerifiable() throws JOSEException { + var trudyKey = new ECKeyGenerator(Curve.P_384).keyID("did:web:trudy#trudy-key").generate(); + when(didPkResolverMock.resolveKey(eq(trudyKey.getKeyID()))).thenReturn(Result.success(trudyKey.toPublicKey())); + + var tokenId = "test-token-id"; + var edr = tokenRefreshService.obtainToken(tokenParams(tokenId), DataAddress.Builder.newInstance().type("test-type").build(), Map.of("audience", "did:web:trudy")) + .orElseThrow(f -> new RuntimeException(f.getFailureDetail())); + + // bob poses as trudy, using her key-ID and DID, but has to use his own private key + var accessToken = edr.getToken(); + var jwsHeader = new JWSHeader.Builder(JWSAlgorithm.ES384).keyID(trudyKey.getKeyID()).build(); + var claimsSet = getAuthTokenClaims(tokenId, accessToken).issuer("did:web:trudy").subject("did:web:trudy").build(); + + var signedAuthToken = new SignedJWT(jwsHeader, claimsSet); + signedAuthToken.sign(CryptoConverter.createSigner(consumerKey)); + var tokenResponse = tokenRefreshService.refreshToken(edr.getAdditional().get("refreshToken").toString(), signedAuthToken.serialize()); + + assertThat(tokenResponse).isFailed().detail().isEqualTo("Token verification failed"); + } + + @DisplayName("Verify that a refresh attempt fails if no \"access_token\" claim is present") + @Test + void refresh_whenNoAccessTokenClaim() throws JOSEException { + var tokenId = "test-token-id"; + var edr = tokenRefreshService.obtainToken(tokenParams(tokenId), DataAddress.Builder.newInstance().type("test-type").build(), Map.of("audience", CONSUMER_DID)) + .orElseThrow(f -> new RuntimeException(f.getFailureDetail())); + + var accessToken = edr.getToken(); + var jwsHeader = new JWSHeader.Builder(JWSAlgorithm.ES384).keyID(consumerKey.getKeyID()).build(); + var claimsSet = getAuthTokenClaims(tokenId, accessToken).claim("access_token", null).build(); + + var signedAuthToken = new SignedJWT(jwsHeader, claimsSet); + signedAuthToken.sign(CryptoConverter.createSigner(consumerKey)); + var tokenResponse = tokenRefreshService.refreshToken(edr.getAdditional().get("refreshToken").toString(), signedAuthToken.serialize()); + + assertThat(tokenResponse).isFailed() + .detail() + .isEqualTo("Required claim 'access_token' not present on token."); + } + + private JWTClaimsSet.Builder getAuthTokenClaims(String tokenId, String accessToken) { + return new JWTClaimsSet.Builder() + .jwtID(tokenId) + .issuer(CONSUMER_DID) + .subject(CONSUMER_DID) + .audience(PROVIDER_DID) + .claim("access_token", accessToken); + } + + private TokenParameters tokenParams(String id) { + return TokenParameters.Builder.newInstance() + .claims(JwtRegisteredClaimNames.JWT_ID, id) + .claims(JwtRegisteredClaimNames.AUDIENCE, CONSUMER_BPN) + .claims(JwtRegisteredClaimNames.ISSUER, PROVIDER_BPN) + .claims(JwtRegisteredClaimNames.SUBJECT, PROVIDER_BPN) + .claims(JwtRegisteredClaimNames.ISSUED_AT, Instant.now().toEpochMilli()) // todo: milli or second? + .claims(CLAIM_AGREEMENT_ID, "test-agreement-id") + .claims(CLAIM_ASSET_ID, "test-asset-id") + .claims(CLAIM_PROCESS_ID, "test-process-id") + .claims(CLAIM_FLOW_TYPE, FlowType.PULL.toString()) + .build(); + } + + private Map asClaims(String serializedJwt) { + try { + var jwt = SignedJWT.parse(serializedJwt); + return jwt.getJWTClaimsSet().getClaims(); + } catch (ParseException e) { + throw new RuntimeException(e); + } + } +} \ No newline at end of file diff --git a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImplTest.java b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImplTest.java new file mode 100644 index 000000000..7b2a6f34b --- /dev/null +++ b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImplTest.java @@ -0,0 +1,292 @@ +/* + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.eclipse.tractusx.edc.dataplane.tokenrefresh.core; + +import org.eclipse.edc.connector.dataplane.spi.AccessTokenData; +import org.eclipse.edc.connector.dataplane.spi.store.AccessTokenDataStore; +import org.eclipse.edc.iam.did.spi.resolution.DidPublicKeyResolver; +import org.eclipse.edc.spi.iam.ClaimToken; +import org.eclipse.edc.spi.iam.TokenParameters; +import org.eclipse.edc.spi.iam.TokenRepresentation; +import org.eclipse.edc.spi.result.Result; +import org.eclipse.edc.spi.result.StoreResult; +import org.eclipse.edc.spi.types.domain.DataAddress; +import org.eclipse.edc.token.spi.TokenDecorator; +import org.eclipse.edc.token.spi.TokenGenerationService; +import org.eclipse.edc.token.spi.TokenValidationService; +import org.junit.jupiter.api.Test; + +import java.util.Map; +import java.util.regex.Pattern; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.eclipse.edc.junit.assertions.AbstractResultAssert.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyList; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.argThat; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoInteractions; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.when; + +class DataPlaneTokenRefreshServiceImplTest { + private static final Pattern UUID_PATTERN = Pattern.compile("^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$"); + private final AccessTokenDataStore accessTokenDataStore = mock(); + private final TokenGenerationService tokenGenService = mock(); + private final TokenValidationService tokenValidationService = mock(); + private final DidPublicKeyResolver didPublicKeyResolver = mock(); + + private final DataPlaneTokenRefreshServiceImpl accessTokenService = new DataPlaneTokenRefreshServiceImpl(tokenValidationService, didPublicKeyResolver, accessTokenDataStore, tokenGenService, mock(), mock(), "https://example.com"); + + @Test + void obtainToken() { + var params = TokenParameters.Builder.newInstance().claims("foo", "bar").claims("jti", "baz").header("qux", "quz").build(); + var address = DataAddress.Builder.newInstance().type("test-type").build(); + + when(tokenGenService.generate(any(), any(TokenDecorator[].class))).thenReturn(Result.success(TokenRepresentation.Builder.newInstance().token("foo-token").build())); + when(accessTokenDataStore.store(any(AccessTokenData.class))).thenReturn(StoreResult.success()); + + var result = accessTokenService.obtainToken(params, address, Map.of("fizz", "buzz", "refreshToken", "getsOverwritten")); + assertThat(result).isSucceeded().extracting(TokenRepresentation::getToken).isEqualTo("foo-token"); + assertThat(result.getContent().getAdditional()) + .containsKeys("fizz", "refreshToken", "expiresIn", "refreshEndpoint") + .containsEntry("refreshToken", "foo-token"); + + verify(tokenGenService, times(2)).generate(any(), any(TokenDecorator[].class)); + verify(accessTokenDataStore).store(any(AccessTokenData.class)); + } + + @Test + void obtainToken_withAdditionalProperties() { + var params = TokenParameters.Builder.newInstance().claims("foo", "bar").claims("jti", "baz").header("qux", "quz").build(); + var address = DataAddress.Builder.newInstance().type("test-type").build(); + + when(tokenGenService.generate(any(), any(TokenDecorator[].class))).thenReturn(Result.success(TokenRepresentation.Builder.newInstance().token("foo-token").build())); + when(accessTokenDataStore.store(any(AccessTokenData.class))).thenReturn(StoreResult.success()); + + var result = accessTokenService.obtainToken(params, address, Map.of("foo", "bar")); + assertThat(result).isSucceeded().extracting(TokenRepresentation::getToken).isEqualTo("foo-token"); + + verify(tokenGenService, times(2)).generate(any(), any(TokenDecorator[].class)); + verify(accessTokenDataStore).store(argThat(accessTokenData -> accessTokenData.additionalProperties().get("foo").equals("bar"))); + } + + @Test + void obtainToken_invalidParams() { + assertThatThrownBy(() -> accessTokenService.obtainToken(null, DataAddress.Builder.newInstance().type("foo").build(), Map.of())) + .isInstanceOf(NullPointerException.class); + assertThatThrownBy(() -> accessTokenService.obtainToken(TokenParameters.Builder.newInstance().build(), null, Map.of())) + .isInstanceOf(NullPointerException.class); + + } + + @Test + void obtainToken_noTokenId() { + var params = TokenParameters.Builder.newInstance().claims("foo", "bar")/* missing: .claims("jti", "baz")*/.header("qux", "quz").build(); + var address = DataAddress.Builder.newInstance().type("test-type").build(); + + when(tokenGenService.generate(any(), any(TokenDecorator[].class))).thenReturn(Result.success(TokenRepresentation.Builder.newInstance().token("foo-token").build())); + when(accessTokenDataStore.store(any(AccessTokenData.class))).thenReturn(StoreResult.success()); + + var result = accessTokenService.obtainToken(params, address, Map.of()); + assertThat(result).isSucceeded().extracting(TokenRepresentation::getToken).isEqualTo("foo-token"); + + verify(tokenGenService, times(2)).generate(any(), any(TokenDecorator[].class)); + verify(accessTokenDataStore).store(argThat(accessTokenData -> UUID_PATTERN.matcher(accessTokenData.id()).matches())); + } + + @Test + void obtainToken_creationFails() { + var params = TokenParameters.Builder.newInstance().claims("foo", "bar").claims("jti", "baz").header("qux", "quz").build(); + var address = DataAddress.Builder.newInstance().type("test-type").build(); + + when(tokenGenService.generate(any(), any(TokenDecorator[].class))).thenReturn(Result.failure("test failure")); + + var result = accessTokenService.obtainToken(params, address, Map.of()); + assertThat(result).isFailed().detail().contains("test failure"); + + verify(tokenGenService).generate(any(), any(TokenDecorator[].class)); + verifyNoMoreInteractions(accessTokenDataStore); + } + + @Test + void obtainToken_storingFails() { + var params = TokenParameters.Builder.newInstance().claims("foo", "bar").claims("jti", "baz").header("qux", "quz").build(); + var address = DataAddress.Builder.newInstance().type("test-type").build(); + + when(tokenGenService.generate(any(), any(TokenDecorator[].class))).thenReturn(Result.success(TokenRepresentation.Builder.newInstance().token("foo-token").build())); + when(accessTokenDataStore.store(any(AccessTokenData.class))).thenReturn(StoreResult.alreadyExists("test failure")); + + var result = accessTokenService.obtainToken(params, address, Map.of()); + assertThat(result).isFailed().detail().isEqualTo("test failure"); + + verify(tokenGenService, times(2)).generate(any(), any(TokenDecorator[].class)); + verify(accessTokenDataStore).store(any(AccessTokenData.class)); + } + + @Test + void resolve() { + var tokenId = "test-id"; + var claimToken = ClaimToken.Builder.newInstance().claim("jti", tokenId).build(); + when(tokenValidationService.validate(anyString(), any(), anyList())) + .thenReturn(Result.success(claimToken)); + when(accessTokenDataStore.getById(eq(tokenId))).thenReturn(new AccessTokenData(tokenId, ClaimToken.Builder.newInstance().build(), + DataAddress.Builder.newInstance().type("test-type").build())); + + var result = accessTokenService.resolve("some-jwt"); + assertThat(result).isSucceeded() + .satisfies(atd -> assertThat(atd.id()).isEqualTo(tokenId)); + verify(tokenValidationService).validate(eq("some-jwt"), any(), anyList()); + verify(accessTokenDataStore).getById(eq(tokenId)); + } + + @Test + void resolve_whenValidationFails() { + var tokenId = "test-id"; + var claimToken = ClaimToken.Builder.newInstance().claim("jti", tokenId).build(); + when(tokenValidationService.validate(anyString(), any(), anyList())) + .thenReturn(Result.failure("test-failure")); + + var result = accessTokenService.resolve("some-jwt"); + assertThat(result).isFailed() + .detail().isEqualTo("test-failure"); + verify(tokenValidationService).validate(eq("some-jwt"), any(), anyList()); + verifyNoInteractions(accessTokenDataStore); + } + + @Test + void resolve_whenTokenIdNotFound() { + var tokenId = "test-id"; + var claimToken = ClaimToken.Builder.newInstance().claim("jti", tokenId).build(); + when(tokenValidationService.validate(anyString(), any(), anyList())) + .thenReturn(Result.success(claimToken)); + when(accessTokenDataStore.getById(eq(tokenId))).thenReturn(null); + + var result = accessTokenService.resolve("some-jwt"); + assertThat(result).isFailed() + .detail().isEqualTo("AccessTokenData with ID 'test-id' does not exist."); + verify(tokenValidationService).validate(eq("some-jwt"), any(), anyList()); + verify(accessTokenDataStore).getById(eq(tokenId)); + } + + @Test + void refresh_whenAccessTokenDataNotResolved() { + var accessToken = "foo-bar"; + var refreshToken = "fizz-buzz"; + when(tokenValidationService.validate(eq(accessToken), any(), anyList())) + .thenReturn(Result.failure("test-failure")); + + assertThat(accessTokenService.refreshToken(refreshToken, accessToken)) + .isFailed() + .detail() + .isEqualTo("test-failure"); + + verify(tokenValidationService).validate(eq(accessToken), any(), anyList()); + verifyNoMoreInteractions(tokenValidationService, tokenGenService, didPublicKeyResolver, accessTokenDataStore); + } + + @Test + void refresh_whenRegeneratingTokenFails() { + var accessToken = "foo-bar"; + var refreshToken = "fizz-buzz"; + var tokenId = "token-id"; + when(tokenValidationService.validate(eq(accessToken), any(), anyList())) + .thenReturn(Result.success(ClaimToken.Builder.newInstance().claim("jti", tokenId).build())); + + when(accessTokenDataStore.getById(eq(tokenId))).thenReturn(new AccessTokenData(tokenId, ClaimToken.Builder.newInstance().claim("claim1", "value1").build(), + DataAddress.Builder.newInstance().type("type").build(), Map.of("fizz", "buzz"))); + + when(tokenGenService.generate(any(), any(TokenDecorator[].class))).thenReturn(Result.failure("generator-failure")); + + + assertThat(accessTokenService.refreshToken(refreshToken, accessToken)) + .isFailed() + .detail() + .startsWith("Failed to regenerate access/refresh token pair: "); + + verify(tokenValidationService).validate(eq(accessToken), any(), anyList()); + verify(accessTokenDataStore).getById(tokenId); + verify(tokenGenService, times(2)).generate(any(), any(TokenDecorator[].class)); + verifyNoMoreInteractions(tokenValidationService, tokenGenService, didPublicKeyResolver, accessTokenDataStore); + } + + @Test + void refresh_whenStoreFails() { + var accessToken = "foo-bar"; + var refreshToken = "fizz-buzz"; + var tokenId = "token-id"; + when(tokenValidationService.validate(eq(accessToken), any(), anyList())) + .thenReturn(Result.success(ClaimToken.Builder.newInstance().claim("jti", tokenId).build())); + + when(accessTokenDataStore.getById(eq(tokenId))).thenReturn(new AccessTokenData(tokenId, ClaimToken.Builder.newInstance().claim("claim1", "value1").build(), + DataAddress.Builder.newInstance().type("type").build(), Map.of("fizz", "buzz"))); + + when(tokenGenService.generate(any(), any(TokenDecorator[].class))).thenReturn(Result.success(TokenRepresentation.Builder.newInstance().build())); + + when(accessTokenDataStore.update(any())).thenReturn(StoreResult.alreadyExists("test-failure")); + + assertThat(accessTokenService.refreshToken(refreshToken, accessToken)) + .isFailed() + .detail() + .startsWith("test-failure"); + + verify(tokenValidationService).validate(eq(accessToken), any(), anyList()); + verify(accessTokenDataStore).getById(tokenId); + verify(tokenGenService, times(2)).generate(any(), any(TokenDecorator[].class)); + verify(accessTokenDataStore).update(any()); + verifyNoMoreInteractions(tokenValidationService, tokenGenService, didPublicKeyResolver, accessTokenDataStore); + } + + @Test + void refresh_successful() { + var accessToken = "foo-bar"; + var refreshToken = "fizz-buzz"; + var tokenId = "token-id"; + when(tokenValidationService.validate(eq(accessToken), any(), anyList())) + .thenReturn(Result.success(ClaimToken.Builder.newInstance().claim("jti", tokenId).build())); + + when(accessTokenDataStore.getById(eq(tokenId))).thenReturn(new AccessTokenData(tokenId, ClaimToken.Builder.newInstance().claim("claim1", "value1").build(), + DataAddress.Builder.newInstance().type("type").build(), Map.of("fizz", "buzz"))); + + when(tokenGenService.generate(any(), any(TokenDecorator[].class))) + .thenReturn(Result.success(TokenRepresentation.Builder.newInstance().token("fizz-token").build())) + .thenReturn(Result.success(TokenRepresentation.Builder.newInstance().token("buzz-token").build())); + + when(accessTokenDataStore.update(any())).thenReturn(StoreResult.success()); + + assertThat(accessTokenService.refreshToken(refreshToken, accessToken)) + .isSucceeded() + .satisfies(tr -> { + assertThat(tr.accessToken()).isEqualTo("fizz-token"); + assertThat(tr.refreshToken()).isEqualTo("buzz-token"); + }); + + verify(tokenValidationService).validate(eq(accessToken), any(), anyList()); + verify(accessTokenDataStore).getById(tokenId); + verify(tokenGenService, times(2)).generate(any(), any(TokenDecorator[].class)); + verify(accessTokenDataStore).update(any()); + verifyNoMoreInteractions(tokenValidationService, tokenGenService, didPublicKeyResolver, accessTokenDataStore); + } +} \ No newline at end of file diff --git a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/rules/ClaimIsPresentRuleTest.java b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/rules/ClaimIsPresentRuleTest.java new file mode 100644 index 000000000..741938653 --- /dev/null +++ b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/rules/ClaimIsPresentRuleTest.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.eclipse.tractusx.edc.dataplane.tokenrefresh.core.rules; + +import org.eclipse.edc.spi.iam.ClaimToken; +import org.junit.jupiter.api.Test; + +import static org.eclipse.edc.junit.assertions.AbstractResultAssert.assertThat; + + +class ClaimIsPresentRuleTest { + @Test + void checkRule_whenPresent() { + var claimToken = ClaimToken.Builder.newInstance().claim("foo", "bar").build(); + assertThat(new ClaimIsPresentRule("foo").checkRule(claimToken, null)).isSucceeded(); + } + + @Test + void checkRule_whenNotPresent() { + var claimToken = ClaimToken.Builder.newInstance().build(); + assertThat(new ClaimIsPresentRule("foo").checkRule(claimToken, null)).isFailed() + .detail().isEqualTo("Required claim 'foo' not present on token."); + } + +} \ No newline at end of file diff --git a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/rules/RefreshTokenMustExistRuleTest.java b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/rules/RefreshTokenMustExistRuleTest.java new file mode 100644 index 000000000..e3e50d04e --- /dev/null +++ b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/rules/RefreshTokenMustExistRuleTest.java @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.eclipse.tractusx.edc.dataplane.tokenrefresh.core.rules; + +import org.eclipse.edc.connector.dataplane.spi.AccessTokenData; +import org.eclipse.edc.connector.dataplane.spi.store.AccessTokenDataStore; +import org.eclipse.edc.spi.iam.ClaimToken; +import org.eclipse.edc.spi.types.domain.DataAddress; +import org.junit.jupiter.api.Test; + +import java.util.Map; + +import static org.eclipse.edc.junit.assertions.AbstractResultAssert.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +class RefreshTokenMustExistRuleTest { + + private static final String TEST_TOKEN_ID = "test-jti"; + private static final String TEST_REFRESH_TOKEN = "test-refresh-token"; + private final AccessTokenDataStore accessTokenData = mock(); + private final RefreshTokenMustExistRule rule = new RefreshTokenMustExistRule(accessTokenData, TEST_REFRESH_TOKEN); + + @Test + void checkRule_noAccessTokenDataEntryFound() { + when(accessTokenData.getById(TEST_TOKEN_ID)).thenReturn(null); + + assertThat(rule.checkRule(createToken(), Map.of())) + .isFailed() + .detail() + .isEqualTo("No AccessTokenData entry found for token-ID '%s'.".formatted(TEST_TOKEN_ID)); + } + + @Test + void checkRule_noRefreshTokenStored() { + when(accessTokenData.getById(TEST_TOKEN_ID)).thenReturn(new AccessTokenData(TEST_TOKEN_ID, + ClaimToken.Builder.newInstance().build(), + DataAddress.Builder.newInstance().type("test-type").build(), + Map.of("foo", "var"))); + + assertThat(rule.checkRule(createToken(), Map.of())) + .isFailed() + .detail() + .isEqualTo("Property 'refreshToken' expected to be String but was null"); + } + + @Test + void checkRule_refreshTokenNotString() { + when(accessTokenData.getById(TEST_TOKEN_ID)).thenReturn(new AccessTokenData(TEST_TOKEN_ID, + ClaimToken.Builder.newInstance().build(), + DataAddress.Builder.newInstance().type("test-type").build(), + Map.of("refreshToken", 42L))); + + assertThat(rule.checkRule(createToken(), Map.of())) + .isFailed() + .detail() + .isEqualTo("Property 'refreshToken' expected to be String but was class java.lang.Long"); + } + + @Test + void checkRule_refreshTokenDoesNotMatch() { + when(accessTokenData.getById(TEST_TOKEN_ID)).thenReturn(new AccessTokenData(TEST_TOKEN_ID, + ClaimToken.Builder.newInstance().build(), + DataAddress.Builder.newInstance().type("test-type").build(), + Map.of("refreshToken", "this-is-not-equal"))); + + assertThat(rule.checkRule(createToken(), Map.of())) + .isFailed() + .detail() + .isEqualTo("Provided refresh token does not match the stored refresh token."); + } + + @Test + void checkRule_issuerDoesNotMatchAudience() { + when(accessTokenData.getById(TEST_TOKEN_ID)).thenReturn(new AccessTokenData(TEST_TOKEN_ID, + ClaimToken.Builder.newInstance().build(), + DataAddress.Builder.newInstance().type("test-type").build(), + Map.of("refreshToken", TEST_REFRESH_TOKEN, "audience", "did:web:alice"))); + + assertThat(rule.checkRule(createToken(), Map.of())) + .isFailed() + .detail() + .isEqualTo("Principal 'did:web:bob' is not authorized to refresh this token."); + } + + @Test + void checkRule_success() { + when(accessTokenData.getById(TEST_TOKEN_ID)).thenReturn(new AccessTokenData(TEST_TOKEN_ID, + ClaimToken.Builder.newInstance().build(), + DataAddress.Builder.newInstance().type("test-type").build(), + Map.of("refreshToken", TEST_REFRESH_TOKEN, "audience", "did:web:bob"))); + + assertThat(rule.checkRule(createToken(), Map.of())) + .isSucceeded(); + } + + private ClaimToken createToken() { + return ClaimToken.Builder.newInstance() + .claim("access_token", "test-access-token") + .claim("jti", TEST_TOKEN_ID) + .claim("iss", "did:web:bob") + .build(); + } +} \ No newline at end of file diff --git a/edc-extensions/edr/edr-api/src/main/java/org/eclipse/tractusx/edc/api/edr/EdrApiExtension.java b/edc-extensions/edr/edr-api/src/main/java/org/eclipse/tractusx/edc/api/edr/EdrApiExtension.java index 0e42b6ee4..2eb9cdd9b 100644 --- a/edc-extensions/edr/edr-api/src/main/java/org/eclipse/tractusx/edc/api/edr/EdrApiExtension.java +++ b/edc-extensions/edr/edr-api/src/main/java/org/eclipse/tractusx/edc/api/edr/EdrApiExtension.java @@ -20,12 +20,12 @@ package org.eclipse.tractusx.edc.api.edr; import org.eclipse.edc.connector.api.management.configuration.ManagementApiConfiguration; -import org.eclipse.edc.connector.api.management.configuration.transform.ManagementApiTypeTransformerRegistry; import org.eclipse.edc.jsonld.spi.JsonLd; import org.eclipse.edc.runtime.metamodel.annotation.Inject; import org.eclipse.edc.spi.monitor.Monitor; import org.eclipse.edc.spi.system.ServiceExtension; import org.eclipse.edc.spi.system.ServiceExtensionContext; +import org.eclipse.edc.transform.spi.TypeTransformerRegistry; import org.eclipse.edc.validator.spi.JsonObjectValidatorRegistry; import org.eclipse.edc.web.spi.WebService; import org.eclipse.tractusx.edc.api.edr.transform.EndpointDataReferenceToDataAddressTransformer; @@ -50,7 +50,7 @@ public class EdrApiExtension implements ServiceExtension { private EdrService edrService; @Inject - private ManagementApiTypeTransformerRegistry transformerRegistry; + private TypeTransformerRegistry transformerRegistry; @Inject private JsonLd jsonLdService; @@ -64,11 +64,12 @@ public class EdrApiExtension implements ServiceExtension { @Override public void initialize(ServiceExtensionContext context) { jsonLdService.registerNamespace(TX_PREFIX, TX_NAMESPACE); - transformerRegistry.register(new NegotiateEdrRequestDtoToNegotiatedEdrRequestTransformer()); - transformerRegistry.register(new JsonObjectToNegotiateEdrRequestDtoTransformer()); - transformerRegistry.register(new JsonObjectFromEndpointDataReferenceEntryTransformer()); - transformerRegistry.register(new EndpointDataReferenceToDataAddressTransformer()); + var mgmtApiTransformerRegistry = transformerRegistry.forContext("management-api"); + mgmtApiTransformerRegistry.register(new NegotiateEdrRequestDtoToNegotiatedEdrRequestTransformer()); + mgmtApiTransformerRegistry.register(new JsonObjectToNegotiateEdrRequestDtoTransformer()); + mgmtApiTransformerRegistry.register(new JsonObjectFromEndpointDataReferenceEntryTransformer()); + mgmtApiTransformerRegistry.register(new EndpointDataReferenceToDataAddressTransformer()); validatorRegistry.register(EDR_REQUEST_DTO_TYPE, NegotiateEdrRequestDtoValidator.instance()); - webService.registerResource(apiConfig.getContextAlias(), new EdrController(edrService, transformerRegistry, validatorRegistry, monitor)); + webService.registerResource(apiConfig.getContextAlias(), new EdrController(edrService, mgmtApiTransformerRegistry, validatorRegistry, monitor)); } } diff --git a/edc-extensions/edr/edr-api/src/main/java/org/eclipse/tractusx/edc/api/edr/EdrController.java b/edc-extensions/edr/edr-api/src/main/java/org/eclipse/tractusx/edc/api/edr/EdrController.java index 8b2fecf37..c3a270393 100644 --- a/edc-extensions/edr/edr-api/src/main/java/org/eclipse/tractusx/edc/api/edr/EdrController.java +++ b/edc-extensions/edr/edr-api/src/main/java/org/eclipse/tractusx/edc/api/edr/EdrController.java @@ -31,7 +31,6 @@ import jakarta.ws.rs.QueryParam; import jakarta.ws.rs.core.MediaType; import org.eclipse.edc.api.model.IdResponse; -import org.eclipse.edc.connector.api.management.configuration.transform.ManagementApiTypeTransformerRegistry; import org.eclipse.edc.spi.EdcException; import org.eclipse.edc.spi.monitor.Monitor; import org.eclipse.edc.spi.query.Criterion; @@ -39,6 +38,7 @@ import org.eclipse.edc.spi.result.Result; import org.eclipse.edc.spi.types.domain.DataAddress; import org.eclipse.edc.spi.types.domain.edr.EndpointDataReference; +import org.eclipse.edc.transform.spi.TypeTransformerRegistry; import org.eclipse.edc.validator.spi.JsonObjectValidatorRegistry; import org.eclipse.edc.web.spi.exception.InvalidRequestException; import org.eclipse.edc.web.spi.exception.ValidationFailureException; @@ -61,11 +61,11 @@ public class EdrController implements EdrApi { private final EdrService edrService; - private final ManagementApiTypeTransformerRegistry transformerRegistry; + private final TypeTransformerRegistry transformerRegistry; private final JsonObjectValidatorRegistry validatorRegistry; private final Monitor monitor; - public EdrController(EdrService edrService, ManagementApiTypeTransformerRegistry transformerRegistry, + public EdrController(EdrService edrService, TypeTransformerRegistry transformerRegistry, JsonObjectValidatorRegistry validatorRegistry, Monitor monitor) { this.edrService = edrService; this.transformerRegistry = transformerRegistry; diff --git a/edc-extensions/edr/edr-api/src/test/java/org/eclipse/tractusx/edc/api/edr/EdrApiExtensionTest.java b/edc-extensions/edr/edr-api/src/test/java/org/eclipse/tractusx/edc/api/edr/EdrApiExtensionTest.java index ef2e3c4e9..69dfde64b 100644 --- a/edc-extensions/edr/edr-api/src/test/java/org/eclipse/tractusx/edc/api/edr/EdrApiExtensionTest.java +++ b/edc-extensions/edr/edr-api/src/test/java/org/eclipse/tractusx/edc/api/edr/EdrApiExtensionTest.java @@ -20,10 +20,10 @@ package org.eclipse.tractusx.edc.api.edr; import org.eclipse.edc.connector.api.management.configuration.ManagementApiConfiguration; -import org.eclipse.edc.connector.api.management.configuration.transform.ManagementApiTypeTransformerRegistry; import org.eclipse.edc.junit.extensions.DependencyInjectionExtension; import org.eclipse.edc.spi.system.ServiceExtensionContext; import org.eclipse.edc.spi.system.injection.ObjectFactory; +import org.eclipse.edc.transform.spi.TypeTransformerRegistry; import org.eclipse.edc.web.spi.WebService; import org.eclipse.tractusx.edc.api.edr.transform.JsonObjectFromEndpointDataReferenceEntryTransformer; import org.eclipse.tractusx.edc.api.edr.transform.JsonObjectToNegotiateEdrRequestDtoTransformer; @@ -41,14 +41,16 @@ @ExtendWith(DependencyInjectionExtension.class) public class EdrApiExtensionTest { - private final ManagementApiTypeTransformerRegistry transformerRegistry = mock(); + private final TypeTransformerRegistry transformerRegistry = mock(); private final WebService webService = mock(WebService.class); private final ManagementApiConfiguration configuration = mock(ManagementApiConfiguration.class); @BeforeEach void setUp(ObjectFactory factory, ServiceExtensionContext context) { context.registerService(WebService.class, webService); - context.registerService(ManagementApiTypeTransformerRegistry.class, transformerRegistry); + var rootRegistry = mock(TypeTransformerRegistry.class); + when(rootRegistry.forContext(eq("management-api"))).thenReturn(transformerRegistry); + context.registerService(TypeTransformerRegistry.class, rootRegistry); context.registerService(ManagementApiConfiguration.class, configuration); } diff --git a/edc-extensions/edr/edr-api/src/test/java/org/eclipse/tractusx/edc/api/edr/EdrControllerTest.java b/edc-extensions/edr/edr-api/src/test/java/org/eclipse/tractusx/edc/api/edr/EdrControllerTest.java index 5a99eeafd..90c815e4b 100644 --- a/edc-extensions/edr/edr-api/src/test/java/org/eclipse/tractusx/edc/api/edr/EdrControllerTest.java +++ b/edc-extensions/edr/edr-api/src/test/java/org/eclipse/tractusx/edc/api/edr/EdrControllerTest.java @@ -25,7 +25,6 @@ import jakarta.json.JsonObject; import jakarta.ws.rs.core.MediaType; import org.eclipse.edc.api.model.IdResponse; -import org.eclipse.edc.connector.api.management.configuration.transform.ManagementApiTypeTransformerRegistry; import org.eclipse.edc.connector.contract.spi.types.negotiation.ContractNegotiation; import org.eclipse.edc.jsonld.TitaniumJsonLd; import org.eclipse.edc.jsonld.spi.JsonLd; @@ -37,6 +36,7 @@ import org.eclipse.edc.spi.result.ServiceResult; import org.eclipse.edc.spi.types.domain.DataAddress; import org.eclipse.edc.spi.types.domain.edr.EndpointDataReference; +import org.eclipse.edc.transform.spi.TypeTransformerRegistry; import org.eclipse.edc.validator.spi.JsonObjectValidatorRegistry; import org.eclipse.edc.validator.spi.ValidationResult; import org.eclipse.edc.validator.spi.Violation; @@ -85,7 +85,7 @@ public class EdrControllerTest extends RestControllerTestBase { public static final String EDR_PATH = "/edrs"; private final JsonLd jsonLdService = new TitaniumJsonLd(monitor); EdrService edrService = mock(EdrService.class); - ManagementApiTypeTransformerRegistry transformerRegistry = mock(); + TypeTransformerRegistry transformerRegistry = mock(); JsonObjectValidatorRegistry validatorRegistry = mock(); @BeforeEach diff --git a/edc-extensions/provision-additional-headers/src/main/java/org/eclipse/tractusx/edc/provision/additionalheaders/AdditionalHeadersResourceDefinitionGenerator.java b/edc-extensions/provision-additional-headers/src/main/java/org/eclipse/tractusx/edc/provision/additionalheaders/AdditionalHeadersResourceDefinitionGenerator.java index b13f09fed..83838ac89 100644 --- a/edc-extensions/provision-additional-headers/src/main/java/org/eclipse/tractusx/edc/provision/additionalheaders/AdditionalHeadersResourceDefinitionGenerator.java +++ b/edc-extensions/provision-additional-headers/src/main/java/org/eclipse/tractusx/edc/provision/additionalheaders/AdditionalHeadersResourceDefinitionGenerator.java @@ -22,8 +22,8 @@ import org.eclipse.edc.connector.spi.contractagreement.ContractAgreementService; import org.eclipse.edc.connector.transfer.spi.provision.ProviderResourceDefinitionGenerator; -import org.eclipse.edc.connector.transfer.spi.types.DataRequest; import org.eclipse.edc.connector.transfer.spi.types.ResourceDefinition; +import org.eclipse.edc.connector.transfer.spi.types.TransferProcess; import org.eclipse.edc.policy.model.Policy; import org.eclipse.edc.spi.types.domain.DataAddress; import org.eclipse.edc.spi.types.domain.agreement.ContractAgreement; @@ -41,14 +41,8 @@ class AdditionalHeadersResourceDefinitionGenerator implements ProviderResourceDe } @Override - public boolean canGenerate(DataRequest dataRequest, DataAddress dataAddress, Policy policy) { - return "HttpData".equals(dataAddress.getType()); - } - - @Override - public @Nullable ResourceDefinition generate( - DataRequest dataRequest, DataAddress dataAddress, Policy policy) { - var bpn = Optional.of(dataRequest.getContractId()) + public @Nullable ResourceDefinition generate(TransferProcess transferProcess, DataAddress dataAddress, Policy policy) { + var bpn = Optional.of(transferProcess.getDataRequest().getContractId()) .map(contractAgreementService::findById) .map(ContractAgreement::getConsumerId) .orElse(null); @@ -56,8 +50,13 @@ public boolean canGenerate(DataRequest dataRequest, DataAddress dataAddress, Pol return AdditionalHeadersResourceDefinition.Builder.newInstance() .id(UUID.randomUUID().toString()) .dataAddress(dataAddress) - .contractId(dataRequest.getContractId()) + .contractId(transferProcess.getDataRequest().getContractId()) .bpn(bpn) .build(); } + + @Override + public boolean canGenerate(TransferProcess transferProcess, DataAddress dataAddress, Policy policy) { + return "HttpData".equals(dataAddress.getType()); + } } diff --git a/edc-extensions/provision-additional-headers/src/test/java/org/eclipse/tractusx/edc/provision/additionalheaders/AdditionalHeadersResourceDefinitionGeneratorTest.java b/edc-extensions/provision-additional-headers/src/test/java/org/eclipse/tractusx/edc/provision/additionalheaders/AdditionalHeadersResourceDefinitionGeneratorTest.java index f56480b36..22d42af87 100644 --- a/edc-extensions/provision-additional-headers/src/test/java/org/eclipse/tractusx/edc/provision/additionalheaders/AdditionalHeadersResourceDefinitionGeneratorTest.java +++ b/edc-extensions/provision-additional-headers/src/test/java/org/eclipse/tractusx/edc/provision/additionalheaders/AdditionalHeadersResourceDefinitionGeneratorTest.java @@ -24,6 +24,7 @@ import org.eclipse.edc.connector.spi.contractagreement.ContractAgreementService; import org.eclipse.edc.connector.transfer.spi.provision.ProviderResourceDefinitionGenerator; import org.eclipse.edc.connector.transfer.spi.types.DataRequest; +import org.eclipse.edc.connector.transfer.spi.types.TransferProcess; import org.eclipse.edc.policy.model.Policy; import org.eclipse.edc.spi.types.domain.DataAddress; import org.eclipse.edc.spi.types.domain.agreement.ContractAgreement; @@ -43,6 +44,16 @@ class AdditionalHeadersResourceDefinitionGeneratorTest { private final ContractAgreementService contractAgreementService = mock(); private final ProviderResourceDefinitionGenerator generator = new AdditionalHeadersResourceDefinitionGenerator(contractAgreementService); + private static ContractAgreement contractAgreementWithBpn(String bpn) { + return ContractAgreement.Builder.newInstance() + .id(UUID.randomUUID().toString()) + .consumerId(bpn) + .providerId("providerId") + .assetId("assetId") + .policy(Policy.Builder.newInstance().build()) + .build(); + } + @Test void canGenerate_shouldReturnFalseForNotHttpDataAddresses() { var dataAddress = DataAddress.Builder.newInstance().type("any").build(); @@ -52,8 +63,9 @@ void canGenerate_shouldReturnFalseForNotHttpDataAddresses() { .dataDestination(dataAddress) .build(); var build = Policy.Builder.newInstance().build(); + var transferProcess = TransferProcess.Builder.newInstance().dataRequest(dataRequest).build(); - var result = generator.canGenerate(dataRequest, dataAddress, build); + var result = generator.canGenerate(transferProcess, dataAddress, build); assertThat(result).isFalse(); } @@ -67,8 +79,9 @@ void canGenerate_shouldReturnTrueForHttpDataAddresses() { .dataDestination(dataAddress) .build(); var build = Policy.Builder.newInstance().build(); + var transferProcess = TransferProcess.Builder.newInstance().dataRequest(dataRequest).build(); - var result = generator.canGenerate(dataRequest, dataAddress, build); + var result = generator.canGenerate(transferProcess, dataAddress, build); assertThat(result).isTrue(); } @@ -84,8 +97,9 @@ void shouldCreateResourceDefinitionWithDataAddress() { .build(); var build = Policy.Builder.newInstance().build(); when(contractAgreementService.findById(any())).thenReturn(contractAgreementWithBpn("bpn")); + var transferProcess = TransferProcess.Builder.newInstance().dataRequest(dataRequest).build(); - var result = generator.generate(dataRequest, dataAddress, build); + var result = generator.generate(transferProcess, dataAddress, build); assertThat(result) .asInstanceOf(type(AdditionalHeadersResourceDefinition.class)) @@ -99,14 +113,4 @@ void shouldCreateResourceDefinitionWithDataAddress() { }); verify(contractAgreementService).findById("contractId"); } - - private static ContractAgreement contractAgreementWithBpn(String bpn) { - return ContractAgreement.Builder.newInstance() - .id(UUID.randomUUID().toString()) - .consumerId(bpn) - .providerId("providerId") - .assetId("assetId") - .policy(Policy.Builder.newInstance().build()) - .build(); - } } diff --git a/edc-extensions/transferprocess-sftp-provisioner/src/main/java/org/eclipse/tractusx/edc/transferprocess/sftp/provisioner/SftpProviderResourceDefinitionGenerator.java b/edc-extensions/transferprocess-sftp-provisioner/src/main/java/org/eclipse/tractusx/edc/transferprocess/sftp/provisioner/SftpProviderResourceDefinitionGenerator.java index 8f1748cfe..53de10d8c 100644 --- a/edc-extensions/transferprocess-sftp-provisioner/src/main/java/org/eclipse/tractusx/edc/transferprocess/sftp/provisioner/SftpProviderResourceDefinitionGenerator.java +++ b/edc-extensions/transferprocess-sftp-provisioner/src/main/java/org/eclipse/tractusx/edc/transferprocess/sftp/provisioner/SftpProviderResourceDefinitionGenerator.java @@ -20,8 +20,8 @@ package org.eclipse.tractusx.edc.transferprocess.sftp.provisioner; import org.eclipse.edc.connector.transfer.spi.provision.ProviderResourceDefinitionGenerator; -import org.eclipse.edc.connector.transfer.spi.types.DataRequest; import org.eclipse.edc.connector.transfer.spi.types.ResourceDefinition; +import org.eclipse.edc.connector.transfer.spi.types.TransferProcess; import org.eclipse.edc.policy.model.Policy; import org.eclipse.edc.spi.types.domain.DataAddress; import org.eclipse.tractusx.edc.transferprocess.sftp.common.EdcSftpException; @@ -32,7 +32,7 @@ public class SftpProviderResourceDefinitionGenerator implements ProviderResourceDefinitionGenerator { @Override - public @Nullable ResourceDefinition generate(DataRequest dataRequest, DataAddress assetAddress, Policy policy) { + public @Nullable ResourceDefinition generate(TransferProcess transferProcess, DataAddress assetAddress, Policy policy) { try { var sftpDataAddress = SftpDataAddress.fromDataAddress(assetAddress); return new SftpProviderResourceDefinition(NoOpSftpProvisioner.PROVIDER_TYPE, sftpDataAddress); @@ -42,7 +42,7 @@ public class SftpProviderResourceDefinitionGenerator implements ProviderResource } @Override - public boolean canGenerate(DataRequest dataRequest, DataAddress dataAddress, Policy policy) { + public boolean canGenerate(TransferProcess transferProcess, DataAddress dataAddress, Policy policy) { try { SftpDataAddress.fromDataAddress(dataAddress); } catch (EdcSftpException e) { diff --git a/edc-extensions/transferprocess-sftp-provisioner/src/test/java/org/eclipse/tractusx/edc/transferprocess/sftp/provisioner/SftpProviderResourceDefinitionGeneratorTest.java b/edc-extensions/transferprocess-sftp-provisioner/src/test/java/org/eclipse/tractusx/edc/transferprocess/sftp/provisioner/SftpProviderResourceDefinitionGeneratorTest.java index 7d997e007..7f8b0a126 100644 --- a/edc-extensions/transferprocess-sftp-provisioner/src/test/java/org/eclipse/tractusx/edc/transferprocess/sftp/provisioner/SftpProviderResourceDefinitionGeneratorTest.java +++ b/edc-extensions/transferprocess-sftp-provisioner/src/test/java/org/eclipse/tractusx/edc/transferprocess/sftp/provisioner/SftpProviderResourceDefinitionGeneratorTest.java @@ -22,6 +22,7 @@ import org.eclipse.edc.connector.transfer.spi.types.DataRequest; +import org.eclipse.edc.connector.transfer.spi.types.TransferProcess; import org.eclipse.edc.policy.model.Policy; import org.eclipse.edc.spi.types.domain.DataAddress; import org.eclipse.tractusx.edc.transferprocess.sftp.common.SftpDataAddress; @@ -70,8 +71,9 @@ void generate_successful() throws NoSuchAlgorithmException { final DataAddress dataAddress = SftpDataAddress.Builder.newInstance().sftpUser(sftpUser).sftpLocation(sftpLocation).build(); var policy = Policy.Builder.newInstance().build(); + var transferProcess = TransferProcess.Builder.newInstance().dataRequest(dataRequest).build(); var resourceDefinition = - (SftpProviderResourceDefinition) generator.generate(dataRequest, dataAddress, policy); + (SftpProviderResourceDefinition) generator.generate(transferProcess, dataAddress, policy); assertNotNull(resourceDefinition); var sftpDataAddress = resourceDefinition.getSftpDataAddress(); @@ -92,8 +94,10 @@ void generate_wrongDataAddressType() { var dataAddress = DataAddress.Builder.newInstance().type("wrong").build(); var policy = Policy.Builder.newInstance().build(); + var transferProcess = TransferProcess.Builder.newInstance().dataRequest(dataRequest).build(); + var resourceDefinition = - (SftpProviderResourceDefinition) generator.generate(dataRequest, dataAddress, policy); + (SftpProviderResourceDefinition) generator.generate(transferProcess, dataAddress, policy); assertNull(resourceDefinition); } diff --git a/edc-tests/edc-dataplane/edc-dataplane-proxy-e2e/build.gradle.kts b/edc-tests/edc-dataplane/edc-dataplane-proxy-e2e/build.gradle.kts index 7c4d4d89b..94280497f 100644 --- a/edc-tests/edc-dataplane/edc-dataplane-proxy-e2e/build.gradle.kts +++ b/edc-tests/edc-dataplane/edc-dataplane-proxy-e2e/build.gradle.kts @@ -34,9 +34,9 @@ dependencies { testRuntimeOnly(libs.edc.controlplane.apiclient) testImplementation(project(":spi:edr-spi")) testImplementation(project(":core:edr-cache-core")) - testImplementation(project(":edc-extensions:dataplane-proxy:edc-dataplane-proxy-consumer-api")) - testImplementation(project(":edc-extensions:dataplane-proxy:edc-dataplane-proxy-provider-api")) - testImplementation(project(":edc-extensions:dataplane-proxy:edc-dataplane-proxy-provider-core")) + testImplementation(project(":edc-extensions:dataplane:dataplane-proxy:edc-dataplane-proxy-consumer-api")) + testImplementation(project(":edc-extensions:dataplane:dataplane-proxy:edc-dataplane-proxy-provider-api")) + testImplementation(project(":edc-extensions:dataplane:dataplane-proxy:edc-dataplane-proxy-provider-core")) } diff --git a/edc-tests/edc-dataplane/edc-dataplane-tokenrefresh-tests/build.gradle.kts b/edc-tests/edc-dataplane/edc-dataplane-tokenrefresh-tests/build.gradle.kts new file mode 100644 index 000000000..57453561e --- /dev/null +++ b/edc-tests/edc-dataplane/edc-dataplane-tokenrefresh-tests/build.gradle.kts @@ -0,0 +1,35 @@ +/******************************************************************************** + * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +plugins { + `java-library` +} + +dependencies { + + testImplementation(project(":edc-tests:e2e-tests")) + testImplementation(libs.edc.junit) + testImplementation(libs.restAssured) + + testImplementation(libs.edc.dpf.http) + +} + + + diff --git a/edc-tests/edc-dataplane/edc-dataplane-tokenrefresh-tests/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/e2e/DataPlaneTokenRefreshEndToEndTest.java b/edc-tests/edc-dataplane/edc-dataplane-tokenrefresh-tests/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/e2e/DataPlaneTokenRefreshEndToEndTest.java new file mode 100644 index 000000000..2302d19b1 --- /dev/null +++ b/edc-tests/edc-dataplane/edc-dataplane-tokenrefresh-tests/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/e2e/DataPlaneTokenRefreshEndToEndTest.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.eclipse.tractusx.edc.dataplane.tokenrefresh.e2e; + +import org.eclipse.edc.junit.annotations.EndToEndTest; +import org.eclipse.edc.junit.extensions.EdcRuntimeExtension; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import static org.eclipse.edc.junit.testfixtures.TestUtils.getFreePort; + + +@EndToEndTest +public class DataPlaneTokenRefreshEndToEndTest { + private static final int PROVIDER_CONTROL_PORT = getFreePort(); // port of the control api + + @RegisterExtension + protected static final EdcRuntimeExtension DATAPLANE_RUNTIME = new EdcRuntimeExtension( + ":edc-tests:runtime:dataplane-cloud", + "Token-Refresh-Dataplane", + RuntimeConfig.baseConfig("/signaling", PROVIDER_CONTROL_PORT) + ); + + @Test + void foo() { + // will be used once the RefreshAPI is here as well + } +} diff --git a/edc-tests/edc-dataplane/edc-dataplane-tokenrefresh-tests/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/e2e/RuntimeConfig.java b/edc-tests/edc-dataplane/edc-dataplane-tokenrefresh-tests/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/e2e/RuntimeConfig.java new file mode 100644 index 000000000..a1ff0e1f5 --- /dev/null +++ b/edc-tests/edc-dataplane/edc-dataplane-tokenrefresh-tests/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/e2e/RuntimeConfig.java @@ -0,0 +1,51 @@ +/******************************************************************************** + * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +package org.eclipse.tractusx.edc.dataplane.tokenrefresh.e2e; + +import java.util.HashMap; +import java.util.Map; + +import static org.eclipse.edc.junit.testfixtures.TestUtils.getFreePort; + +/** + * Configuration baseline for Data-Plane e2e tests + */ +public class RuntimeConfig { + /** + * Configures the data plane token endpoint, and all relevant HTTP contexts + */ + public static Map baseConfig(String signalingPath, int signalingPort) { + return new HashMap<>() { + { + put("edc.dataplane.token.validation.endpoint", "http://token-validation.com"); + put("web.http.path", "/api"); + put("web.http.port", String.valueOf(getFreePort())); + put("web.http.public.path", "/public"); + put("web.http.public.port", String.valueOf(getFreePort())); + put("web.http.consumer.api.path", "/api/consumer"); + put("web.http.consumer.api.port", String.valueOf(getFreePort())); + put("web.http.signaling.path", signalingPath); + put("web.http.signaling.port", String.valueOf(signalingPort)); + } + }; + } + +} + diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index a6046fb4b..00f9f5d52 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -44,6 +44,7 @@ edc-spi-jsonld = { module = "org.eclipse.edc:json-ld-spi", version.ref = "edc" } edc-spi-jwt = { module = "org.eclipse.edc:jwt-spi", version.ref = "edc" } edc-spi-token = { module = "org.eclipse.edc:token-spi", version.ref = "edc" } edc-spi-transform = { module = "org.eclipse.edc:transform-spi", version.ref = "edc" } +edc-spi-identity-did = { module = "org.eclipse.edc:identity-did-spi", version.ref = "edc" } edc-token-core = { module = "org.eclipse.edc:token-core", version.ref = "edc" } edc-spi-oauth2 = { module = "org.eclipse.edc:oauth2-spi", version.ref = "edc" } edc-util = { module = "org.eclipse.edc:util", version.ref = "edc" } @@ -53,6 +54,7 @@ edc-config-filesystem = { module = "org.eclipse.edc:configuration-filesystem", v edc-jsonld = { module = "org.eclipse.edc:json-ld", version.ref = "edc" } edc-vault-filesystem = { module = "org.eclipse.edc:vault-filesystem", version.ref = "edc" } edc-vault-hashicorp = { module = "org.eclipse.edc:vault-hashicorp", version.ref = "edc" } +edc-common-crypto = { module = "org.eclipse.edc:crypto-common", version.ref = "edc" } edc-core-controlplane = { module = "org.eclipse.edc:control-plane-core", version.ref = "edc" } edc-core-connector = { module = "org.eclipse.edc:connector-core", version.ref = "edc" } edc-core-jetty = { module = "org.eclipse.edc:jetty-core", version.ref = "edc" } @@ -62,6 +64,7 @@ edc-core-policy-monitor = { module = "org.eclipse.edc:policy-monitor-core", vers edc-core-sql = { module = "org.eclipse.edc:sql-core", version.ref = "edc" } edc-core-validator = { module = "org.eclipse.edc:validator-core", version.ref = "edc" } edc-core-transform = { module = "org.eclipse.edc:transform-core", version.ref = "edc" } +edc-core-token = { module = "org.eclipse.edc:token-core", version.ref = "edc" } edc-statemachine = { module = "org.eclipse.edc:state-machine", version.ref = "edc" } edc-junit = { module = "org.eclipse.edc:junit", version.ref = "edc" } edc-api-management-config = { module = "org.eclipse.edc:management-api-configuration", version.ref = "edc" } @@ -115,6 +118,7 @@ edc-controlplane-callback-dispatcher-http = { module = "org.eclipse.edc:callback edc-identity-trust-spi = { module = "org.eclipse.edc:identity-trust-spi", version.ref = "edc" } edc-identity-core-trust = { module = "org.eclipse.edc:identity-trust-core", version.ref = "edc" } edc-identity-core-did = { module = "org.eclipse.edc:identity-did-core", version.ref = "edc" } + edc-identity-did-web = { module = "org.eclipse.edc:identity-did-web", version.ref = "edc" } edc-identity-vc-ldp = { module = "org.eclipse.edc:ldp-verifiable-credentials", version.ref = "edc" } edc-identity-vc-jwt = { module = "org.eclipse.edc:jwt-verifiable-credentials", version.ref = "edc" } @@ -158,6 +162,8 @@ edc-dpf-oauth2 = { module = "org.eclipse.edc:data-plane-http-oauth2", version.re edc-dpf-api-control = { module = "org.eclipse.edc:data-plane-control-api", version.ref = "edc" } edc-dpf-api-public = { module = "org.eclipse.edc:data-plane-public-api", version.ref = "edc" } +edc-dpf-api-signaling = { module = "org.eclipse.edc:data-plane-signaling-api", version.ref = "edc" } + # micrometer and other infra stuff edc-micrometer-core = { module = "org.eclipse.edc:micrometer-core", version.ref = "edc" } edc-micrometer-jersey = { module = "org.eclipse.edc:jersey-micrometer", version.ref = "edc" } diff --git a/resources/java.header b/resources/java.header index c099ca0e1..8ff72fff0 100644 --- a/resources/java.header +++ b/resources/java.header @@ -6,7 +6,7 @@ ^ \*$ ^ \* This program and the accompanying materials are made available under the$ ^ \* terms of the Apache License, Version 2.0 which is available at$ -^ \* https://www.apache.org/licenses/LICENSE\-2\.0\.$ +^ \* https\:\/\/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$ @@ -17,4 +17,4 @@ ^ \* SPDX-License-Identifier: Apache\-2\.0$ ^ \*+/$ ^$ -^package +package .* \ No newline at end of file diff --git a/settings.gradle.kts b/settings.gradle.kts index 3b4ed3422..5ede9eab1 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -24,6 +24,7 @@ include(":spi:callback-spi") include(":spi:edr-spi") include(":spi:core-spi") include(":spi:ssi-spi") +include(":spi:tokenrefresh-spi") // core modules @@ -32,14 +33,13 @@ include(":core:edr-core") include(":core:json-ld-core") include(":core:core-utils") - +// extensions - control plane include(":edc-extensions:bpn-validation") include(":edc-extensions:bpn-validation:bpn-validation-api") include(":edc-extensions:bpn-validation:bpn-validation-spi") include(":edc-extensions:bpn-validation:bpn-validation-core") include(":edc-extensions:bpn-validation:business-partner-store-sql") include(":edc-extensions:data-encryption") -include(":edc-extensions:dataplane-selector-configuration") include(":edc-extensions:postgresql-migration") include(":edc-extensions:provision-additional-headers") include(":edc-extensions:transferprocess-sftp-client") @@ -56,6 +56,14 @@ include(":edc-extensions:ssi:ssi-identity-extractor") include(":edc-extensions:iatp:tx-iatp") include(":edc-extensions:iatp:tx-iatp-sts-dim") +// extensions - data plane +include(":edc-extensions:dataplane:dataplane-proxy:edc-dataplane-proxy-consumer-api") +include(":edc-extensions:dataplane:dataplane-proxy:edc-dataplane-proxy-provider-spi") +include(":edc-extensions:dataplane:dataplane-proxy:edc-dataplane-proxy-provider-core") +include(":edc-extensions:dataplane:dataplane-proxy:edc-dataplane-proxy-provider-api") +include(":edc-extensions:dataplane:dataplane-selector-configuration") +include(":edc-extensions:dataplane:dataplane-token-refresh:token-refresh-core") + // test modules include(":edc-tests:e2e-tests") include(":edc-tests:miw-tests") @@ -70,6 +78,7 @@ include(":edc-tests:runtime:iatp:runtime-memory-iatp-dim-ih") include(":edc-tests:runtime:iatp:runtime-memory-sts") include(":edc-tests:runtime:iatp:iatp-extensions") include(":edc-tests:edc-dataplane:edc-dataplane-proxy-e2e") +include(":edc-tests:edc-dataplane:edc-dataplane-tokenrefresh-tests") include(":edc-tests:edc-dataplane:cloud-transfer-tests") // modules for controlplane artifacts @@ -84,10 +93,8 @@ include(":edc-dataplane") include(":edc-dataplane:edc-dataplane-azure-vault") include(":edc-dataplane:edc-dataplane-base") include(":edc-dataplane:edc-dataplane-hashicorp-vault") -include(":edc-extensions:dataplane-proxy:edc-dataplane-proxy-consumer-api") -include(":edc-extensions:dataplane-proxy:edc-dataplane-proxy-provider-spi") -include(":edc-extensions:dataplane-proxy:edc-dataplane-proxy-provider-core") -include(":edc-extensions:dataplane-proxy:edc-dataplane-proxy-provider-api") + + include(":samples:multi-tenancy") diff --git a/spi/tokenrefresh-spi/build.gradle.kts b/spi/tokenrefresh-spi/build.gradle.kts new file mode 100644 index 000000000..3560fe265 --- /dev/null +++ b/spi/tokenrefresh-spi/build.gradle.kts @@ -0,0 +1,28 @@ +/******************************************************************************** + * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +plugins { + `java-library` + `java-test-fixtures` +} + +dependencies { + implementation(libs.edc.spi.core) + implementation(libs.edc.spi.jwt) +} diff --git a/spi/tokenrefresh-spi/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/spi/DataPlaneTokenRefreshService.java b/spi/tokenrefresh-spi/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/spi/DataPlaneTokenRefreshService.java new file mode 100644 index 000000000..a5f855de3 --- /dev/null +++ b/spi/tokenrefresh-spi/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/spi/DataPlaneTokenRefreshService.java @@ -0,0 +1,37 @@ +/******************************************************************************** + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +package org.eclipse.tractusx.edc.dataplane.tokenrefresh.spi; + +import org.eclipse.edc.spi.result.Result; +import org.eclipse.tractusx.edc.dataplane.tokenrefresh.spi.model.TokenResponse; + +/** + * This service receives an incoming token refresh request, validates it and generates a new token pair (access token + refresh token). + */ +public interface DataPlaneTokenRefreshService { + /** + * Generates a new token pair (access and refresh token) based on an existing refresh token and access token. + * + * @param refreshToken The refresh token that was issued in the original/previous token request. + * @param authenticationToken A client authentication token + * @return A result that contains the new access and refresh token, or a failure. + */ + Result refreshToken(String refreshToken, String authenticationToken); +} diff --git a/spi/tokenrefresh-spi/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/spi/model/TokenResponse.java b/spi/tokenrefresh-spi/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/spi/model/TokenResponse.java new file mode 100644 index 000000000..cf64c5c23 --- /dev/null +++ b/spi/tokenrefresh-spi/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/spi/model/TokenResponse.java @@ -0,0 +1,28 @@ +/******************************************************************************** + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +package org.eclipse.tractusx.edc.dataplane.tokenrefresh.spi.model; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public record TokenResponse(@JsonProperty("access_token") String accessToken, + @JsonProperty("refresh_token") String refreshToken, + @JsonProperty("expires") Long expiresInSeconds, + @JsonProperty("token_type") String tokenType) { +} From 1ec3225cd2ba9a0677c46bd82828a4ce53996999 Mon Sep 17 00:00:00 2001 From: Dominic Reuter <78848280+domreuter@users.noreply.github.com> Date: Sat, 9 Mar 2024 10:51:00 +0100 Subject: [PATCH 043/100] docs(bpngroups): update supported operators (#1117) Co-authored-by: Dominic Reuter --- edc-extensions/bpn-validation/README.md | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/edc-extensions/bpn-validation/README.md b/edc-extensions/bpn-validation/README.md index 02abad765..b947e75f5 100644 --- a/edc-extensions/bpn-validation/README.md +++ b/edc-extensions/bpn-validation/README.md @@ -28,8 +28,15 @@ Both previously mentioned evaluation functions are bound to the following scopes This policy states, that a certain BPN must, may or must not be member of a certain group. Groups may be represented as scalar, or as comma-separated lists. For semantic expression, the following ODRL operators are -supported: `eq`, `neq`, `in`, `isAllOf`, `isAnyOf`, `isNoneOf`. The following example demonstrates a full JSON-LD -structure in expanded form, containing such a constraint. +supported: +- `eq` +- `neq` +- `isPartOf` +- `isAllOf` +- `isAnyOf` +- `isNoneOf` + +The following example demonstrates a full JSON-LD structure in expanded form, containing such a constraint. ### Example From d0f4b1180959e8fb30d0d1588316720c3387fe3d Mon Sep 17 00:00:00 2001 From: Enrico Risa Date: Mon, 11 Mar 2024 08:43:01 +0100 Subject: [PATCH 044/100] chore: fix compile error after upstream transformers refactor (#1118) * chore: fix compile error after upstream transformers refactor * chore: deps file --- DEPENDENCIES | 1 - .../test/java/org/eclipse/tractusx/edc/api/edr/EdrApiTest.java | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/DEPENDENCIES b/DEPENDENCIES index 60308d844..96b16bc1e 100644 --- a/DEPENDENCIES +++ b/DEPENDENCIES @@ -375,7 +375,6 @@ maven/mavencentral/org.eclipse.edc/transfer-process-store-sql/0.5.2-SNAPSHOT, Ap maven/mavencentral/org.eclipse.edc/transfer-pull-http-dynamic-receiver/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/transfer-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/transform-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/transform-dspace/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/transform-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/util/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/validator-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc diff --git a/edc-extensions/edr/edr-api/src/test/java/org/eclipse/tractusx/edc/api/edr/EdrApiTest.java b/edc-extensions/edr/edr-api/src/test/java/org/eclipse/tractusx/edc/api/edr/EdrApiTest.java index cf29fd7d8..6649d669a 100644 --- a/edc-extensions/edr/edr-api/src/test/java/org/eclipse/tractusx/edc/api/edr/EdrApiTest.java +++ b/edc-extensions/edr/edr-api/src/test/java/org/eclipse/tractusx/edc/api/edr/EdrApiTest.java @@ -26,7 +26,7 @@ import org.eclipse.edc.connector.api.management.contractnegotiation.transform.JsonObjectToContractOfferDescriptionTransformer; import org.eclipse.edc.connector.api.management.contractnegotiation.transform.JsonObjectToContractRequestTransformer; import org.eclipse.edc.core.transform.TypeTransformerRegistryImpl; -import org.eclipse.edc.core.transform.transformer.OdrlTransformersFactory; +import org.eclipse.edc.core.transform.transformer.odrl.OdrlTransformersFactory; import org.eclipse.edc.jsonld.JsonLdExtension; import org.eclipse.edc.jsonld.spi.JsonLd; import org.eclipse.edc.jsonld.util.JacksonJsonLd; From a80c97ca5c112dc6b5eeb9aec5bf3b358dab3205 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 Mar 2024 08:56:06 +0100 Subject: [PATCH 045/100] chore(deps): bump com.azure:azure-identity from 1.11.2 to 1.11.3 (#1092) * chore(deps): bump com.azure:azure-identity from 1.11.2 to 1.11.3 Bumps [com.azure:azure-identity](https://github.com/Azure/azure-sdk-for-java) from 1.11.2 to 1.11.3. - [Release notes](https://github.com/Azure/azure-sdk-for-java/releases) - [Commits](https://github.com/Azure/azure-sdk-for-java/compare/azure-identity_1.11.2...azure-identity_1.11.3) --- updated-dependencies: - dependency-name: com.azure:azure-identity dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] * fix package import --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Paul Latzelsperger --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 00f9f5d52..3f07c355b 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -7,7 +7,7 @@ apache-sshd = "2.12.1" assertj = "3.25.3" awaitility = "4.2.0" aws = "2.24.10" -azure-identity = "1.11.2" +azure-identity = "1.11.3" bouncyCastle-jdk18on = "1.77" flyway = "10.8.1" iron-vc = "0.11.0" From e7ad71752dd0aae6e575740ff00b563cb2ccb41a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 Mar 2024 10:26:02 +0100 Subject: [PATCH 046/100] chore(deps): bump com.apicatalog:iron-verifiable-credentials from 0.11.0 to 0.14.0 (#1093) * chore(deps): bump com.apicatalog:iron-verifiable-credentials Bumps [com.apicatalog:iron-verifiable-credentials](https://github.com/filip26/iron-verifiable-credentials) from 0.11.0 to 0.14.0. - [Release notes](https://github.com/filip26/iron-verifiable-credentials/releases) - [Commits](https://github.com/filip26/iron-verifiable-credentials/compare/v0.11.0...v0.14.0) --- updated-dependencies: - dependency-name: com.apicatalog:iron-verifiable-credentials dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * update java action, remove test verbosity --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Paul Latzelsperger --- .github/actions/setup-java/action.yml | 2 +- .github/workflows/verify.yaml | 8 ++++---- gradle/libs.versions.toml | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/actions/setup-java/action.yml b/.github/actions/setup-java/action.yml index 76fe240d4..bace6be67 100644 --- a/.github/actions/setup-java/action.yml +++ b/.github/actions/setup-java/action.yml @@ -26,7 +26,7 @@ runs: using: "composite" steps: - name: Setup JDK 17 - uses: actions/setup-java@v3.13.0 + uses: actions/setup-java@v4.1.0 with: java-version: '17' distribution: 'temurin' diff --git a/.github/workflows/verify.yaml b/.github/workflows/verify.yaml index c2d7ff1cd..736fdae41 100644 --- a/.github/workflows/verify.yaml +++ b/.github/workflows/verify.yaml @@ -119,7 +119,7 @@ jobs: - uses: ./.github/actions/setup-java - name: Run E2E tests - run: ./gradlew test -DincludeTags="EndToEndTest" -PverboseTest=true + run: ./gradlew test -DincludeTags="EndToEndTest" postgres-tests: runs-on: ubuntu-latest @@ -139,7 +139,7 @@ jobs: - uses: ./.github/actions/setup-java - name: Run Postgresql E2E tests - run: ./gradlew test -DincludeTags="PostgresqlIntegrationTest" -PverboseTest=true + run: ./gradlew test -DincludeTags="PostgresqlIntegrationTest" dataplane-tests: runs-on: ubuntu-latest @@ -182,9 +182,9 @@ jobs: - name: Run MIW Integration tests run: | - ./gradlew -p edc-tests/miw-tests test -DincludeTags="MiwIntegrationTest" -PverboseTest=true + ./gradlew -p edc-tests/miw-tests test -DincludeTags="MiwIntegrationTest" - name: Run SSI E2E tests run: | pwd ./gradlew compileJava compileTestJava - ./gradlew -p edc-tests/e2e-tests test -DincludeTags="MiwIntegrationTest" -PverboseTest=true + ./gradlew -p edc-tests/e2e-tests test -DincludeTags="MiwIntegrationTest" diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 3f07c355b..d9a7e7f0a 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -10,7 +10,7 @@ aws = "2.24.10" azure-identity = "1.11.3" bouncyCastle-jdk18on = "1.77" flyway = "10.8.1" -iron-vc = "0.11.0" +iron-vc = "0.14.0" jackson = "2.16.1" jakarta-json = "2.0.1" jupiter = "5.10.2" From 14b6786386f291b1e97690292f5f34ca23c98faf Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 Mar 2024 10:57:18 +0100 Subject: [PATCH 047/100] chore(deps): bump com.apicatalog:titanium-json-ld from 1.3.3 to 1.4.0 (#1094) Bumps [com.apicatalog:titanium-json-ld](https://github.com/filip26/titanium-json-ld) from 1.3.3 to 1.4.0. - [Release notes](https://github.com/filip26/titanium-json-ld/releases) - [Commits](https://github.com/filip26/titanium-json-ld/compare/v1.3.3...v1.4.0) --- updated-dependencies: - dependency-name: com.apicatalog:titanium-json-ld dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index d9a7e7f0a..d4787321b 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -23,7 +23,7 @@ rsApi = "3.1.0" slf4j = "2.0.12" testcontainers = "1.19.6" tink = "1.12.0" -titanium = "1.3.3" +titanium = "1.4.0" [libraries] edc-spi-catalog = { module = "org.eclipse.edc:catalog-spi", version.ref = "edc" } From e008e758a0423140fcfd107eb6c89a1cfbb384ac Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 Mar 2024 12:50:06 +0100 Subject: [PATCH 048/100] chore(deps): bump aws from 2.24.10 to 2.25.1 (#1095) * chore(deps): bump aws from 2.24.10 to 2.25.1 Bumps `aws` from 2.24.10 to 2.25.1. Updates `software.amazon.awssdk:s3` from 2.24.10 to 2.25.1 Updates `software.amazon.awssdk:s3-transfer-manager` from 2.24.10 to 2.25.1 --- updated-dependencies: - dependency-name: software.amazon.awssdk:s3 dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:s3-transfer-manager dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * chore: dependencies file --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Enrico Risa --- DEPENDENCIES | 39 +++++++++++++++++++++++++++++++++++++-- gradle/libs.versions.toml | 2 +- 2 files changed, 38 insertions(+), 3 deletions(-) diff --git a/DEPENDENCIES b/DEPENDENCIES index 96b16bc1e..f1fe1664d 100644 --- a/DEPENDENCIES +++ b/DEPENDENCIES @@ -105,35 +105,44 @@ maven/mavencentral/io.micrometer/micrometer-core/1.12.3, Apache-2.0 AND (Apache- maven/mavencentral/io.micrometer/micrometer-observation/1.12.3, Apache-2.0, approved, #11680 maven/mavencentral/io.netty/netty-buffer/4.1.100.Final, Apache-2.0, approved, CQ21842 maven/mavencentral/io.netty/netty-buffer/4.1.101.Final, Apache-2.0, approved, CQ21842 +maven/mavencentral/io.netty/netty-buffer/4.1.107.Final, Apache-2.0, approved, CQ21842 maven/mavencentral/io.netty/netty-codec-dns/4.1.101.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 maven/mavencentral/io.netty/netty-codec-http/4.1.100.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 maven/mavencentral/io.netty/netty-codec-http/4.1.101.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 +maven/mavencentral/io.netty/netty-codec-http/4.1.107.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 maven/mavencentral/io.netty/netty-codec-http2/4.1.100.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 maven/mavencentral/io.netty/netty-codec-http2/4.1.101.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 +maven/mavencentral/io.netty/netty-codec-http2/4.1.107.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 maven/mavencentral/io.netty/netty-codec-socks/4.1.101.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 maven/mavencentral/io.netty/netty-codec/4.1.100.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 maven/mavencentral/io.netty/netty-codec/4.1.101.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 +maven/mavencentral/io.netty/netty-codec/4.1.107.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 maven/mavencentral/io.netty/netty-common/4.1.100.Final, Apache-2.0 AND MIT AND CC0-1.0, approved, CQ21843 maven/mavencentral/io.netty/netty-common/4.1.101.Final, Apache-2.0 AND MIT AND CC0-1.0, approved, CQ21843 +maven/mavencentral/io.netty/netty-common/4.1.107.Final, Apache-2.0 AND MIT AND CC0-1.0, approved, CQ21843 maven/mavencentral/io.netty/netty-handler-proxy/4.1.101.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 maven/mavencentral/io.netty/netty-handler/4.1.100.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 maven/mavencentral/io.netty/netty-handler/4.1.101.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 +maven/mavencentral/io.netty/netty-handler/4.1.107.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 maven/mavencentral/io.netty/netty-resolver-dns-classes-macos/4.1.101.Final, Apache-2.0, approved, #6367 maven/mavencentral/io.netty/netty-resolver-dns-native-macos/4.1.101.Final, Apache-2.0, approved, #7004 maven/mavencentral/io.netty/netty-resolver-dns/4.1.101.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 maven/mavencentral/io.netty/netty-resolver/4.1.100.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 maven/mavencentral/io.netty/netty-resolver/4.1.101.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 +maven/mavencentral/io.netty/netty-resolver/4.1.107.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 maven/mavencentral/io.netty/netty-tcnative-boringssl-static/2.0.62.Final, Apache-2.0 OR LicenseRef-Public-Domain OR BSD-2-Clause OR MIT, approved, CQ15280 maven/mavencentral/io.netty/netty-tcnative-classes/2.0.62.Final, Apache-2.0, approved, clearlydefined maven/mavencentral/io.netty/netty-transport-classes-epoll/4.1.100.Final, Apache-2.0, approved, #6366 maven/mavencentral/io.netty/netty-transport-classes-epoll/4.1.101.Final, Apache-2.0, approved, #6366 +maven/mavencentral/io.netty/netty-transport-classes-epoll/4.1.107.Final, Apache-2.0, approved, #6366 maven/mavencentral/io.netty/netty-transport-classes-kqueue/4.1.101.Final, Apache-2.0, approved, #4107 maven/mavencentral/io.netty/netty-transport-native-epoll/4.1.101.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 maven/mavencentral/io.netty/netty-transport-native-kqueue/4.1.101.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 -maven/mavencentral/io.netty/netty-transport-native-unix-common/4.1.100.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 maven/mavencentral/io.netty/netty-transport-native-unix-common/4.1.101.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 +maven/mavencentral/io.netty/netty-transport-native-unix-common/4.1.107.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 maven/mavencentral/io.netty/netty-transport/4.1.100.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 maven/mavencentral/io.netty/netty-transport/4.1.101.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 +maven/mavencentral/io.netty/netty-transport/4.1.107.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 maven/mavencentral/io.opentelemetry.instrumentation/opentelemetry-instrumentation-annotations/1.32.0, Apache-2.0, approved, #11684 maven/mavencentral/io.opentelemetry/opentelemetry-api/1.32.0, Apache-2.0, approved, #11682 maven/mavencentral/io.opentelemetry/opentelemetry-context/1.32.0, Apache-2.0, approved, #11683 @@ -498,32 +507,58 @@ maven/mavencentral/org.xmlresolver/xmlresolver/5.2.2, Apache-2.0, approved, clea maven/mavencentral/org.yaml/snakeyaml/2.0, Apache-2.0 AND (Apache-2.0 OR BSD-3-Clause OR EPL-1.0 OR GPL-2.0-or-later OR LGPL-2.1-or-later), approved, #7275 maven/mavencentral/org.yaml/snakeyaml/2.2, Apache-2.0 AND (Apache-2.0 OR BSD-3-Clause OR EPL-1.0 OR GPL-2.0-or-later OR LGPL-2.1-or-later), approved, #10232 maven/mavencentral/software.amazon.awssdk/annotations/2.24.10, Apache-2.0, approved, #13251 +maven/mavencentral/software.amazon.awssdk/annotations/2.25.1, , restricted, clearlydefined maven/mavencentral/software.amazon.awssdk/apache-client/2.24.10, Apache-2.0, approved, #13257 +maven/mavencentral/software.amazon.awssdk/apache-client/2.25.1, , restricted, clearlydefined maven/mavencentral/software.amazon.awssdk/arns/2.24.10, Apache-2.0, approved, #13243 +maven/mavencentral/software.amazon.awssdk/arns/2.25.1, , restricted, clearlydefined maven/mavencentral/software.amazon.awssdk/auth/2.24.10, Apache-2.0, approved, #13256 +maven/mavencentral/software.amazon.awssdk/auth/2.25.1, , restricted, clearlydefined maven/mavencentral/software.amazon.awssdk/aws-core/2.24.10, Apache-2.0, approved, #13240 +maven/mavencentral/software.amazon.awssdk/aws-core/2.25.1, , restricted, clearlydefined maven/mavencentral/software.amazon.awssdk/aws-query-protocol/2.24.10, Apache-2.0, approved, #13262 +maven/mavencentral/software.amazon.awssdk/aws-query-protocol/2.25.1, , restricted, clearlydefined maven/mavencentral/software.amazon.awssdk/aws-xml-protocol/2.24.10, Apache-2.0, approved, #13247 +maven/mavencentral/software.amazon.awssdk/aws-xml-protocol/2.25.1, , restricted, clearlydefined maven/mavencentral/software.amazon.awssdk/checksums-spi/2.24.10, Apache-2.0, approved, #13245 +maven/mavencentral/software.amazon.awssdk/checksums-spi/2.25.1, , restricted, clearlydefined maven/mavencentral/software.amazon.awssdk/checksums/2.24.10, Apache-2.0, approved, #13242 +maven/mavencentral/software.amazon.awssdk/checksums/2.25.1, , restricted, clearlydefined maven/mavencentral/software.amazon.awssdk/crt-core/2.24.10, Apache-2.0, approved, #13252 +maven/mavencentral/software.amazon.awssdk/crt-core/2.25.1, , restricted, clearlydefined maven/mavencentral/software.amazon.awssdk/endpoints-spi/2.24.10, Apache-2.0, approved, #13246 +maven/mavencentral/software.amazon.awssdk/endpoints-spi/2.25.1, , restricted, clearlydefined maven/mavencentral/software.amazon.awssdk/http-auth-aws/2.24.10, Apache-2.0, approved, #13253 +maven/mavencentral/software.amazon.awssdk/http-auth-aws/2.25.1, , restricted, clearlydefined maven/mavencentral/software.amazon.awssdk/http-auth-spi/2.24.10, Apache-2.0, approved, #13264 +maven/mavencentral/software.amazon.awssdk/http-auth-spi/2.25.1, , restricted, clearlydefined maven/mavencentral/software.amazon.awssdk/http-auth/2.24.10, Apache-2.0, approved, #13248 +maven/mavencentral/software.amazon.awssdk/http-auth/2.25.1, , restricted, clearlydefined maven/mavencentral/software.amazon.awssdk/http-client-spi/2.24.10, Apache-2.0, approved, #13259 +maven/mavencentral/software.amazon.awssdk/http-client-spi/2.25.1, , restricted, clearlydefined maven/mavencentral/software.amazon.awssdk/iam/2.24.10, Apache-2.0, approved, #13444 maven/mavencentral/software.amazon.awssdk/identity-spi/2.24.10, Apache-2.0, approved, #13244 +maven/mavencentral/software.amazon.awssdk/identity-spi/2.25.1, , restricted, clearlydefined maven/mavencentral/software.amazon.awssdk/json-utils/2.24.10, Apache-2.0, approved, #13261 +maven/mavencentral/software.amazon.awssdk/json-utils/2.25.1, , restricted, clearlydefined maven/mavencentral/software.amazon.awssdk/metrics-spi/2.24.10, Apache-2.0, approved, #13239 +maven/mavencentral/software.amazon.awssdk/metrics-spi/2.25.1, , restricted, clearlydefined maven/mavencentral/software.amazon.awssdk/netty-nio-client/2.24.10, Apache-2.0, approved, #13260 +maven/mavencentral/software.amazon.awssdk/netty-nio-client/2.25.1, , restricted, clearlydefined maven/mavencentral/software.amazon.awssdk/profiles/2.24.10, Apache-2.0, approved, #13258 +maven/mavencentral/software.amazon.awssdk/profiles/2.25.1, , restricted, clearlydefined maven/mavencentral/software.amazon.awssdk/protocol-core/2.24.10, Apache-2.0, approved, #13241 +maven/mavencentral/software.amazon.awssdk/protocol-core/2.25.1, , restricted, clearlydefined maven/mavencentral/software.amazon.awssdk/regions/2.24.10, Apache-2.0, approved, #13255 -maven/mavencentral/software.amazon.awssdk/s3-transfer-manager/2.24.10, Apache-2.0, approved, #13263 +maven/mavencentral/software.amazon.awssdk/regions/2.25.1, , restricted, clearlydefined +maven/mavencentral/software.amazon.awssdk/s3-transfer-manager/2.25.1, , restricted, clearlydefined maven/mavencentral/software.amazon.awssdk/s3/2.24.10, Apache-2.0, approved, #13254 +maven/mavencentral/software.amazon.awssdk/s3/2.25.1, , restricted, clearlydefined maven/mavencentral/software.amazon.awssdk/sdk-core/2.24.10, Apache-2.0, approved, #13265 +maven/mavencentral/software.amazon.awssdk/sdk-core/2.25.1, , restricted, clearlydefined maven/mavencentral/software.amazon.awssdk/sts/2.24.10, Apache-2.0, approved, #13442 maven/mavencentral/software.amazon.awssdk/third-party-jackson-core/2.24.10, Apache-2.0, approved, #13249 +maven/mavencentral/software.amazon.awssdk/third-party-jackson-core/2.25.1, , restricted, clearlydefined maven/mavencentral/software.amazon.awssdk/utils/2.24.10, Apache-2.0, approved, #13250 +maven/mavencentral/software.amazon.awssdk/utils/2.25.1, , restricted, clearlydefined maven/mavencentral/software.amazon.eventstream/eventstream/1.0.1, Apache-2.0, approved, clearlydefined diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index d4787321b..4f9b5dfdf 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -6,7 +6,7 @@ edc = "0.5.2-SNAPSHOT" apache-sshd = "2.12.1" assertj = "3.25.3" awaitility = "4.2.0" -aws = "2.24.10" +aws = "2.25.1" azure-identity = "1.11.3" bouncyCastle-jdk18on = "1.77" flyway = "10.8.1" From a939764df4efd583b2b8b014ec609b55570c6d79 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 Mar 2024 15:16:45 +0100 Subject: [PATCH 049/100] chore(deps): bump com.azure:azure-security-keyvault-secrets from 4.7.3 to 4.8.0 (#1096) * chore(deps): bump com.azure:azure-security-keyvault-secrets Bumps [com.azure:azure-security-keyvault-secrets](https://github.com/Azure/azure-sdk-for-java) from 4.7.3 to 4.8.0. - [Release notes](https://github.com/Azure/azure-sdk-for-java/releases) - [Commits](https://github.com/Azure/azure-sdk-for-java/compare/azure-security-keyvault-keys_4.7.3...azure-cosmos_4.8.0) --- updated-dependencies: - dependency-name: com.azure:azure-security-keyvault-secrets dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * DEPENDENCIES --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Paul Latzelsperger --- DEPENDENCIES | 23 ++++++++++++++----- .../build.gradle.kts | 2 +- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/DEPENDENCIES b/DEPENDENCIES index f1fe1664d..e8e09bf6e 100644 --- a/DEPENDENCIES +++ b/DEPENDENCIES @@ -4,13 +4,18 @@ maven/mavencentral/com.apicatalog/iron-verifiable-credentials/0.8.1, Apache-2.0, maven/mavencentral/com.apicatalog/titanium-json-ld/1.0.0, Apache-2.0, approved, clearlydefined maven/mavencentral/com.apicatalog/titanium-json-ld/1.3.1, Apache-2.0, approved, #8912 maven/mavencentral/com.apicatalog/titanium-json-ld/1.3.3, Apache-2.0, approved, #8912 +maven/mavencentral/com.apicatalog/titanium-json-ld/1.4.0, , restricted, clearlydefined maven/mavencentral/com.azure/azure-core-http-netty/1.13.11, MIT AND Apache-2.0, approved, #7948 maven/mavencentral/com.azure/azure-core-http-netty/1.14.0, MIT AND Apache-2.0, approved, #13238 +maven/mavencentral/com.azure/azure-core-http-netty/1.14.1, MIT AND Apache-2.0, approved, #13238 maven/mavencentral/com.azure/azure-core/1.45.1, MIT AND Apache-2.0, approved, #11845 maven/mavencentral/com.azure/azure-core/1.46.0, MIT AND Apache-2.0, approved, #13234 +maven/mavencentral/com.azure/azure-core/1.47.0, , restricted, clearlydefined maven/mavencentral/com.azure/azure-identity/1.11.2, MIT AND Apache-2.0, approved, #13237 +maven/mavencentral/com.azure/azure-identity/1.11.3, MIT AND Apache-2.0, approved, #13237 maven/mavencentral/com.azure/azure-json/1.1.0, MIT AND Apache-2.0, approved, #10547 maven/mavencentral/com.azure/azure-security-keyvault-secrets/4.7.3, MIT, approved, #10868 +maven/mavencentral/com.azure/azure-security-keyvault-secrets/4.8.0, , restricted, clearlydefined maven/mavencentral/com.azure/azure-storage-blob/12.25.2, MIT, approved, #13400 maven/mavencentral/com.azure/azure-storage-common/12.24.2, MIT, approved, #13402 maven/mavencentral/com.azure/azure-storage-internal-avro/12.10.2, MIT, approved, #13399 @@ -20,9 +25,11 @@ maven/mavencentral/com.fasterxml.jackson.core/jackson-annotations/2.15.1, Apache maven/mavencentral/com.fasterxml.jackson.core/jackson-annotations/2.15.2, Apache-2.0, approved, #7947 maven/mavencentral/com.fasterxml.jackson.core/jackson-annotations/2.15.3, Apache-2.0, approved, #7947 maven/mavencentral/com.fasterxml.jackson.core/jackson-annotations/2.16.1, Apache-2.0, approved, #11606 +maven/mavencentral/com.fasterxml.jackson.core/jackson-annotations/2.16.2, Apache-2.0, approved, #11606 maven/mavencentral/com.fasterxml.jackson.core/jackson-core/2.13.5, Apache-2.0, approved, #2133 maven/mavencentral/com.fasterxml.jackson.core/jackson-core/2.15.1, MIT AND Apache-2.0, approved, #7932 maven/mavencentral/com.fasterxml.jackson.core/jackson-core/2.16.1, Apache-2.0 AND MIT, approved, #11602 +maven/mavencentral/com.fasterxml.jackson.core/jackson-core/2.16.2, Apache-2.0 AND MIT, approved, #11602 maven/mavencentral/com.fasterxml.jackson.core/jackson-databind/2.13.4.2, Apache-2.0, approved, #2134 maven/mavencentral/com.fasterxml.jackson.core/jackson-databind/2.13.5, Apache-2.0, approved, #2134 maven/mavencentral/com.fasterxml.jackson.core/jackson-databind/2.14.2, Apache-2.0, approved, #4105 @@ -30,26 +37,30 @@ maven/mavencentral/com.fasterxml.jackson.core/jackson-databind/2.15.1, Apache-2. maven/mavencentral/com.fasterxml.jackson.core/jackson-databind/2.15.2, Apache-2.0, approved, #7934 maven/mavencentral/com.fasterxml.jackson.core/jackson-databind/2.15.3, Apache-2.0, approved, #7934 maven/mavencentral/com.fasterxml.jackson.core/jackson-databind/2.16.1, Apache-2.0, approved, #11605 +maven/mavencentral/com.fasterxml.jackson.core/jackson-databind/2.16.2, Apache-2.0, approved, #11605 maven/mavencentral/com.fasterxml.jackson.dataformat/jackson-dataformat-toml/2.15.2, Apache-2.0, approved, #9160 -maven/mavencentral/com.fasterxml.jackson.dataformat/jackson-dataformat-toml/2.16.1, Apache-2.0, approved, #13145 +maven/mavencentral/com.fasterxml.jackson.dataformat/jackson-dataformat-toml/2.16.2, Apache-2.0, approved, #13145 maven/mavencentral/com.fasterxml.jackson.dataformat/jackson-dataformat-xml/2.13.5, Apache-2.0, approved, #3768 -maven/mavencentral/com.fasterxml.jackson.dataformat/jackson-dataformat-xml/2.16.1, Apache-2.0, approved, #12438 +maven/mavencentral/com.fasterxml.jackson.dataformat/jackson-dataformat-xml/2.16.2, Apache-2.0, approved, #12438 maven/mavencentral/com.fasterxml.jackson.dataformat/jackson-dataformat-yaml/2.15.1, Apache-2.0, approved, #8802 maven/mavencentral/com.fasterxml.jackson.dataformat/jackson-dataformat-yaml/2.15.2, Apache-2.0, approved, #8802 -maven/mavencentral/com.fasterxml.jackson.dataformat/jackson-dataformat-yaml/2.16.1, Apache-2.0, approved, #11855 +maven/mavencentral/com.fasterxml.jackson.dataformat/jackson-dataformat-yaml/2.16.2, Apache-2.0, approved, #11855 maven/mavencentral/com.fasterxml.jackson.datatype/jackson-datatype-jakarta-jsonp/2.16.1, Apache-2.0, approved, #11854 +maven/mavencentral/com.fasterxml.jackson.datatype/jackson-datatype-jakarta-jsonp/2.16.2, Apache-2.0, approved, #11854 maven/mavencentral/com.fasterxml.jackson.datatype/jackson-datatype-jsr310/2.13.5, Apache-2.0, approved, clearlydefined maven/mavencentral/com.fasterxml.jackson.datatype/jackson-datatype-jsr310/2.15.1, Apache-2.0, approved, #7930 maven/mavencentral/com.fasterxml.jackson.datatype/jackson-datatype-jsr310/2.15.2, Apache-2.0, approved, #7930 maven/mavencentral/com.fasterxml.jackson.datatype/jackson-datatype-jsr310/2.16.1, Apache-2.0, approved, #11853 -maven/mavencentral/com.fasterxml.jackson.jakarta.rs/jackson-jakarta-rs-base/2.16.1, Apache-2.0, approved, #11851 +maven/mavencentral/com.fasterxml.jackson.datatype/jackson-datatype-jsr310/2.16.2, Apache-2.0, approved, #11853 +maven/mavencentral/com.fasterxml.jackson.jakarta.rs/jackson-jakarta-rs-base/2.16.2, Apache-2.0, approved, #11851 maven/mavencentral/com.fasterxml.jackson.jakarta.rs/jackson-jakarta-rs-json-provider/2.15.1, Apache-2.0, approved, #9236 maven/mavencentral/com.fasterxml.jackson.jakarta.rs/jackson-jakarta-rs-json-provider/2.15.2, Apache-2.0, approved, #9236 -maven/mavencentral/com.fasterxml.jackson.jakarta.rs/jackson-jakarta-rs-json-provider/2.16.1, Apache-2.0, approved, #11858 +maven/mavencentral/com.fasterxml.jackson.jakarta.rs/jackson-jakarta-rs-json-provider/2.16.2, Apache-2.0, approved, #11858 maven/mavencentral/com.fasterxml.jackson.module/jackson-module-jakarta-xmlbind-annotations/2.15.3, Apache-2.0, approved, #9241 -maven/mavencentral/com.fasterxml.jackson.module/jackson-module-jakarta-xmlbind-annotations/2.16.1, Apache-2.0, approved, #11856 +maven/mavencentral/com.fasterxml.jackson.module/jackson-module-jakarta-xmlbind-annotations/2.16.2, Apache-2.0, approved, #11856 maven/mavencentral/com.fasterxml.jackson/jackson-bom/2.15.1, Apache-2.0, approved, #7929 maven/mavencentral/com.fasterxml.jackson/jackson-bom/2.16.1, Apache-2.0, approved, #11852 +maven/mavencentral/com.fasterxml.jackson/jackson-bom/2.16.2, Apache-2.0, approved, #11852 maven/mavencentral/com.fasterxml.woodstox/woodstox-core/6.5.1, Apache-2.0, approved, #7950 maven/mavencentral/com.github.docker-java/docker-java-api/3.3.5, Apache-2.0, approved, #10346 maven/mavencentral/com.github.docker-java/docker-java-api/3.3.6, Apache-2.0, approved, #10346 diff --git a/edc-dataplane/edc-dataplane-azure-vault/build.gradle.kts b/edc-dataplane/edc-dataplane-azure-vault/build.gradle.kts index 0172e73d0..3db121d5e 100644 --- a/edc-dataplane/edc-dataplane-azure-vault/build.gradle.kts +++ b/edc-dataplane/edc-dataplane-azure-vault/build.gradle.kts @@ -32,7 +32,7 @@ dependencies { } } implementation(libs.edc.azure.identity) - implementation("com.azure:azure-security-keyvault-secrets:4.7.3") + implementation("com.azure:azure-security-keyvault-secrets:4.8.0") runtimeOnly(project(":edc-extensions:edr:edr-cache-sql")) runtimeOnly(libs.edc.transaction.local) runtimeOnly(libs.edc.sql.pool) From 88db87662d66c5e05fdf3e63bbf6be7d19afa85c Mon Sep 17 00:00:00 2001 From: Paul Latzelsperger <43503240+paullatzelsperger@users.noreply.github.com> Date: Tue, 12 Mar 2024 14:36:09 +0100 Subject: [PATCH 050/100] docs: improve token refresh docu (#1123) * docs: improve token refresh docu * fix numbering --- .../AutomaticRefreshEdrApi.drawio | 69 ++++++++++++++++ .../AutomaticRefreshEdrApi.drawio.png | Bin 0 -> 43679 bytes .../dataplane-signaling/ManualRefresh.drawio | 75 +++++++++++++----- .../ManualRefresh.drawio.png | Bin 40718 -> 55593 bytes .../tx-signaling.extensions.md | 71 ++++++++++++----- 5 files changed, 173 insertions(+), 42 deletions(-) create mode 100644 docs/development/dataplane-signaling/AutomaticRefreshEdrApi.drawio create mode 100644 docs/development/dataplane-signaling/AutomaticRefreshEdrApi.drawio.png diff --git a/docs/development/dataplane-signaling/AutomaticRefreshEdrApi.drawio b/docs/development/dataplane-signaling/AutomaticRefreshEdrApi.drawio new file mode 100644 index 000000000..7d9697e53 --- /dev/null +++ b/docs/development/dataplane-signaling/AutomaticRefreshEdrApi.drawio @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/development/dataplane-signaling/AutomaticRefreshEdrApi.drawio.png b/docs/development/dataplane-signaling/AutomaticRefreshEdrApi.drawio.png new file mode 100644 index 0000000000000000000000000000000000000000..fc68d7e815659c7781830f493abd80c1340b16ee GIT binary patch literal 43679 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 EUlO2?0ssI2 literal 0 HcmV?d00001 diff --git a/docs/development/dataplane-signaling/ManualRefresh.drawio b/docs/development/dataplane-signaling/ManualRefresh.drawio index 0bdd5aa6e..9f5bfc112 100644 --- a/docs/development/dataplane-signaling/ManualRefresh.drawio +++ b/docs/development/dataplane-signaling/ManualRefresh.drawio @@ -1,52 +1,83 @@ - + - + - + - + - + - + - - + + - - - - - - - - - + + - + - + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/development/dataplane-signaling/ManualRefresh.drawio.png b/docs/development/dataplane-signaling/ManualRefresh.drawio.png index ed0c3ee2b5031e618b6f59e243458de6c21c3fb1..b0ff1db7fd813dee45e4c5ba018c424a8f71e507 100644 GIT binary patch literal 55593 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 a*E)kqBo9Ske!evc{HUJNIGL+>$@@P(W(4;D literal 40718 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 uz*L@L$>|JhM3WV*mOKap0|fCAoHGb>jp| Date: Tue, 12 Mar 2024 17:24:21 +0100 Subject: [PATCH 051/100] feat: add DataPlane Token Refresh API (#1120) --- DEPENDENCIES | 1 + .../edc-dataplane-base/build.gradle.kts | 5 +- .../token-refresh-api/build.gradle.kts | 36 +++ .../api/TokenRefreshApiExtension.java | 53 ++++ .../tokenrefresh/api/v1/TokenRefreshApi.java | 58 ++++ .../api/v1/TokenRefreshApiController.java | 59 ++++ ...rg.eclipse.edc.spi.system.ServiceExtension | 20 ++ .../api/v1/TokenRefreshApiControllerTest.java | 146 ++++++++++ ...DataPlaneTokenRefreshServiceExtension.java | 21 +- .../DataPlaneTokenRefreshServiceImpl.java | 18 +- ...eTokenRefreshServiceImplComponentTest.java | 23 ++ .../build.gradle.kts | 4 +- .../DataPlaneTokenRefreshEndToEndTest.java | 253 +++++++++++++++++- .../tokenrefresh/e2e/RuntimeConfig.java | 53 +++- gradle/libs.versions.toml | 3 +- settings.gradle.kts | 1 + 16 files changed, 730 insertions(+), 24 deletions(-) create mode 100644 edc-extensions/dataplane/dataplane-token-refresh/token-refresh-api/build.gradle.kts create mode 100644 edc-extensions/dataplane/dataplane-token-refresh/token-refresh-api/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/api/TokenRefreshApiExtension.java create mode 100644 edc-extensions/dataplane/dataplane-token-refresh/token-refresh-api/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/api/v1/TokenRefreshApi.java create mode 100644 edc-extensions/dataplane/dataplane-token-refresh/token-refresh-api/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/api/v1/TokenRefreshApiController.java create mode 100644 edc-extensions/dataplane/dataplane-token-refresh/token-refresh-api/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension create mode 100644 edc-extensions/dataplane/dataplane-token-refresh/token-refresh-api/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/api/v1/TokenRefreshApiControllerTest.java diff --git a/DEPENDENCIES b/DEPENDENCIES index e8e09bf6e..32a250533 100644 --- a/DEPENDENCIES +++ b/DEPENDENCIES @@ -297,6 +297,7 @@ maven/mavencentral/org.eclipse.edc/data-plane-http-oauth2-core/0.5.2-SNAPSHOT, A maven/mavencentral/org.eclipse.edc/data-plane-http-oauth2/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/data-plane-http-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/data-plane-http/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-public-api-v2/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/data-plane-public-api/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/data-plane-selector-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/data-plane-selector-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc diff --git a/edc-dataplane/edc-dataplane-base/build.gradle.kts b/edc-dataplane/edc-dataplane-base/build.gradle.kts index 85af80bb9..d0cc8cfbb 100644 --- a/edc-dataplane/edc-dataplane-base/build.gradle.kts +++ b/edc-dataplane/edc-dataplane-base/build.gradle.kts @@ -28,6 +28,7 @@ dependencies { runtimeOnly(project(":edc-extensions:dataplane:dataplane-proxy:edc-dataplane-proxy-provider-api")) runtimeOnly(project(":edc-extensions:dataplane:dataplane-proxy:edc-dataplane-proxy-provider-core")) runtimeOnly(project(":edc-extensions:dataplane:dataplane-token-refresh:token-refresh-core")) + runtimeOnly(project(":edc-extensions:dataplane:dataplane-token-refresh:token-refresh-api")) runtimeOnly(libs.edc.jsonld) // needed by the DataPlaneSignalingApi runtimeOnly(libs.edc.identity.core.did) // for the DID Public Key Resolver @@ -43,7 +44,9 @@ dependencies { runtimeOnly(libs.edc.dpf.api.control) runtimeOnly(libs.edc.dpf.api.signaling) - runtimeOnly(libs.edc.dpf.api.public) + + runtimeOnly(libs.edc.dpf.api.public.v1) + runtimeOnly(libs.edc.dpf.api.public.v2) runtimeOnly(libs.edc.core.connector) runtimeOnly(libs.edc.boot) diff --git a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-api/build.gradle.kts b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-api/build.gradle.kts new file mode 100644 index 000000000..0439436fa --- /dev/null +++ b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-api/build.gradle.kts @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +plugins { + `java-library` + `maven-publish` + id("io.swagger.core.v3.swagger-gradle-plugin") +} + +dependencies { + api(project(":spi:tokenrefresh-spi")) + implementation(libs.edc.spi.core) + implementation(libs.edc.spi.web) + implementation(libs.jakarta.rsApi) + + testImplementation(libs.edc.junit) + testImplementation(libs.restAssured) + testImplementation(testFixtures(libs.edc.core.jersey)) +} + diff --git a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-api/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/api/TokenRefreshApiExtension.java b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-api/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/api/TokenRefreshApiExtension.java new file mode 100644 index 000000000..3fb4a88b6 --- /dev/null +++ b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-api/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/api/TokenRefreshApiExtension.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.eclipse.tractusx.edc.dataplane.tokenrefresh.api; + +import org.eclipse.edc.runtime.metamodel.annotation.Extension; +import org.eclipse.edc.runtime.metamodel.annotation.Inject; +import org.eclipse.edc.spi.system.ServiceExtension; +import org.eclipse.edc.spi.system.ServiceExtensionContext; +import org.eclipse.edc.web.spi.WebService; +import org.eclipse.tractusx.edc.dataplane.tokenrefresh.api.v1.TokenRefreshApiController; +import org.eclipse.tractusx.edc.dataplane.tokenrefresh.spi.DataPlaneTokenRefreshService; + +import static org.eclipse.tractusx.edc.dataplane.tokenrefresh.api.TokenRefreshApiExtension.NAME; + +@Extension(value = NAME) +public class TokenRefreshApiExtension implements ServiceExtension { + + public static final String NAME = "DataPlane Token Refresh API Extension"; + private static final String PUBLIC_API_CONTEXT = "public"; + @Inject + private DataPlaneTokenRefreshService refreshService; + + @Inject + private WebService webService; + + @Override + public String name() { + return NAME; + } + + @Override + public void initialize(ServiceExtensionContext context) { + var controller = new TokenRefreshApiController(refreshService); + webService.registerResource(PUBLIC_API_CONTEXT, controller); + } +} diff --git a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-api/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/api/v1/TokenRefreshApi.java b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-api/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/api/v1/TokenRefreshApi.java new file mode 100644 index 000000000..f0a85a0ed --- /dev/null +++ b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-api/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/api/v1/TokenRefreshApi.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.eclipse.tractusx.edc.dataplane.tokenrefresh.api.v1; + +import io.swagger.v3.oas.annotations.OpenAPIDefinition; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.enums.SecuritySchemeType; +import io.swagger.v3.oas.annotations.info.Info; +import io.swagger.v3.oas.annotations.media.ArraySchema; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.security.SecurityScheme; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.eclipse.edc.web.spi.ApiErrorDetail; +import org.eclipse.tractusx.edc.dataplane.tokenrefresh.spi.model.TokenResponse; + +@SecurityScheme(name = "Authentication", + description = "Self-Issued ID token containing an access_token", + type = SecuritySchemeType.HTTP, + scheme = "bearer", + bearerFormat = "JWT") +@OpenAPIDefinition(info = @Info(description = "With this API clients can refresh their access token for a provider's HTTP data plane using an authentication token and a refresh token.", title = "Token Refresh API")) +@Tag(name = "Token Refresh API") +public interface TokenRefreshApi { + + @Operation(description = "Resolves all groups for a particular BPN", + parameters = { @Parameter(name = "grant_type", description = "The grant type. Must be \"refresh_token\""), + @Parameter(name = "refresh_token", description = "The refresh token") }, + responses = { + @ApiResponse(responseCode = "200", description = "The access token and refresh token were updated. Expiry should be " + + "interpreted as starting from the time of message reception, allowing for some leeway.", + content = @Content(schema = @Schema(implementation = TokenResponse.class))), + @ApiResponse(responseCode = "401", description = "The token could not be refreshed due to an authentication error, either the refresh token or the Authorization header were invalid.", + content = @Content(array = @ArraySchema(schema = @Schema(implementation = ApiErrorDetail.class)))), + @ApiResponse(responseCode = "400", description = "Request body was malformed, query parameters were missing, etc.", + content = @Content(array = @ArraySchema(schema = @Schema(implementation = ApiErrorDetail.class)))) + }) + TokenResponse refreshToken(String grantType, String refreshToken, String bearerToken); +} diff --git a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-api/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/api/v1/TokenRefreshApiController.java b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-api/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/api/v1/TokenRefreshApiController.java new file mode 100644 index 000000000..c2e08290f --- /dev/null +++ b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-api/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/api/v1/TokenRefreshApiController.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.eclipse.tractusx.edc.dataplane.tokenrefresh.api.v1; + +import jakarta.ws.rs.Consumes; +import jakarta.ws.rs.HeaderParam; +import jakarta.ws.rs.POST; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.Produces; +import jakarta.ws.rs.QueryParam; +import jakarta.ws.rs.core.MediaType; +import org.eclipse.edc.web.spi.exception.AuthenticationFailedException; +import org.eclipse.edc.web.spi.exception.InvalidRequestException; +import org.eclipse.tractusx.edc.dataplane.tokenrefresh.spi.DataPlaneTokenRefreshService; +import org.eclipse.tractusx.edc.dataplane.tokenrefresh.spi.model.TokenResponse; + +import static jakarta.ws.rs.core.HttpHeaders.AUTHORIZATION; + +@Produces({ MediaType.APPLICATION_JSON }) +@Path("/token") +public class TokenRefreshApiController implements TokenRefreshApi { + private static final String REFRESH_TOKEN_GRANT = "refresh_token"; + private final DataPlaneTokenRefreshService tokenRefreshService; + + public TokenRefreshApiController(DataPlaneTokenRefreshService tokenRefreshService) { + this.tokenRefreshService = tokenRefreshService; + } + + @POST + @Consumes(MediaType.APPLICATION_FORM_URLENCODED) + @Override + public TokenResponse refreshToken(@QueryParam("grant_type") String grantType, + @QueryParam("refresh_token") String refreshToken, + @HeaderParam(AUTHORIZATION) String bearerToken) { + if (!REFRESH_TOKEN_GRANT.equals(grantType)) { + throw new InvalidRequestException("Grant type MUST be '%s' but was '%s'".formatted(REFRESH_TOKEN_GRANT, grantType)); + } + + return tokenRefreshService.refreshToken(refreshToken, bearerToken) + .orElseThrow(f -> new AuthenticationFailedException(f.getFailureDetail())); + } +} diff --git a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-api/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-api/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension new file mode 100644 index 000000000..db16e33f7 --- /dev/null +++ b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-api/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension @@ -0,0 +1,20 @@ +################################################################################# +# Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License, Version 2.0 which is available at +# https://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. +# +# SPDX-License-Identifier: Apache-2.0 +################################################################################# + +org.eclipse.tractusx.edc.dataplane.tokenrefresh.api.TokenRefreshApiExtension \ No newline at end of file diff --git a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-api/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/api/v1/TokenRefreshApiControllerTest.java b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-api/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/api/v1/TokenRefreshApiControllerTest.java new file mode 100644 index 000000000..bb2b805c2 --- /dev/null +++ b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-api/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/api/v1/TokenRefreshApiControllerTest.java @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.eclipse.tractusx.edc.dataplane.tokenrefresh.api.v1; + +import io.restassured.http.ContentType; +import io.restassured.specification.RequestSpecification; +import org.eclipse.edc.spi.result.Result; +import org.eclipse.edc.web.jersey.testfixtures.RestControllerTestBase; +import org.eclipse.tractusx.edc.dataplane.tokenrefresh.spi.DataPlaneTokenRefreshService; +import org.eclipse.tractusx.edc.dataplane.tokenrefresh.spi.model.TokenResponse; +import org.hamcrest.Matchers; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.EmptySource; +import org.junit.jupiter.params.provider.NullSource; +import org.junit.jupiter.params.provider.ValueSource; + +import static io.restassured.RestAssured.given; +import static jakarta.ws.rs.core.HttpHeaders.AUTHORIZATION; +import static org.hamcrest.Matchers.containsString; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +class TokenRefreshApiControllerTest extends RestControllerTestBase { + + private final DataPlaneTokenRefreshService refreshService = mock(); + + @DisplayName("Expect HTTP 400 when no Authorization header is present") + @Test + void refresh_noAuthHeader_expect401() { + baseRequest() + .queryParam("grant_type", "refresh_token") + .queryParam("refresh_token", "foo-token") + /* missing: .header(AUTHORIZATION, "auth-token") */ + .contentType(ContentType.URLENC) + .then() + .statusCode(401); + } + + @DisplayName("Expect HTTP 200 when the token was successfully refreshed") + @Test + void refresh_expect200() { + when(refreshService.refreshToken(any(), any())).thenReturn(Result.success(new TokenResponse("new-accesstoken", "new-refreshtoken", 3000L, "bearer"))); + baseRequest() + .queryParam("grant_type", "refresh_token") + .queryParam("refresh_token", "foo-token") + .header(AUTHORIZATION, "auth-token") + .contentType(ContentType.URLENC) + .then() + .statusCode(200) + .body(Matchers.isA(TokenResponse.class)); + } + + @DisplayName("Expect HTTP 400 when an invalid grant type was provided") + @ParameterizedTest(name = "Invalid grant_type: {0}") + @ValueSource(strings = { "REFRESH_TOKEN", "refreshToken", "invalid_grant", "client_credentials", "" }) + @NullSource + void refresh_invalidGrantType_expect400(String grant) { + baseRequest() + .queryParam("grant_type", grant) + .queryParam("refresh_token", "foo-token") + .header(AUTHORIZATION, "auth-token") + .contentType(ContentType.URLENC) + .then() + .statusCode(400); + } + + @DisplayName("Expect HTTP 400 when an invalid refresh token was provided") + @ParameterizedTest(name = "Invalid refresh_token: {0}") + @NullSource + @EmptySource + void refresh_invalidRefreshToken_expect400(String refreshToken) { + baseRequest() + .queryParam("grant_type", "refresh_token") + .queryParam("refresh_token", refreshToken) + .header(AUTHORIZATION, "auth-token") + .contentType(ContentType.URLENC) + .then() + .statusCode(400); + } + + @DisplayName("Expect HTTP 400 when one of the query params was missing") + @Test + void refresh_queryParamsMissing() { + baseRequest() + .queryParam("grant_type", "refresh_token") + .header(AUTHORIZATION, "auth-token") + .contentType(ContentType.URLENC) + .then() + .statusCode(400); + + baseRequest() + .queryParam("refresh_token", "foo-token") + .header(AUTHORIZATION, "auth-token") + .contentType(ContentType.URLENC) + .then() + .statusCode(400); + } + + @DisplayName("Expect HTTP 401 if the auth header or refresh token are invalid") + @Test + void refresh_tokenInvalid_expect401() { + when(refreshService.refreshToken(any(), any())).thenReturn(Result.failure("Invalid auth token")); + + baseRequest() + .queryParam("grant_type", "refresh_token") + .queryParam("refresh_token", "foo-token") + .header(AUTHORIZATION, "auth-token") + .contentType(ContentType.URLENC) + .then() + .statusCode(401) + .body(containsString("Invalid auth token")); + } + + @Override + protected Object controller() { + return new TokenRefreshApiController(refreshService); + } + + private RequestSpecification baseRequest() { + return given() + .baseUri("http://localhost:" + port) + .basePath("/token") + .when(); + } + +} \ No newline at end of file diff --git a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceExtension.java b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceExtension.java index 0acc3a818..8f03fc2f3 100644 --- a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceExtension.java +++ b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceExtension.java @@ -30,6 +30,7 @@ import org.eclipse.edc.spi.system.ServiceExtensionContext; import org.eclipse.edc.token.JwtGenerationService; import org.eclipse.edc.token.spi.TokenValidationService; +import org.eclipse.tractusx.edc.dataplane.tokenrefresh.spi.DataPlaneTokenRefreshService; import org.jetbrains.annotations.NotNull; import java.security.PrivateKey; @@ -50,15 +51,31 @@ public class DataPlaneTokenRefreshServiceExtension implements ServiceExtension { @Inject private PrivateKeyResolver privateKeyResolver; + private DataPlaneTokenRefreshServiceImpl tokenRefreshService; @Override public String name() { return NAME; } + // exposes the service as access token service @Provider - public DataPlaneAccessTokenService createRefreshAccessTokenService(ServiceExtensionContext context) { - return new DataPlaneTokenRefreshServiceImpl(tokenValidationService, didPkResolver, accessTokenDataStore, new JwtGenerationService(), getPrivateKeySupplier(context), context.getMonitor(), "foo.bar"); + public DataPlaneAccessTokenService createAccessTokenService(ServiceExtensionContext context) { + return getTokenRefreshService(context); + } + + // exposes the service as pure refresh service + @Provider + public DataPlaneTokenRefreshService createRefreshTokenService(ServiceExtensionContext context) { + return getTokenRefreshService(context); + } + + @NotNull + private DataPlaneTokenRefreshServiceImpl getTokenRefreshService(ServiceExtensionContext context) { + if (tokenRefreshService == null) { + tokenRefreshService = new DataPlaneTokenRefreshServiceImpl(tokenValidationService, didPkResolver, accessTokenDataStore, new JwtGenerationService(), getPrivateKeySupplier(context), context.getMonitor(), "foo.bar"); + } + return tokenRefreshService; } @NotNull diff --git a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImpl.java b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImpl.java index ea47788c9..7e6fdc0f1 100644 --- a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImpl.java +++ b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImpl.java @@ -50,6 +50,8 @@ import java.util.function.Supplier; import java.util.stream.Stream; +import static org.eclipse.edc.jwt.spi.JwtRegisteredClaimNames.AUDIENCE; + /** * This implementation of the {@link DataPlaneTokenRefreshService} validates an incoming authentication token. */ @@ -58,7 +60,10 @@ public class DataPlaneTokenRefreshServiceImpl implements DataPlaneTokenRefreshSe public static final String TOKEN_ID_CLAIM = "jti"; public static final String REFRESH_TOKEN_PROPERTY = "refreshToken"; private static final Long DEFAULT_EXPIRY_IN_SECONDS = 60 * 5L; - private final List tokenValidationRules = List.of(new IssuerEqualsSubjectRule(), new ClaimIsPresentRule(ACCESS_TOKEN_CLAIM), new ClaimIsPresentRule(TOKEN_ID_CLAIM)); + private final List authenticationTokenValidationRules = List.of(new IssuerEqualsSubjectRule(), + new ClaimIsPresentRule(AUDIENCE), // we don't check the contents, only it is present + new ClaimIsPresentRule(ACCESS_TOKEN_CLAIM), + new ClaimIsPresentRule(TOKEN_ID_CLAIM)); private final TokenValidationService tokenValidationService; private final DidPublicKeyResolver publicKeyResolver; private final AccessTokenDataStore accessTokenDataStore; @@ -71,7 +76,10 @@ public class DataPlaneTokenRefreshServiceImpl implements DataPlaneTokenRefreshSe public DataPlaneTokenRefreshServiceImpl(TokenValidationService tokenValidationService, DidPublicKeyResolver publicKeyResolver, AccessTokenDataStore accessTokenDataStore, - TokenGenerationService tokenGenerationService, Supplier privateKeySupplier, Monitor monitor, String refreshEndpoint) { + TokenGenerationService tokenGenerationService, + Supplier privateKeySupplier, + Monitor monitor, + String refreshEndpoint) { this.tokenValidationService = tokenValidationService; this.publicKeyResolver = publicKeyResolver; this.accessTokenDataStore = accessTokenDataStore; @@ -100,9 +108,11 @@ public DataPlaneTokenRefreshServiceImpl(TokenValidationService tokenValidationSe @Override public Result refreshToken(String refreshToken, String authenticationToken) { - var allRules = new ArrayList<>(tokenValidationRules); + var allRules = new ArrayList<>(authenticationTokenValidationRules); allRules.add(new RefreshTokenMustExistRule(accessTokenDataStore, refreshToken)); + authenticationToken = authenticationToken.replace("Bearer", "").trim(); + var accessTokenDataResult = resolveToken(authenticationToken, allRules); if (accessTokenDataResult.failed()) { return accessTokenDataResult.mapTo(); @@ -182,7 +192,7 @@ public Result obtainToken(TokenParameters tokenParameters, @Override public Result resolve(String token) { - return resolveToken(token, tokenValidationRules); + return resolveToken(token, authenticationTokenValidationRules); } /** diff --git a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImplComponentTest.java b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImplComponentTest.java index 28240b505..dab07a6e3 100644 --- a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImplComponentTest.java +++ b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImplComponentTest.java @@ -212,6 +212,29 @@ void refresh_whenNoAccessTokenClaim() throws JOSEException { .isEqualTo("Required claim 'access_token' not present on token."); } + @DisplayName("Verify that the equality of the 'iss' and the 'sub' claim of the authentication token") + @Test + void refresh_whenIssNotEqualToSub() throws JOSEException { + var tokenId = "test-token-id"; + var edr = tokenRefreshService.obtainToken(tokenParams(tokenId), DataAddress.Builder.newInstance().type("test-type").build(), Map.of("audience", CONSUMER_DID)) + .orElseThrow(f -> new RuntimeException(f.getFailureDetail())); + + var accessToken = edr.getToken(); + var jwsHeader = new JWSHeader.Builder(JWSAlgorithm.ES384).keyID(consumerKey.getKeyID()).build(); + var claimsSet = getAuthTokenClaims(tokenId, accessToken) + .issuer(CONSUMER_DID) + .subject("violating-subject") + .build(); + + var signedAuthToken = new SignedJWT(jwsHeader, claimsSet); + signedAuthToken.sign(CryptoConverter.createSigner(consumerKey)); + var tokenResponse = tokenRefreshService.refreshToken(edr.getAdditional().get("refreshToken").toString(), signedAuthToken.serialize()); + + assertThat(tokenResponse).isFailed() + .detail() + .isEqualTo("The 'iss' and 'sub' claims must be non-null and identical."); + } + private JWTClaimsSet.Builder getAuthTokenClaims(String tokenId, String accessToken) { return new JWTClaimsSet.Builder() .jwtID(tokenId) diff --git a/edc-tests/edc-dataplane/edc-dataplane-tokenrefresh-tests/build.gradle.kts b/edc-tests/edc-dataplane/edc-dataplane-tokenrefresh-tests/build.gradle.kts index 57453561e..2f813d5fa 100644 --- a/edc-tests/edc-dataplane/edc-dataplane-tokenrefresh-tests/build.gradle.kts +++ b/edc-tests/edc-dataplane/edc-dataplane-tokenrefresh-tests/build.gradle.kts @@ -23,12 +23,14 @@ plugins { dependencies { + testImplementation(project(":spi:tokenrefresh-spi")) testImplementation(project(":edc-tests:e2e-tests")) testImplementation(libs.edc.junit) testImplementation(libs.restAssured) testImplementation(libs.edc.dpf.http) - + testImplementation(libs.edc.spi.identity.did) + testImplementation(libs.nimbus.jwt) } diff --git a/edc-tests/edc-dataplane/edc-dataplane-tokenrefresh-tests/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/e2e/DataPlaneTokenRefreshEndToEndTest.java b/edc-tests/edc-dataplane/edc-dataplane-tokenrefresh-tests/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/e2e/DataPlaneTokenRefreshEndToEndTest.java index 2302d19b1..2432700f7 100644 --- a/edc-tests/edc-dataplane/edc-dataplane-tokenrefresh-tests/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/e2e/DataPlaneTokenRefreshEndToEndTest.java +++ b/edc-tests/edc-dataplane/edc-dataplane-tokenrefresh-tests/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/e2e/DataPlaneTokenRefreshEndToEndTest.java @@ -19,27 +19,268 @@ package org.eclipse.tractusx.edc.dataplane.tokenrefresh.e2e; +import com.nimbusds.jose.JOSEException; +import com.nimbusds.jose.JWSAlgorithm; +import com.nimbusds.jose.JWSHeader; +import com.nimbusds.jose.crypto.ECDSASigner; +import com.nimbusds.jose.jwk.Curve; +import com.nimbusds.jose.jwk.ECKey; +import com.nimbusds.jose.jwk.gen.ECKeyGenerator; +import com.nimbusds.jwt.JWTClaimsSet; +import com.nimbusds.jwt.SignedJWT; +import org.eclipse.edc.connector.dataplane.spi.iam.DataPlaneAuthorizationService; +import org.eclipse.edc.iam.did.spi.resolution.DidPublicKeyResolver; import org.eclipse.edc.junit.annotations.EndToEndTest; import org.eclipse.edc.junit.extensions.EdcRuntimeExtension; +import org.eclipse.edc.spi.result.Result; +import org.eclipse.edc.spi.security.Vault; +import org.eclipse.edc.spi.types.domain.DataAddress; +import org.eclipse.edc.spi.types.domain.transfer.DataFlowStartMessage; +import org.eclipse.edc.spi.types.domain.transfer.FlowType; +import org.eclipse.tractusx.edc.dataplane.tokenrefresh.spi.model.TokenResponse; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; -import static org.eclipse.edc.junit.testfixtures.TestUtils.getFreePort; +import java.net.URI; +import java.text.ParseException; +import java.util.Map; + +import static org.apache.http.HttpHeaders.AUTHORIZATION; +import static org.assertj.core.api.Assertions.assertThat; +import static org.eclipse.edc.spi.CoreConstants.EDC_NAMESPACE; +import static org.hamcrest.Matchers.containsString; @EndToEndTest public class DataPlaneTokenRefreshEndToEndTest { - private static final int PROVIDER_CONTROL_PORT = getFreePort(); // port of the control api - + public static final String CONSUMER_DID = "did:web:alice"; + public static final String PROVIDER_DID = "did:web:bob"; + public static final String PROVIDER_KEY_ID = PROVIDER_DID + "#key-1"; + public static final String CONSUMER_KEY_ID = CONSUMER_DID + "#cons-1"; + private static final RuntimeConfig RUNTIME_CONFIG = new RuntimeConfig(); @RegisterExtension protected static final EdcRuntimeExtension DATAPLANE_RUNTIME = new EdcRuntimeExtension( ":edc-tests:runtime:dataplane-cloud", "Token-Refresh-Dataplane", - RuntimeConfig.baseConfig("/signaling", PROVIDER_CONTROL_PORT) + with(RUNTIME_CONFIG.baseConfig(), Map.of("edc.transfer.proxy.token.signer.privatekey.alias", PROVIDER_KEY_ID)) ); + private ECKey providerKey; + private ECKey consumerKey; + + private static Map with(Map baseConfig, Map additionalConfig) { + baseConfig.putAll(additionalConfig); + return baseConfig; + } + + + @BeforeEach + void setup() throws JOSEException { + providerKey = new ECKeyGenerator(Curve.P_384).keyID(PROVIDER_KEY_ID).generate(); + consumerKey = new ECKeyGenerator(Curve.P_256).keyID(CONSUMER_KEY_ID).generate(); + + // mock the did resolver, hard-wire it to the provider or consumer DID + DATAPLANE_RUNTIME.registerServiceMock(DidPublicKeyResolver.class, s -> { + try { + if (s.startsWith(CONSUMER_DID)) { + return Result.success(consumerKey.toPublicKey()); + } else if (s.startsWith(PROVIDER_DID)) { + return Result.success(providerKey.toPublicKey()); + } + throw new IllegalArgumentException("DID '%s' could not be resolved.".formatted(s)); + } catch (JOSEException e) { + throw new RuntimeException(e); + } + }); + } + + @Test + void refresh_success() { + + // register generator and secrets + prepareDataplaneRuntime(); + + var authorizationService = DATAPLANE_RUNTIME.getService(DataPlaneAuthorizationService.class); + var edr = authorizationService.createEndpointDataReference(createStartMessage("test-process-id", CONSUMER_DID)) + .orElseThrow(f -> new AssertionError(f.getFailureDetail())); + + var refreshToken = edr.getStringProperty("refreshToken"); + var accessToken = edr.getStringProperty("authorization"); + var authToken = createAuthToken(accessToken, consumerKey); + + var tokenResponse = RUNTIME_CONFIG.getRefreshApi().baseRequest() + .queryParam("grant_type", "refresh_token") + .queryParam("refresh_token", refreshToken) + .header(AUTHORIZATION, "Bearer " + authToken) + .post("/token") + .then() + .log().ifError() + .statusCode(200) + .extract().body().as(TokenResponse.class); + + assertThat(tokenResponse).isNotNull(); + } + + @DisplayName("The sign key of the authentication token is different from the public key from the DID") + @Test + void refresh_spoofedAuthToken() throws JOSEException { + prepareDataplaneRuntime(); + + var authorizationService = DATAPLANE_RUNTIME.getService(DataPlaneAuthorizationService.class); + var edr = authorizationService.createEndpointDataReference(createStartMessage("test-process-id", CONSUMER_DID)) + .orElseThrow(f -> new AssertionError(f.getFailureDetail())); + + var refreshToken = edr.getStringProperty("refreshToken"); + var accessToken = edr.getStringProperty("authorization"); + var spoofedKey = new ECKeyGenerator(Curve.P_256).keyID(CONSUMER_KEY_ID).generate(); + var authTokenWithSpoofedKey = createAuthToken(accessToken, spoofedKey); + + RUNTIME_CONFIG.getRefreshApi().baseRequest() + .queryParam("grant_type", "refresh_token") + .queryParam("refresh_token", refreshToken) + .header(AUTHORIZATION, "Bearer " + authTokenWithSpoofedKey) + .post("/token") + .then() + .log().ifValidationFails() + .statusCode(401) + .body(containsString("Token verification failed")); + } + + @DisplayName("The refresh token does not match the stored one") + @Test + void refresh_withWrongRefreshToken() { + prepareDataplaneRuntime(); + + var authorizationService = DATAPLANE_RUNTIME.getService(DataPlaneAuthorizationService.class); + var edr = authorizationService.createEndpointDataReference(createStartMessage("test-process-id", CONSUMER_DID)) + .orElseThrow(f -> new AssertionError(f.getFailureDetail())); + var refreshToken = "invalid_refresh_token"; + var accessToken = edr.getStringProperty("authorization"); + + RUNTIME_CONFIG.getRefreshApi().baseRequest() + .queryParam("grant_type", "refresh_token") + .queryParam("refresh_token", refreshToken) + .header(AUTHORIZATION, "Bearer " + createAuthToken(accessToken, consumerKey)) + .post("/token") + .then() + .log().ifValidationFails() + .statusCode(401) + .body(containsString("Provided refresh token does not match the stored refresh token.")); + } + + + @DisplayName("The authentication token misses required claims: access_token") @Test - void foo() { - // will be used once the RefreshAPI is here as well + void refresh_invalidAuthenticationToken_missingAccessToken() { + prepareDataplaneRuntime(); + + var authorizationService = DATAPLANE_RUNTIME.getService(DataPlaneAuthorizationService.class); + var edr = authorizationService.createEndpointDataReference(createStartMessage("test-process-id", CONSUMER_DID)) + .orElseThrow(f -> new AssertionError(f.getFailureDetail())); + + var refreshToken = edr.getStringProperty("refreshToken"); + var accessToken = edr.getStringProperty("authorization"); + + var claims = new JWTClaimsSet.Builder() + /* missing: .claim("access_token", accessToken)*/ + .issuer(CONSUMER_DID) + .subject(CONSUMER_DID) + .audience("did:web:bob") + .jwtID(getJwtId(accessToken)) + .build(); + var authToken = createJwt(consumerKey, claims); + + RUNTIME_CONFIG.getRefreshApi().baseRequest() + .queryParam("grant_type", "refresh_token") + .queryParam("refresh_token", refreshToken) + .header(AUTHORIZATION, "Bearer " + authToken) + .post("/token") + .then() + .log().ifValidationFails() + .statusCode(401) + .body(containsString("Required claim 'access_token' not present on token.")); + } + + @DisplayName("The authentication token misses required claims: audience") + @Test + void refresh_invalidAuthenticationToken_missingAudience() { + prepareDataplaneRuntime(); + + var authorizationService = DATAPLANE_RUNTIME.getService(DataPlaneAuthorizationService.class); + var edr = authorizationService.createEndpointDataReference(createStartMessage("test-process-id", CONSUMER_DID)) + .orElseThrow(f -> new AssertionError(f.getFailureDetail())); + + var refreshToken = edr.getStringProperty("refreshToken"); + var accessToken = edr.getStringProperty("authorization"); + + var claims = new JWTClaimsSet.Builder() + .claim("access_token", accessToken) + .issuer(CONSUMER_DID) + .subject(CONSUMER_DID) + /* missing: .audience("did:web:bob")*/ + .jwtID(getJwtId(accessToken)) + .build(); + var authToken = createJwt(consumerKey, claims); + + RUNTIME_CONFIG.getRefreshApi().baseRequest() + .queryParam("grant_type", "refresh_token") + .queryParam("refresh_token", refreshToken) + .header(AUTHORIZATION, "Bearer " + authToken) + .post("/token") + .then() + .log().ifValidationFails() + .statusCode(401) + .body(containsString("Required claim 'aud' not present on token.")); + } + + private void prepareDataplaneRuntime() { + var vault = DATAPLANE_RUNTIME.getContext().getService(Vault.class); + vault.storeSecret(PROVIDER_KEY_ID, providerKey.toJSONString()); + } + + private String createAuthToken(String accessToken, ECKey signerKey) { + var claims = new JWTClaimsSet.Builder() + .claim("access_token", accessToken) + .issuer(CONSUMER_DID) + .subject(CONSUMER_DID) + .audience("did:web:bob") + .jwtID(getJwtId(accessToken)) + .build(); + return createJwt(signerKey, claims); + } + + private String createJwt(ECKey signerKey, JWTClaimsSet claims) { + var header = new JWSHeader.Builder(JWSAlgorithm.ES256).keyID(consumerKey.getKeyID()).build(); + var jwt = new SignedJWT(header, claims); + try { + jwt.sign(new ECDSASigner(signerKey)); + return jwt.serialize(); + } catch (JOSEException e) { + throw new RuntimeException(e); + } + } + + private String getJwtId(String accessToken) { + try { + return SignedJWT.parse(accessToken).getJWTClaimsSet().getJWTID(); + } catch (ParseException e) { + throw new RuntimeException(e); + } + } + + private DataFlowStartMessage createStartMessage(String processId, String audience) { + return DataFlowStartMessage.Builder.newInstance() + .processId(processId) + .sourceDataAddress(DataAddress.Builder.newInstance().type("HttpData").property(EDC_NAMESPACE + "baseUrl", "http://foo.bar/").build()) + .destinationDataAddress(DataAddress.Builder.newInstance().type("HttpData").property(EDC_NAMESPACE + "baseUrl", "http://fizz.buzz").build()) + .flowType(FlowType.PULL) + .participantId("some-participantId") + .assetId("test-asset") + .callbackAddress(URI.create("https://foo.bar/callback")) + .agreementId("test-agreement") + .property("audience", audience) + .build(); } } diff --git a/edc-tests/edc-dataplane/edc-dataplane-tokenrefresh-tests/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/e2e/RuntimeConfig.java b/edc-tests/edc-dataplane/edc-dataplane-tokenrefresh-tests/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/e2e/RuntimeConfig.java index a1ff0e1f5..11c8da8fe 100644 --- a/edc-tests/edc-dataplane/edc-dataplane-tokenrefresh-tests/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/e2e/RuntimeConfig.java +++ b/edc-tests/edc-dataplane/edc-dataplane-tokenrefresh-tests/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/e2e/RuntimeConfig.java @@ -19,33 +19,68 @@ package org.eclipse.tractusx.edc.dataplane.tokenrefresh.e2e; +import io.restassured.specification.RequestSpecification; + +import java.net.URI; import java.util.HashMap; import java.util.Map; +import static io.restassured.RestAssured.given; import static org.eclipse.edc.junit.testfixtures.TestUtils.getFreePort; /** * Configuration baseline for Data-Plane e2e tests */ public class RuntimeConfig { + + private final Endpoint publicApi = new Endpoint(URI.create("http://localhost:%d/public".formatted(getFreePort()))); + private final Endpoint signalingApi = new Endpoint(URI.create("http://localhost:%d/signaling".formatted(getFreePort()))); + private final Endpoint refreshApi = publicApi; + private final Endpoint defaultApi = new Endpoint(URI.create("http://localhost:%d/api".formatted(getFreePort()))); + /** * Configures the data plane token endpoint, and all relevant HTTP contexts */ - public static Map baseConfig(String signalingPath, int signalingPort) { + public Map baseConfig() { return new HashMap<>() { { put("edc.dataplane.token.validation.endpoint", "http://token-validation.com"); - put("web.http.path", "/api"); - put("web.http.port", String.valueOf(getFreePort())); - put("web.http.public.path", "/public"); - put("web.http.public.port", String.valueOf(getFreePort())); - put("web.http.consumer.api.path", "/api/consumer"); - put("web.http.consumer.api.port", String.valueOf(getFreePort())); - put("web.http.signaling.path", signalingPath); - put("web.http.signaling.port", String.valueOf(signalingPort)); + put("web.http.path", defaultApi.url().getPath()); + put("web.http.port", String.valueOf(defaultApi.url().getPort())); + put("web.http.public.path", publicApi.url().getPath()); + put("web.http.public.port", String.valueOf(publicApi.url().getPort())); + put("web.http.signaling.path", signalingApi.url().getPath()); + put("web.http.signaling.port", String.valueOf(signalingApi.url().getPort())); } }; } + public Endpoint getPublicApi() { + return publicApi; + } + + public Endpoint getSignalingApi() { + return signalingApi; + } + + public Endpoint getRefreshApi() { + return refreshApi; + } + + public Endpoint getDefaultApi() { + return defaultApi; + } + + public record Endpoint(URI url, Map headers) { + public Endpoint(URI url) { + this(url, Map.of()); + } + + public RequestSpecification baseRequest() { + return given().baseUri(url.toString()).headers(headers); + } + + } + } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 4f9b5dfdf..c36742228 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -160,7 +160,8 @@ edc-dpf-azblob = { module = "org.eclipse.edc:data-plane-azure-storage", version. edc-dpf-http = { module = "org.eclipse.edc:data-plane-http", version.ref = "edc" } edc-dpf-oauth2 = { module = "org.eclipse.edc:data-plane-http-oauth2", version.ref = "edc" } edc-dpf-api-control = { module = "org.eclipse.edc:data-plane-control-api", version.ref = "edc" } -edc-dpf-api-public = { module = "org.eclipse.edc:data-plane-public-api", version.ref = "edc" } +edc-dpf-api-public-v1 = { module = "org.eclipse.edc:data-plane-public-api", version.ref = "edc" } +edc-dpf-api-public-v2 = { module = "org.eclipse.edc:data-plane-public-api-v2", version.ref = "edc" } edc-dpf-api-signaling = { module = "org.eclipse.edc:data-plane-signaling-api", version.ref = "edc" } diff --git a/settings.gradle.kts b/settings.gradle.kts index 5ede9eab1..dffc3350d 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -63,6 +63,7 @@ include(":edc-extensions:dataplane:dataplane-proxy:edc-dataplane-proxy-provider- include(":edc-extensions:dataplane:dataplane-proxy:edc-dataplane-proxy-provider-api") include(":edc-extensions:dataplane:dataplane-selector-configuration") include(":edc-extensions:dataplane:dataplane-token-refresh:token-refresh-core") +include(":edc-extensions:dataplane:dataplane-token-refresh:token-refresh-api") // test modules include(":edc-tests:e2e-tests") From bd6f22d4b68794f1b3c3bdc2c6dad40863ab1d7f Mon Sep 17 00:00:00 2001 From: Paul Latzelsperger <43503240+paullatzelsperger@users.noreply.github.com> Date: Tue, 12 Mar 2024 22:29:02 +0100 Subject: [PATCH 052/100] feat: add expiry check to DataPlaneTokenRefreshServiceImpl (#1124) --- ...DataPlaneTokenRefreshServiceExtension.java | 11 ++- .../DataPlaneTokenRefreshServiceImpl.java | 32 +++++++-- ...eTokenRefreshServiceImplComponentTest.java | 69 +++++++++++++++++-- .../DataPlaneTokenRefreshServiceImplTest.java | 3 +- 4 files changed, 99 insertions(+), 16 deletions(-) diff --git a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceExtension.java b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceExtension.java index 8f03fc2f3..8f2355b3d 100644 --- a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceExtension.java +++ b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceExtension.java @@ -25,6 +25,7 @@ import org.eclipse.edc.runtime.metamodel.annotation.Extension; import org.eclipse.edc.runtime.metamodel.annotation.Inject; import org.eclipse.edc.runtime.metamodel.annotation.Provider; +import org.eclipse.edc.runtime.metamodel.annotation.Setting; import org.eclipse.edc.spi.security.PrivateKeyResolver; import org.eclipse.edc.spi.system.ServiceExtension; import org.eclipse.edc.spi.system.ServiceExtensionContext; @@ -34,6 +35,7 @@ import org.jetbrains.annotations.NotNull; import java.security.PrivateKey; +import java.time.Clock; import java.util.function.Supplier; import static org.eclipse.edc.connector.dataplane.spi.TransferDataPlaneConfig.TOKEN_SIGNER_PRIVATE_KEY_ALIAS; @@ -42,15 +44,19 @@ @Extension(value = NAME) public class DataPlaneTokenRefreshServiceExtension implements ServiceExtension { public static final String NAME = "DataPlane Token Refresh Service extension"; + public static final int DEFAULT_TOKEN_EXPIRY_TOLERANCE_SECONDS = 5; + @Setting(value = "Token expiry tolerance period in seconds to allow for clock skew", defaultValue = "" + DEFAULT_TOKEN_EXPIRY_TOLERANCE_SECONDS) + public static final String TOKEN_EXPIRY_TOLERANCE_SECONDS_PROPERTY = "edc.dataplane.api.token.expiry.tolerance"; @Inject private TokenValidationService tokenValidationService; @Inject private DidPublicKeyResolver didPkResolver; @Inject private AccessTokenDataStore accessTokenDataStore; - @Inject private PrivateKeyResolver privateKeyResolver; + @Inject + private Clock clock; private DataPlaneTokenRefreshServiceImpl tokenRefreshService; @Override @@ -73,7 +79,8 @@ public DataPlaneTokenRefreshService createRefreshTokenService(ServiceExtensionCo @NotNull private DataPlaneTokenRefreshServiceImpl getTokenRefreshService(ServiceExtensionContext context) { if (tokenRefreshService == null) { - tokenRefreshService = new DataPlaneTokenRefreshServiceImpl(tokenValidationService, didPkResolver, accessTokenDataStore, new JwtGenerationService(), getPrivateKeySupplier(context), context.getMonitor(), "foo.bar"); + var epsilon = context.getConfig().getInteger(TOKEN_EXPIRY_TOLERANCE_SECONDS_PROPERTY, DEFAULT_TOKEN_EXPIRY_TOLERANCE_SECONDS); + tokenRefreshService = new DataPlaneTokenRefreshServiceImpl(clock, tokenValidationService, didPkResolver, accessTokenDataStore, new JwtGenerationService(), getPrivateKeySupplier(context), context.getMonitor(), null, epsilon); } return tokenRefreshService; } diff --git a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImpl.java b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImpl.java index 7e6fdc0f1..005b2bed3 100644 --- a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImpl.java +++ b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImpl.java @@ -23,12 +23,14 @@ import org.eclipse.edc.connector.dataplane.spi.iam.DataPlaneAccessTokenService; import org.eclipse.edc.connector.dataplane.spi.store.AccessTokenDataStore; import org.eclipse.edc.iam.did.spi.resolution.DidPublicKeyResolver; +import org.eclipse.edc.jwt.spi.JwtRegisteredClaimNames; import org.eclipse.edc.spi.iam.ClaimToken; import org.eclipse.edc.spi.iam.TokenParameters; import org.eclipse.edc.spi.iam.TokenRepresentation; import org.eclipse.edc.spi.monitor.Monitor; import org.eclipse.edc.spi.result.Result; import org.eclipse.edc.spi.types.domain.DataAddress; +import org.eclipse.edc.token.rules.ExpirationIssuedAtValidationRule; import org.eclipse.edc.token.spi.TokenDecorator; import org.eclipse.edc.token.spi.TokenGenerationService; import org.eclipse.edc.token.spi.TokenValidationRule; @@ -40,6 +42,7 @@ import org.eclipse.tractusx.edc.dataplane.tokenrefresh.spi.model.TokenResponse; import java.security.PrivateKey; +import java.time.Clock; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -51,6 +54,7 @@ import java.util.stream.Stream; import static org.eclipse.edc.jwt.spi.JwtRegisteredClaimNames.AUDIENCE; +import static org.eclipse.edc.jwt.spi.JwtRegisteredClaimNames.EXPIRATION_TIME; /** * This implementation of the {@link DataPlaneTokenRefreshService} validates an incoming authentication token. @@ -60,10 +64,8 @@ public class DataPlaneTokenRefreshServiceImpl implements DataPlaneTokenRefreshSe public static final String TOKEN_ID_CLAIM = "jti"; public static final String REFRESH_TOKEN_PROPERTY = "refreshToken"; private static final Long DEFAULT_EXPIRY_IN_SECONDS = 60 * 5L; - private final List authenticationTokenValidationRules = List.of(new IssuerEqualsSubjectRule(), - new ClaimIsPresentRule(AUDIENCE), // we don't check the contents, only it is present - new ClaimIsPresentRule(ACCESS_TOKEN_CLAIM), - new ClaimIsPresentRule(TOKEN_ID_CLAIM)); + private final List authenticationTokenValidationRules; + private final List accessTokenRules; private final TokenValidationService tokenValidationService; private final DidPublicKeyResolver publicKeyResolver; private final AccessTokenDataStore accessTokenDataStore; @@ -71,15 +73,16 @@ public class DataPlaneTokenRefreshServiceImpl implements DataPlaneTokenRefreshSe private final Supplier privateKeySupplier; private final Monitor monitor; private final String refreshEndpoint; + private final Clock clock; - public DataPlaneTokenRefreshServiceImpl(TokenValidationService tokenValidationService, + public DataPlaneTokenRefreshServiceImpl(Clock clock, TokenValidationService tokenValidationService, DidPublicKeyResolver publicKeyResolver, AccessTokenDataStore accessTokenDataStore, TokenGenerationService tokenGenerationService, Supplier privateKeySupplier, Monitor monitor, - String refreshEndpoint) { + String refreshEndpoint, int tokenExpiryToleranceSeconds) { this.tokenValidationService = tokenValidationService; this.publicKeyResolver = publicKeyResolver; this.accessTokenDataStore = accessTokenDataStore; @@ -87,6 +90,15 @@ public DataPlaneTokenRefreshServiceImpl(TokenValidationService tokenValidationSe this.privateKeySupplier = privateKeySupplier; this.monitor = monitor; this.refreshEndpoint = refreshEndpoint; + this.clock = clock; + authenticationTokenValidationRules = List.of(new IssuerEqualsSubjectRule(), + new ClaimIsPresentRule(AUDIENCE), // we don't check the contents, only it is present + new ClaimIsPresentRule(ACCESS_TOKEN_CLAIM), + new ClaimIsPresentRule(TOKEN_ID_CLAIM)); + accessTokenRules = List.of(new IssuerEqualsSubjectRule(), + new ClaimIsPresentRule(AUDIENCE), + new ClaimIsPresentRule(TOKEN_ID_CLAIM), + new ExpirationIssuedAtValidationRule(clock, tokenExpiryToleranceSeconds)); } /** @@ -192,7 +204,7 @@ public Result obtainToken(TokenParameters tokenParameters, @Override public Result resolve(String token) { - return resolveToken(token, authenticationTokenValidationRules); + return resolveToken(token, accessTokenRules); } /** @@ -213,6 +225,12 @@ private Result createToken(TokenParameters tokenParam TokenDecorator tokenIdDecorator = params -> params.claims(TOKEN_ID_CLAIM, tokenId.get()); allDecorators.add(tokenIdDecorator); } + //if there is not "exp" header on the token params, we'll configure one + if (!tokenParameters.getClaims().containsKey(JwtRegisteredClaimNames.EXPIRATION_TIME)) { + monitor.info("No '%s' claim found on TokenParameters. Will use the default of %d seconds".formatted(EXPIRATION_TIME, DEFAULT_EXPIRY_IN_SECONDS)); + var exp = clock.instant().plusSeconds(DEFAULT_EXPIRY_IN_SECONDS).getEpochSecond(); + allDecorators.add(tp -> tp.claims(JwtRegisteredClaimNames.EXPIRATION_TIME, exp)); + } return tokenGenerationService.generate(privateKeySupplier, allDecorators.toArray(new TokenDecorator[0])) .map(tr -> new TokenRepresentationWithId(tokenId.get(), tr)); diff --git a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImplComponentTest.java b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImplComponentTest.java index dab07a6e3..a8d5b72e9 100644 --- a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImplComponentTest.java +++ b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImplComponentTest.java @@ -45,6 +45,7 @@ import org.junit.jupiter.api.Test; import java.text.ParseException; +import java.time.Clock; import java.time.Instant; import java.util.List; import java.util.Map; @@ -71,23 +72,26 @@ class DataPlaneTokenRefreshServiceImplComponentTest { private DataPlaneTokenRefreshServiceImpl tokenRefreshService; private InMemoryAccessTokenDataStore tokenDataStore; private ECKey consumerKey; + private ECKey providerKey; @BeforeEach void setup() throws JOSEException { - var providerKey = new ECKeyGenerator(Curve.P_384).keyID(PROVIDER_BPN + "#provider-key").keyUse(KeyUse.SIGNATURE).generate(); + providerKey = new ECKeyGenerator(Curve.P_384).keyID(PROVIDER_BPN + "#provider-key").keyUse(KeyUse.SIGNATURE).generate(); consumerKey = new ECKeyGenerator(Curve.P_384).keyID(CONSUMER_DID + "#consumer-key").keyUse(KeyUse.SIGNATURE).generate(); var privateKey = providerKey.toPrivateKey(); tokenDataStore = new InMemoryAccessTokenDataStore(CriterionOperatorRegistryImpl.ofDefaults()); - tokenRefreshService = new DataPlaneTokenRefreshServiceImpl(new TokenValidationServiceImpl(), + tokenRefreshService = new DataPlaneTokenRefreshServiceImpl(Clock.systemUTC(), + new TokenValidationServiceImpl(), didPkResolverMock, tokenDataStore, new JwtGenerationService(), () -> privateKey, mock(), - TEST_REFRESH_ENDPOINT); + TEST_REFRESH_ENDPOINT, + 1); when(didPkResolverMock.resolveKey(eq(consumerKey.getKeyID()))).thenReturn(Result.success(consumerKey.toPublicKey())); when(didPkResolverMock.resolveKey(eq(providerKey.getKeyID()))).thenReturn(Result.success(providerKey.toPublicKey())); @@ -106,7 +110,8 @@ void obtainToken() { .containsKey("agreement_id") .containsEntry("iss", PROVIDER_BPN) .containsEntry("sub", PROVIDER_BPN) - .containsEntry("aud", List.of(CONSUMER_BPN)); + .containsEntry("aud", List.of(CONSUMER_BPN)) + .containsKey("exp"); // assert additional properties -> refresh token assertThat(edr.getContent().getAdditional()) @@ -235,6 +240,52 @@ void refresh_whenIssNotEqualToSub() throws JOSEException { .isEqualTo("The 'iss' and 'sub' claims must be non-null and identical."); } + @DisplayName("Verify that resolving an expired token fails") + @Test + void resolve_whenExpired_shouldFail() { + var tokenId = "test-token-id"; + var edr = tokenRefreshService.obtainToken(tokenParamsBuilder(tokenId) + //token was issued 10min ago, and expired 5min ago + .claims(JwtRegisteredClaimNames.ISSUED_AT, Instant.now().minusSeconds(600).getEpochSecond()) + .claims(JwtRegisteredClaimNames.EXPIRATION_TIME, Instant.now().minusSeconds(300).getEpochSecond()) + .build(), + DataAddress.Builder.newInstance().type("test-type").build(), Map.of("audience", CONSUMER_DID)) + .orElseThrow(f -> new RuntimeException(f.getFailureDetail())); + + assertThat(tokenRefreshService.resolve(edr.getToken())).isFailed() + .detail().isEqualTo("Token has expired (exp)"); + + } + + @DisplayName("Verify that resolving a valid token succeeds") + @Test + void resolve_success() { + var tokenId = "test-token-id"; + var edr = tokenRefreshService.obtainToken(tokenParamsBuilder(tokenId) + .claims(JwtRegisteredClaimNames.ISSUED_AT, Instant.now().getEpochSecond()) + .build(), + DataAddress.Builder.newInstance().type("test-type").build(), Map.of("audience", CONSUMER_DID)) + .orElseThrow(f -> new RuntimeException(f.getFailureDetail())); + + assertThat(tokenRefreshService.resolve(edr.getToken())).isSucceeded(); + } + + @DisplayName("Verify that attempting to resolve a non-existing token results in a failure") + @Test + void resolve_notFound() { + var tokenId = "test-token-id"; + var edr = tokenRefreshService.obtainToken(tokenParamsBuilder(tokenId) + .claims(JwtRegisteredClaimNames.ISSUED_AT, Instant.now().getEpochSecond()) + .build(), + DataAddress.Builder.newInstance().type("test-type").build(), Map.of("audience", CONSUMER_DID)) + .orElseThrow(f -> new RuntimeException(f.getFailureDetail())); + tokenDataStore.deleteById(tokenId).orElseThrow(f -> new AssertionError(f.getFailureDetail())); + + assertThat(tokenRefreshService.resolve(edr.getToken())) + .isFailed() + .detail().isEqualTo("AccessTokenData with ID '%s' does not exist.".formatted(tokenId)); + } + private JWTClaimsSet.Builder getAuthTokenClaims(String tokenId, String accessToken) { return new JWTClaimsSet.Builder() .jwtID(tokenId) @@ -245,17 +296,23 @@ private JWTClaimsSet.Builder getAuthTokenClaims(String tokenId, String accessTok } private TokenParameters tokenParams(String id) { + return tokenParamsBuilder(id).build(); + } + + private TokenParameters.Builder tokenParamsBuilder(String id) { return TokenParameters.Builder.newInstance() .claims(JwtRegisteredClaimNames.JWT_ID, id) .claims(JwtRegisteredClaimNames.AUDIENCE, CONSUMER_BPN) .claims(JwtRegisteredClaimNames.ISSUER, PROVIDER_BPN) .claims(JwtRegisteredClaimNames.SUBJECT, PROVIDER_BPN) - .claims(JwtRegisteredClaimNames.ISSUED_AT, Instant.now().toEpochMilli()) // todo: milli or second? + .claims(JwtRegisteredClaimNames.EXPIRATION_TIME, Instant.now().plusSeconds(60).getEpochSecond()) + .claims(JwtRegisteredClaimNames.ISSUED_AT, Instant.now().getEpochSecond()) .claims(CLAIM_AGREEMENT_ID, "test-agreement-id") .claims(CLAIM_ASSET_ID, "test-asset-id") .claims(CLAIM_PROCESS_ID, "test-process-id") .claims(CLAIM_FLOW_TYPE, FlowType.PULL.toString()) - .build(); + .header("kid", providerKey.getKeyID()); + } private Map asClaims(String serializedJwt) { diff --git a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImplTest.java b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImplTest.java index 7b2a6f34b..f57d674ea 100644 --- a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImplTest.java +++ b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImplTest.java @@ -33,6 +33,7 @@ import org.eclipse.edc.token.spi.TokenValidationService; import org.junit.jupiter.api.Test; +import java.time.Clock; import java.util.Map; import java.util.regex.Pattern; @@ -58,7 +59,7 @@ class DataPlaneTokenRefreshServiceImplTest { private final TokenValidationService tokenValidationService = mock(); private final DidPublicKeyResolver didPublicKeyResolver = mock(); - private final DataPlaneTokenRefreshServiceImpl accessTokenService = new DataPlaneTokenRefreshServiceImpl(tokenValidationService, didPublicKeyResolver, accessTokenDataStore, tokenGenService, mock(), mock(), "https://example.com"); + private final DataPlaneTokenRefreshServiceImpl accessTokenService = new DataPlaneTokenRefreshServiceImpl(Clock.systemUTC(), tokenValidationService, didPublicKeyResolver, accessTokenDataStore, tokenGenService, mock(), mock(), "https://example.com", 1); @Test void obtainToken() { From a3b4c06a89d6bf9b2bf606721e26329db71e72b0 Mon Sep 17 00:00:00 2001 From: Paul Latzelsperger <43503240+paullatzelsperger@users.noreply.github.com> Date: Thu, 14 Mar 2024 15:56:24 +0100 Subject: [PATCH 053/100] feat: store refresh token in vault (#1128) * feat: store refresh token in vault * checkstyle, dependencies --- DEPENDENCIES | 74 +++++------ .../edc/edr/core/manager/EdrManagerImpl.java | 1 - ...DataPlaneTokenRefreshServiceExtension.java | 10 +- .../DataPlaneTokenRefreshServiceImpl.java | 74 +++++++---- .../tokenrefresh/core/RefreshToken.java | 24 ++++ .../core/rules/AuthTokenAudienceRule.java | 57 +++++++++ .../core/rules/RefreshTokenMustExistRule.java | 76 ----------- .../rules/RefreshTokenValidationRule.java | 75 +++++++++++ ...eTokenRefreshServiceImplComponentTest.java | 26 ++-- .../DataPlaneTokenRefreshServiceImplTest.java | 5 +- .../tokenrefresh/core/TestFunctions.java | 32 +++++ .../core/rules/AuthTokenAudienceRuleTest.java | 80 ++++++++++++ .../rules/RefreshTokenMustExistRuleTest.java | 121 ------------------ .../rules/RefreshTokenValidationRuleTest.java | 114 +++++++++++++++++ 14 files changed, 490 insertions(+), 279 deletions(-) create mode 100644 edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/RefreshToken.java create mode 100644 edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/rules/AuthTokenAudienceRule.java delete mode 100644 edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/rules/RefreshTokenMustExistRule.java create mode 100644 edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/rules/RefreshTokenValidationRule.java create mode 100644 edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/TestFunctions.java create mode 100644 edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/rules/AuthTokenAudienceRuleTest.java delete mode 100644 edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/rules/RefreshTokenMustExistRuleTest.java create mode 100644 edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/rules/RefreshTokenValidationRuleTest.java diff --git a/DEPENDENCIES b/DEPENDENCIES index 32a250533..bb4a66ac1 100644 --- a/DEPENDENCIES +++ b/DEPENDENCIES @@ -3,19 +3,18 @@ maven/mavencentral/com.apicatalog/iron-ed25519-cryptosuite-2020/0.8.1, Apache-2. maven/mavencentral/com.apicatalog/iron-verifiable-credentials/0.8.1, Apache-2.0, approved, #9234 maven/mavencentral/com.apicatalog/titanium-json-ld/1.0.0, Apache-2.0, approved, clearlydefined maven/mavencentral/com.apicatalog/titanium-json-ld/1.3.1, Apache-2.0, approved, #8912 -maven/mavencentral/com.apicatalog/titanium-json-ld/1.3.3, Apache-2.0, approved, #8912 -maven/mavencentral/com.apicatalog/titanium-json-ld/1.4.0, , restricted, clearlydefined +maven/mavencentral/com.apicatalog/titanium-json-ld/1.4.0, Apache-2.0, approved, #13683 maven/mavencentral/com.azure/azure-core-http-netty/1.13.11, MIT AND Apache-2.0, approved, #7948 maven/mavencentral/com.azure/azure-core-http-netty/1.14.0, MIT AND Apache-2.0, approved, #13238 maven/mavencentral/com.azure/azure-core-http-netty/1.14.1, MIT AND Apache-2.0, approved, #13238 maven/mavencentral/com.azure/azure-core/1.45.1, MIT AND Apache-2.0, approved, #11845 maven/mavencentral/com.azure/azure-core/1.46.0, MIT AND Apache-2.0, approved, #13234 -maven/mavencentral/com.azure/azure-core/1.47.0, , restricted, clearlydefined +maven/mavencentral/com.azure/azure-core/1.47.0, MIT AND Apache-2.0, approved, #13678 maven/mavencentral/com.azure/azure-identity/1.11.2, MIT AND Apache-2.0, approved, #13237 maven/mavencentral/com.azure/azure-identity/1.11.3, MIT AND Apache-2.0, approved, #13237 maven/mavencentral/com.azure/azure-json/1.1.0, MIT AND Apache-2.0, approved, #10547 maven/mavencentral/com.azure/azure-security-keyvault-secrets/4.7.3, MIT, approved, #10868 -maven/mavencentral/com.azure/azure-security-keyvault-secrets/4.8.0, , restricted, clearlydefined +maven/mavencentral/com.azure/azure-security-keyvault-secrets/4.8.0, MIT, approved, #13690 maven/mavencentral/com.azure/azure-storage-blob/12.25.2, MIT, approved, #13400 maven/mavencentral/com.azure/azure-storage-common/12.24.2, MIT, approved, #13402 maven/mavencentral/com.azure/azure-storage-internal-avro/12.10.2, MIT, approved, #13399 @@ -111,9 +110,9 @@ maven/mavencentral/dev.failsafe/failsafe/3.3.2, Apache-2.0, approved, #9268 maven/mavencentral/info.picocli/picocli/4.7.5, Apache-2.0, approved, #4365 maven/mavencentral/io.github.classgraph/classgraph/4.8.154, MIT, approved, CQ22530 maven/mavencentral/io.github.classgraph/classgraph/4.8.162, MIT, approved, CQ22530 -maven/mavencentral/io.micrometer/micrometer-commons/1.12.3, Apache-2.0 AND (Apache-2.0 AND MIT), approved, #11679 -maven/mavencentral/io.micrometer/micrometer-core/1.12.3, Apache-2.0 AND (Apache-2.0 AND MIT), approved, #11678 -maven/mavencentral/io.micrometer/micrometer-observation/1.12.3, Apache-2.0, approved, #11680 +maven/mavencentral/io.micrometer/micrometer-commons/1.12.4, Apache-2.0 AND (Apache-2.0 AND MIT), approved, #11679 +maven/mavencentral/io.micrometer/micrometer-core/1.12.4, Apache-2.0 AND (Apache-2.0 AND MIT), approved, #11678 +maven/mavencentral/io.micrometer/micrometer-observation/1.12.4, Apache-2.0, approved, #11680 maven/mavencentral/io.netty/netty-buffer/4.1.100.Final, Apache-2.0, approved, CQ21842 maven/mavencentral/io.netty/netty-buffer/4.1.101.Final, Apache-2.0, approved, CQ21842 maven/mavencentral/io.netty/netty-buffer/4.1.107.Final, Apache-2.0, approved, CQ21842 @@ -184,9 +183,9 @@ maven/mavencentral/io.swagger.core.v3/swagger-models/2.2.15, Apache-2.0, approve maven/mavencentral/jakarta.activation/jakarta.activation-api/1.2.1, EPL-2.0 OR BSD-3-Clause OR GPL-2.0-only with Classpath-exception-2.0, approved, ee4j.jaf maven/mavencentral/jakarta.activation/jakarta.activation-api/2.1.0, EPL-2.0 OR BSD-3-Clause OR GPL-2.0-only with Classpath-exception-2.0, approved, ee4j.jaf maven/mavencentral/jakarta.annotation/jakarta.annotation-api/2.1.1, EPL-2.0 OR GPL-2.0-only with Classpath-exception-2.0, approved, ee4j.ca -maven/mavencentral/jakarta.inject/jakarta.inject-api/2.0.1, Apache-2.0, approved, clearlydefined -maven/mavencentral/jakarta.json/jakarta.json-api/2.1.1, EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0, approved, #7907 -maven/mavencentral/jakarta.transaction/jakarta.transaction-api/2.0.0, EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0, approved, #7697 +maven/mavencentral/jakarta.inject/jakarta.inject-api/2.0.1, Apache-2.0, approved, ee4j.cdi +maven/mavencentral/jakarta.json/jakarta.json-api/2.1.1, EPL-2.0 OR GPL-2.0-only with Classpath-exception-2.0, approved, ee4j.jsonp +maven/mavencentral/jakarta.transaction/jakarta.transaction-api/2.0.0, EPL-2.0 OR GPL-2.0-only with Classpath-exception-2.0, approved, ee4j.jta maven/mavencentral/jakarta.validation/jakarta.validation-api/2.0.2, Apache-2.0, approved, ee4j.validation maven/mavencentral/jakarta.validation/jakarta.validation-api/3.0.2, Apache-2.0, approved, ee4j.validation maven/mavencentral/jakarta.ws.rs/jakarta.ws.rs-api/3.1.0, EPL-2.0 OR GPL-2.0-only with Classpath-exception-2.0, approved, ee4j.rest @@ -290,6 +289,7 @@ maven/mavencentral/org.eclipse.edc/crypto-common/0.5.2-SNAPSHOT, Apache-2.0, app maven/mavencentral/org.eclipse.edc/data-address-http-data-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/data-plane-aws-s3/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/data-plane-azure-storage/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-client-embedded/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/data-plane-client/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/data-plane-control-api/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/data-plane-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc @@ -519,58 +519,58 @@ maven/mavencentral/org.xmlresolver/xmlresolver/5.2.2, Apache-2.0, approved, clea maven/mavencentral/org.yaml/snakeyaml/2.0, Apache-2.0 AND (Apache-2.0 OR BSD-3-Clause OR EPL-1.0 OR GPL-2.0-or-later OR LGPL-2.1-or-later), approved, #7275 maven/mavencentral/org.yaml/snakeyaml/2.2, Apache-2.0 AND (Apache-2.0 OR BSD-3-Clause OR EPL-1.0 OR GPL-2.0-or-later OR LGPL-2.1-or-later), approved, #10232 maven/mavencentral/software.amazon.awssdk/annotations/2.24.10, Apache-2.0, approved, #13251 -maven/mavencentral/software.amazon.awssdk/annotations/2.25.1, , restricted, clearlydefined +maven/mavencentral/software.amazon.awssdk/annotations/2.25.1, Apache-2.0, approved, #13691 maven/mavencentral/software.amazon.awssdk/apache-client/2.24.10, Apache-2.0, approved, #13257 -maven/mavencentral/software.amazon.awssdk/apache-client/2.25.1, , restricted, clearlydefined +maven/mavencentral/software.amazon.awssdk/apache-client/2.25.1, Apache-2.0, approved, #13687 maven/mavencentral/software.amazon.awssdk/arns/2.24.10, Apache-2.0, approved, #13243 -maven/mavencentral/software.amazon.awssdk/arns/2.25.1, , restricted, clearlydefined +maven/mavencentral/software.amazon.awssdk/arns/2.25.1, Apache-2.0, approved, #13695 maven/mavencentral/software.amazon.awssdk/auth/2.24.10, Apache-2.0, approved, #13256 -maven/mavencentral/software.amazon.awssdk/auth/2.25.1, , restricted, clearlydefined +maven/mavencentral/software.amazon.awssdk/auth/2.25.1, Apache-2.0, approved, #13692 maven/mavencentral/software.amazon.awssdk/aws-core/2.24.10, Apache-2.0, approved, #13240 -maven/mavencentral/software.amazon.awssdk/aws-core/2.25.1, , restricted, clearlydefined +maven/mavencentral/software.amazon.awssdk/aws-core/2.25.1, Apache-2.0, approved, #13702 maven/mavencentral/software.amazon.awssdk/aws-query-protocol/2.24.10, Apache-2.0, approved, #13262 -maven/mavencentral/software.amazon.awssdk/aws-query-protocol/2.25.1, , restricted, clearlydefined +maven/mavencentral/software.amazon.awssdk/aws-query-protocol/2.25.1, Apache-2.0, approved, #13701 maven/mavencentral/software.amazon.awssdk/aws-xml-protocol/2.24.10, Apache-2.0, approved, #13247 -maven/mavencentral/software.amazon.awssdk/aws-xml-protocol/2.25.1, , restricted, clearlydefined +maven/mavencentral/software.amazon.awssdk/aws-xml-protocol/2.25.1, Apache-2.0, approved, #13684 maven/mavencentral/software.amazon.awssdk/checksums-spi/2.24.10, Apache-2.0, approved, #13245 -maven/mavencentral/software.amazon.awssdk/checksums-spi/2.25.1, , restricted, clearlydefined +maven/mavencentral/software.amazon.awssdk/checksums-spi/2.25.1, Apache-2.0, approved, #13686 maven/mavencentral/software.amazon.awssdk/checksums/2.24.10, Apache-2.0, approved, #13242 -maven/mavencentral/software.amazon.awssdk/checksums/2.25.1, , restricted, clearlydefined +maven/mavencentral/software.amazon.awssdk/checksums/2.25.1, Apache-2.0, approved, #13677 maven/mavencentral/software.amazon.awssdk/crt-core/2.24.10, Apache-2.0, approved, #13252 -maven/mavencentral/software.amazon.awssdk/crt-core/2.25.1, , restricted, clearlydefined +maven/mavencentral/software.amazon.awssdk/crt-core/2.25.1, Apache-2.0, approved, #13705 maven/mavencentral/software.amazon.awssdk/endpoints-spi/2.24.10, Apache-2.0, approved, #13246 -maven/mavencentral/software.amazon.awssdk/endpoints-spi/2.25.1, , restricted, clearlydefined +maven/mavencentral/software.amazon.awssdk/endpoints-spi/2.25.1, Apache-2.0, approved, #13681 maven/mavencentral/software.amazon.awssdk/http-auth-aws/2.24.10, Apache-2.0, approved, #13253 -maven/mavencentral/software.amazon.awssdk/http-auth-aws/2.25.1, , restricted, clearlydefined +maven/mavencentral/software.amazon.awssdk/http-auth-aws/2.25.1, Apache-2.0, approved, #13696 maven/mavencentral/software.amazon.awssdk/http-auth-spi/2.24.10, Apache-2.0, approved, #13264 -maven/mavencentral/software.amazon.awssdk/http-auth-spi/2.25.1, , restricted, clearlydefined +maven/mavencentral/software.amazon.awssdk/http-auth-spi/2.25.1, Apache-2.0, approved, #13704 maven/mavencentral/software.amazon.awssdk/http-auth/2.24.10, Apache-2.0, approved, #13248 -maven/mavencentral/software.amazon.awssdk/http-auth/2.25.1, , restricted, clearlydefined +maven/mavencentral/software.amazon.awssdk/http-auth/2.25.1, Apache-2.0, approved, #13682 maven/mavencentral/software.amazon.awssdk/http-client-spi/2.24.10, Apache-2.0, approved, #13259 -maven/mavencentral/software.amazon.awssdk/http-client-spi/2.25.1, , restricted, clearlydefined +maven/mavencentral/software.amazon.awssdk/http-client-spi/2.25.1, Apache-2.0, approved, #13706 maven/mavencentral/software.amazon.awssdk/iam/2.24.10, Apache-2.0, approved, #13444 maven/mavencentral/software.amazon.awssdk/identity-spi/2.24.10, Apache-2.0, approved, #13244 -maven/mavencentral/software.amazon.awssdk/identity-spi/2.25.1, , restricted, clearlydefined +maven/mavencentral/software.amazon.awssdk/identity-spi/2.25.1, Apache-2.0, approved, #13685 maven/mavencentral/software.amazon.awssdk/json-utils/2.24.10, Apache-2.0, approved, #13261 -maven/mavencentral/software.amazon.awssdk/json-utils/2.25.1, , restricted, clearlydefined +maven/mavencentral/software.amazon.awssdk/json-utils/2.25.1, Apache-2.0, approved, #13698 maven/mavencentral/software.amazon.awssdk/metrics-spi/2.24.10, Apache-2.0, approved, #13239 -maven/mavencentral/software.amazon.awssdk/metrics-spi/2.25.1, , restricted, clearlydefined +maven/mavencentral/software.amazon.awssdk/metrics-spi/2.25.1, Apache-2.0, approved, #13680 maven/mavencentral/software.amazon.awssdk/netty-nio-client/2.24.10, Apache-2.0, approved, #13260 -maven/mavencentral/software.amazon.awssdk/netty-nio-client/2.25.1, , restricted, clearlydefined +maven/mavencentral/software.amazon.awssdk/netty-nio-client/2.25.1, Apache-2.0, approved, #13693 maven/mavencentral/software.amazon.awssdk/profiles/2.24.10, Apache-2.0, approved, #13258 -maven/mavencentral/software.amazon.awssdk/profiles/2.25.1, , restricted, clearlydefined +maven/mavencentral/software.amazon.awssdk/profiles/2.25.1, Apache-2.0, approved, #13697 maven/mavencentral/software.amazon.awssdk/protocol-core/2.24.10, Apache-2.0, approved, #13241 -maven/mavencentral/software.amazon.awssdk/protocol-core/2.25.1, , restricted, clearlydefined +maven/mavencentral/software.amazon.awssdk/protocol-core/2.25.1, Apache-2.0, approved, #13679 maven/mavencentral/software.amazon.awssdk/regions/2.24.10, Apache-2.0, approved, #13255 -maven/mavencentral/software.amazon.awssdk/regions/2.25.1, , restricted, clearlydefined -maven/mavencentral/software.amazon.awssdk/s3-transfer-manager/2.25.1, , restricted, clearlydefined +maven/mavencentral/software.amazon.awssdk/regions/2.25.1, Apache-2.0, approved, #13694 +maven/mavencentral/software.amazon.awssdk/s3-transfer-manager/2.25.1, Apache-2.0, approved, #13699 maven/mavencentral/software.amazon.awssdk/s3/2.24.10, Apache-2.0, approved, #13254 -maven/mavencentral/software.amazon.awssdk/s3/2.25.1, , restricted, clearlydefined +maven/mavencentral/software.amazon.awssdk/s3/2.25.1, Apache-2.0, approved, #13688 maven/mavencentral/software.amazon.awssdk/sdk-core/2.24.10, Apache-2.0, approved, #13265 -maven/mavencentral/software.amazon.awssdk/sdk-core/2.25.1, , restricted, clearlydefined +maven/mavencentral/software.amazon.awssdk/sdk-core/2.25.1, Apache-2.0, approved, #13700 maven/mavencentral/software.amazon.awssdk/sts/2.24.10, Apache-2.0, approved, #13442 maven/mavencentral/software.amazon.awssdk/third-party-jackson-core/2.24.10, Apache-2.0, approved, #13249 -maven/mavencentral/software.amazon.awssdk/third-party-jackson-core/2.25.1, , restricted, clearlydefined +maven/mavencentral/software.amazon.awssdk/third-party-jackson-core/2.25.1, Apache-2.0, approved, #13703 maven/mavencentral/software.amazon.awssdk/utils/2.24.10, Apache-2.0, approved, #13250 -maven/mavencentral/software.amazon.awssdk/utils/2.25.1, , restricted, clearlydefined +maven/mavencentral/software.amazon.awssdk/utils/2.25.1, Apache-2.0, approved, #13689 maven/mavencentral/software.amazon.eventstream/eventstream/1.0.1, Apache-2.0, approved, clearlydefined diff --git a/core/edr-core/src/main/java/org/eclipse/tractusx/edc/edr/core/manager/EdrManagerImpl.java b/core/edr-core/src/main/java/org/eclipse/tractusx/edc/edr/core/manager/EdrManagerImpl.java index db89aaefe..091f4e67f 100644 --- a/core/edr-core/src/main/java/org/eclipse/tractusx/edc/edr/core/manager/EdrManagerImpl.java +++ b/core/edr-core/src/main/java/org/eclipse/tractusx/edc/edr/core/manager/EdrManagerImpl.java @@ -183,7 +183,6 @@ private ContractRequest createContractRequest(NegotiateEdrRequest request) { .counterPartyAddress(request.getConnectorAddress()) .contractOffer(request.getOffer()) .protocol(request.getProtocol()) - .providerId(request.getConnectorId()) .callbackAddresses(callbacks).build(); } diff --git a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceExtension.java b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceExtension.java index 8f2355b3d..553ea6665 100644 --- a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceExtension.java +++ b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceExtension.java @@ -27,8 +27,10 @@ import org.eclipse.edc.runtime.metamodel.annotation.Provider; import org.eclipse.edc.runtime.metamodel.annotation.Setting; import org.eclipse.edc.spi.security.PrivateKeyResolver; +import org.eclipse.edc.spi.security.Vault; import org.eclipse.edc.spi.system.ServiceExtension; import org.eclipse.edc.spi.system.ServiceExtensionContext; +import org.eclipse.edc.spi.types.TypeManager; import org.eclipse.edc.token.JwtGenerationService; import org.eclipse.edc.token.spi.TokenValidationService; import org.eclipse.tractusx.edc.dataplane.tokenrefresh.spi.DataPlaneTokenRefreshService; @@ -57,6 +59,11 @@ public class DataPlaneTokenRefreshServiceExtension implements ServiceExtension { private PrivateKeyResolver privateKeyResolver; @Inject private Clock clock; + @Inject + private Vault vault; + @Inject + private TypeManager typeManager; + private DataPlaneTokenRefreshServiceImpl tokenRefreshService; @Override @@ -80,7 +87,8 @@ public DataPlaneTokenRefreshService createRefreshTokenService(ServiceExtensionCo private DataPlaneTokenRefreshServiceImpl getTokenRefreshService(ServiceExtensionContext context) { if (tokenRefreshService == null) { var epsilon = context.getConfig().getInteger(TOKEN_EXPIRY_TOLERANCE_SECONDS_PROPERTY, DEFAULT_TOKEN_EXPIRY_TOLERANCE_SECONDS); - tokenRefreshService = new DataPlaneTokenRefreshServiceImpl(clock, tokenValidationService, didPkResolver, accessTokenDataStore, new JwtGenerationService(), getPrivateKeySupplier(context), context.getMonitor(), null, epsilon); + tokenRefreshService = new DataPlaneTokenRefreshServiceImpl(clock, tokenValidationService, didPkResolver, accessTokenDataStore, new JwtGenerationService(), getPrivateKeySupplier(context), context.getMonitor(), null, + epsilon, vault, typeManager.getMapper()); } return tokenRefreshService; } diff --git a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImpl.java b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImpl.java index 005b2bed3..11769cd62 100644 --- a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImpl.java +++ b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImpl.java @@ -19,6 +19,8 @@ package org.eclipse.tractusx.edc.dataplane.tokenrefresh.core; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; import org.eclipse.edc.connector.dataplane.spi.AccessTokenData; import org.eclipse.edc.connector.dataplane.spi.iam.DataPlaneAccessTokenService; import org.eclipse.edc.connector.dataplane.spi.store.AccessTokenDataStore; @@ -29,15 +31,17 @@ import org.eclipse.edc.spi.iam.TokenRepresentation; import org.eclipse.edc.spi.monitor.Monitor; import org.eclipse.edc.spi.result.Result; +import org.eclipse.edc.spi.security.Vault; import org.eclipse.edc.spi.types.domain.DataAddress; import org.eclipse.edc.token.rules.ExpirationIssuedAtValidationRule; import org.eclipse.edc.token.spi.TokenDecorator; import org.eclipse.edc.token.spi.TokenGenerationService; import org.eclipse.edc.token.spi.TokenValidationRule; import org.eclipse.edc.token.spi.TokenValidationService; +import org.eclipse.tractusx.edc.dataplane.tokenrefresh.core.rules.AuthTokenAudienceRule; import org.eclipse.tractusx.edc.dataplane.tokenrefresh.core.rules.ClaimIsPresentRule; import org.eclipse.tractusx.edc.dataplane.tokenrefresh.core.rules.IssuerEqualsSubjectRule; -import org.eclipse.tractusx.edc.dataplane.tokenrefresh.core.rules.RefreshTokenMustExistRule; +import org.eclipse.tractusx.edc.dataplane.tokenrefresh.core.rules.RefreshTokenValidationRule; import org.eclipse.tractusx.edc.dataplane.tokenrefresh.spi.DataPlaneTokenRefreshService; import org.eclipse.tractusx.edc.dataplane.tokenrefresh.spi.model.TokenResponse; @@ -74,15 +78,20 @@ public class DataPlaneTokenRefreshServiceImpl implements DataPlaneTokenRefreshSe private final Monitor monitor; private final String refreshEndpoint; private final Clock clock; + private final Vault vault; + private final ObjectMapper objectMapper; - - public DataPlaneTokenRefreshServiceImpl(Clock clock, TokenValidationService tokenValidationService, + public DataPlaneTokenRefreshServiceImpl(Clock clock, + TokenValidationService tokenValidationService, DidPublicKeyResolver publicKeyResolver, AccessTokenDataStore accessTokenDataStore, TokenGenerationService tokenGenerationService, Supplier privateKeySupplier, Monitor monitor, - String refreshEndpoint, int tokenExpiryToleranceSeconds) { + String refreshEndpoint, + int tokenExpiryToleranceSeconds, + Vault vault, + ObjectMapper objectMapper) { this.tokenValidationService = tokenValidationService; this.publicKeyResolver = publicKeyResolver; this.accessTokenDataStore = accessTokenDataStore; @@ -91,6 +100,8 @@ public DataPlaneTokenRefreshServiceImpl(Clock clock, TokenValidationService toke this.monitor = monitor; this.refreshEndpoint = refreshEndpoint; this.clock = clock; + this.vault = vault; + this.objectMapper = objectMapper; authenticationTokenValidationRules = List.of(new IssuerEqualsSubjectRule(), new ClaimIsPresentRule(AUDIENCE), // we don't check the contents, only it is present new ClaimIsPresentRule(ACCESS_TOKEN_CLAIM), @@ -121,7 +132,8 @@ public DataPlaneTokenRefreshServiceImpl(Clock clock, TokenValidationService toke public Result refreshToken(String refreshToken, String authenticationToken) { var allRules = new ArrayList<>(authenticationTokenValidationRules); - allRules.add(new RefreshTokenMustExistRule(accessTokenDataStore, refreshToken)); + allRules.add(new RefreshTokenValidationRule(vault, refreshToken, objectMapper)); + allRules.add(new AuthTokenAudienceRule(accessTokenDataStore)); authenticationToken = authenticationToken.replace("Bearer", "").trim(); @@ -144,17 +156,11 @@ public Result refreshToken(String refreshToken, String authentica return Result.failure("Failed to regenerate access/refresh token pair: %s".formatted(errors)); } - // additional token information will be added to the TokenRepresentation, which will be returned to the caller - // note: can't use DBI (double-bracket initialization) here, because SonarCloud will complain about it - var accessTokenAdditional = new HashMap<>(existingAccessTokenData.additionalProperties()); - accessTokenAdditional.put(REFRESH_TOKEN_PROPERTY, newRefreshToken.getContent()); - accessTokenAdditional.put("expiresIn", DEFAULT_EXPIRY_IN_SECONDS); - accessTokenAdditional.put("refreshEndpoint", refreshEndpoint); - accessTokenAdditional.put("authType", "bearer"); + storeRefreshToken(existingAccessTokenData.id(), new RefreshToken(newRefreshToken.getContent(), DEFAULT_EXPIRY_IN_SECONDS, refreshEndpoint)); // the ClaimToken is created based solely on the TokenParameters. The additional information (refresh token...) is persisted separately var claimToken = ClaimToken.Builder.newInstance().claims(newTokenParams.getClaims()).build(); - var accessTokenData = new AccessTokenData(existingAccessTokenData.id(), claimToken, existingAccessTokenData.dataAddress(), accessTokenAdditional); + var accessTokenData = new AccessTokenData(existingAccessTokenData.id(), claimToken, existingAccessTokenData.dataAddress(), existingAccessTokenData.additionalProperties()); var storeResult = accessTokenDataStore.update(accessTokenData); return storeResult.succeeded() ? @@ -180,26 +186,33 @@ public Result obtainToken(TokenParameters tokenParameters, return Result.failure("Could not generate access token: %s".formatted(accessTokenResult.getFailureDetail())); } - // additional token information will be added to the TokenRepresentation, which will be returned to the caller + // the edrAdditionalData contains the refresh token, which is NOT supposed to be put in the DB // note: can't use DBI (double-bracket initialization) here, because SonarCloud will complain about it - var accessTokenAdditional = new HashMap<>(additionalTokenData); - accessTokenAdditional.put("refreshToken", refreshTokenResult.getContent().tokenRepresentation().getToken()); - accessTokenAdditional.put("expiresIn", DEFAULT_EXPIRY_IN_SECONDS); - accessTokenAdditional.put("refreshEndpoint", refreshEndpoint); - accessTokenAdditional.put("authType", "bearer"); + var additionalDataForStorage = new HashMap<>(additionalTokenData); + additionalDataForStorage.put("authType", "bearer"); + + // the ClaimToken is created based solely on the TokenParameters. The additional information (refresh token...) is persisted separately + var claimToken = ClaimToken.Builder.newInstance().claims(tokenParameters.getClaims()).build(); + var accessTokenData = new AccessTokenData(accessTokenResult.getContent().id(), claimToken, backendDataAddress, additionalDataForStorage); + var storeResult = accessTokenDataStore.store(accessTokenData); + + storeRefreshToken(accessTokenResult.getContent().id(), new RefreshToken(refreshTokenResult.getContent().tokenRepresentation().getToken(), + DEFAULT_EXPIRY_IN_SECONDS, refreshEndpoint)); + + // the refresh token information must be returned in the EDR + var edrAdditionalData = new HashMap<>(additionalTokenData); + edrAdditionalData.put("refreshToken", refreshTokenResult.getContent().tokenRepresentation().getToken()); + edrAdditionalData.put("expiresIn", DEFAULT_EXPIRY_IN_SECONDS); + edrAdditionalData.put("refreshEndpoint", refreshEndpoint); - var accessToken = TokenRepresentation.Builder.newInstance() + var edrTokenRepresentation = TokenRepresentation.Builder.newInstance() .token(accessTokenResult.getContent().tokenRepresentation().getToken()) // the access token - .additional(accessTokenAdditional) //contains additional properties and the refresh token + .additional(edrAdditionalData) //contains additional properties and the refresh token .expiresIn(DEFAULT_EXPIRY_IN_SECONDS) //todo: needed? .build(); - // the ClaimToken is created based solely on the TokenParameters. The additional information (refresh token...) is persisted separately - var claimToken = ClaimToken.Builder.newInstance().claims(tokenParameters.getClaims()).build(); - var accessTokenData = new AccessTokenData(accessTokenResult.getContent().id(), claimToken, backendDataAddress, accessTokenAdditional); - var storeResult = accessTokenDataStore.store(accessTokenData); - return storeResult.succeeded() ? Result.success(accessToken) : Result.failure(storeResult.getFailureMessages()); + return storeResult.succeeded() ? Result.success(edrTokenRepresentation) : Result.failure(storeResult.getFailureMessages()); } @Override @@ -254,10 +267,19 @@ private Result resolveToken(String token, List storeRefreshToken(String id, RefreshToken refreshToken) { + try { + return vault.storeSecret(id, objectMapper.writeValueAsString(refreshToken)); + } catch (JsonProcessingException e) { + return Result.failure(e.getMessage()); + } + } + /** * container object for a TokenRepresentation and an ID */ private record TokenRepresentationWithId(String id, TokenRepresentation tokenRepresentation) { } + } diff --git a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/RefreshToken.java b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/RefreshToken.java new file mode 100644 index 000000000..57873e5bb --- /dev/null +++ b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/RefreshToken.java @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.eclipse.tractusx.edc.dataplane.tokenrefresh.core; + +public record RefreshToken(String refreshToken, Long expiresIn, String refreshEndpoint) { + +} diff --git a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/rules/AuthTokenAudienceRule.java b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/rules/AuthTokenAudienceRule.java new file mode 100644 index 000000000..3fce42497 --- /dev/null +++ b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/rules/AuthTokenAudienceRule.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.eclipse.tractusx.edc.dataplane.tokenrefresh.core.rules; + +import com.nimbusds.jwt.JWTClaimNames; +import org.eclipse.edc.connector.dataplane.spi.store.AccessTokenDataStore; +import org.eclipse.edc.spi.iam.ClaimToken; +import org.eclipse.edc.spi.result.Result; +import org.eclipse.edc.token.spi.TokenValidationRule; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Map; + +/** + * Validates that the {@code iss} claim of a token is equal to the {@code audience} property found on the {@link org.eclipse.edc.connector.dataplane.spi.AccessTokenData} + * that is associated with that token (using the {@code jti} claim). + */ +public class AuthTokenAudienceRule implements TokenValidationRule { + private static final String AUDIENCE_PROPERTY = "audience"; + private final AccessTokenDataStore store; + + public AuthTokenAudienceRule(AccessTokenDataStore store) { + this.store = store; + } + + @Override + public Result checkRule(@NotNull ClaimToken claimToken, @Nullable Map map) { + var issuer = claimToken.getStringClaim(JWTClaimNames.ISSUER); + var tokenId = claimToken.getStringClaim(JWTClaimNames.JWT_ID); + + var accessTokenData = store.getById(tokenId); + var expectedAudience = accessTokenData.additionalProperties().getOrDefault(AUDIENCE_PROPERTY, null); + if (expectedAudience instanceof String expectedAud) { + return expectedAud.equals(issuer) ? Result.success() : Result.failure("Principal '%s' is not authorized to refresh this token.".formatted(issuer)); + } + + return Result.failure("Property '%s' was expected to be java.lang.String but was %s.".formatted(AUDIENCE_PROPERTY, expectedAudience == null ? null : expectedAudience.getClass())); + } +} diff --git a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/rules/RefreshTokenMustExistRule.java b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/rules/RefreshTokenMustExistRule.java deleted file mode 100644 index ccf42c31d..000000000 --- a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/rules/RefreshTokenMustExistRule.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -package org.eclipse.tractusx.edc.dataplane.tokenrefresh.core.rules; - -import com.nimbusds.jwt.JWTClaimNames; -import org.eclipse.edc.connector.dataplane.spi.AccessTokenData; -import org.eclipse.edc.connector.dataplane.spi.store.AccessTokenDataStore; -import org.eclipse.edc.spi.iam.ClaimToken; -import org.eclipse.edc.spi.result.Result; -import org.eclipse.edc.token.spi.TokenValidationRule; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.Map; -import java.util.Optional; - -import static org.eclipse.tractusx.edc.dataplane.tokenrefresh.core.DataPlaneTokenRefreshServiceImpl.ACCESS_TOKEN_CLAIM; -import static org.eclipse.tractusx.edc.dataplane.tokenrefresh.core.DataPlaneTokenRefreshServiceImpl.REFRESH_TOKEN_PROPERTY; - -public class RefreshTokenMustExistRule implements TokenValidationRule { - private static final String AUDIENCE_PROPERTY = "audience"; - private final AccessTokenDataStore accessTokenDataStore; - private final String refreshToken; - - public RefreshTokenMustExistRule(AccessTokenDataStore accessTokenDataStore, String refreshToken) { - this.accessTokenDataStore = accessTokenDataStore; - this.refreshToken = refreshToken; - } - - @Override - public Result checkRule(@NotNull ClaimToken toVerify, @Nullable Map additional) { - var oldAccessToken = toVerify.getStringClaim(ACCESS_TOKEN_CLAIM); - var tokenId = toVerify.getStringClaim(JWTClaimNames.JWT_ID); - var issuer = toVerify.getStringClaim(JWTClaimNames.ISSUER); - return Optional.ofNullable(accessTokenDataStore.getById(tokenId)) - .map(accessTokenData -> checkExists(accessTokenData, refreshToken, issuer)) - .orElse(Result.failure("No AccessTokenData entry found for token-ID '%s'.".formatted(tokenId))); - } - - private Result checkExists(AccessTokenData accessTokenData, String refreshToken, String issuer) { - var storedRefreshToken = accessTokenData.additionalProperties().getOrDefault(REFRESH_TOKEN_PROPERTY, null); - if (!(storedRefreshToken instanceof String)) { - return Result.failure("Property '%s' expected to be String but was %s".formatted(REFRESH_TOKEN_PROPERTY, storedRefreshToken == null ? "null" : storedRefreshToken.getClass())); - } - if (!refreshToken.equals(storedRefreshToken)) { - return Result.failure("Provided refresh token does not match the stored refresh token."); - } - var audience = accessTokenData.additionalProperties().getOrDefault(AUDIENCE_PROPERTY, null); - if (!(audience instanceof String)) { - return Result.failure("Property '%s' expected to be String but was %s".formatted(AUDIENCE_PROPERTY, audience == null ? "null" : audience.getClass())); - } - - if (!audience.equals(issuer)) { - return Result.failure("Principal '%s' is not authorized to refresh this token.".formatted(issuer)); - } - - return Result.success(); - } -} diff --git a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/rules/RefreshTokenValidationRule.java b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/rules/RefreshTokenValidationRule.java new file mode 100644 index 000000000..b6eb4a1bb --- /dev/null +++ b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/rules/RefreshTokenValidationRule.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.eclipse.tractusx.edc.dataplane.tokenrefresh.core.rules; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.nimbusds.jwt.JWTClaimNames; +import org.eclipse.edc.spi.iam.ClaimToken; +import org.eclipse.edc.spi.result.Result; +import org.eclipse.edc.spi.security.Vault; +import org.eclipse.edc.token.spi.TokenValidationRule; +import org.eclipse.tractusx.edc.dataplane.tokenrefresh.core.RefreshToken; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Map; + +import static org.eclipse.edc.spi.result.Result.failure; +import static org.eclipse.edc.spi.result.Result.success; + +/** + * Validates that the refresh token information associated with a token's ID ({@code jti}), that is stored in the {@link Vault} + * matches a refresh token string. The refresh token in question is passed into the CTor. + */ +public class RefreshTokenValidationRule implements TokenValidationRule { + private final Vault vault; + private final String incomingRefreshToken; + private final ObjectMapper objectMapper; + + public RefreshTokenValidationRule(Vault vault, String incomingRefreshToken, ObjectMapper objectMapper) { + this.vault = vault; + this.incomingRefreshToken = incomingRefreshToken; + this.objectMapper = objectMapper; + } + + @Override + public Result checkRule(@NotNull ClaimToken toVerify, @Nullable Map additional) { + var tokenId = toVerify.getStringClaim(JWTClaimNames.JWT_ID); + + var storedRefreshTokenJson = vault.resolveSecret(tokenId); + if (storedRefreshTokenJson == null) { + return failure("No refresh token with the ID '%s' was found in the vault.".formatted(tokenId)); + } + return parse(storedRefreshTokenJson) + .compose(rt -> incomingRefreshToken.equals(rt.refreshToken()) ? + success() : + failure("Provided refresh token does not match the stored refresh token.")); + } + + private Result parse(String storedRefreshTokenJson) { + try { + return success(objectMapper.readValue(storedRefreshTokenJson, RefreshToken.class)); + } catch (JsonProcessingException e) { + return failure("Failed to parse stored secret: " + e.getMessage()); + } + } + +} diff --git a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImplComponentTest.java b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImplComponentTest.java index a8d5b72e9..d8261e852 100644 --- a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImplComponentTest.java +++ b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImplComponentTest.java @@ -19,6 +19,7 @@ package org.eclipse.tractusx.edc.dataplane.tokenrefresh.core; +import com.fasterxml.jackson.databind.ObjectMapper; import com.nimbusds.jose.JOSEException; import com.nimbusds.jose.JWSAlgorithm; import com.nimbusds.jose.JWSHeader; @@ -29,6 +30,7 @@ import com.nimbusds.jwt.JWTClaimsSet; import com.nimbusds.jwt.SignedJWT; import org.eclipse.edc.connector.core.store.CriterionOperatorRegistryImpl; +import org.eclipse.edc.connector.core.vault.InMemoryVault; import org.eclipse.edc.connector.dataplane.framework.store.InMemoryAccessTokenDataStore; import org.eclipse.edc.iam.did.spi.resolution.DidPublicKeyResolver; import org.eclipse.edc.junit.annotations.ComponentTest; @@ -37,7 +39,6 @@ import org.eclipse.edc.spi.iam.TokenParameters; import org.eclipse.edc.spi.result.Result; import org.eclipse.edc.spi.types.domain.DataAddress; -import org.eclipse.edc.spi.types.domain.transfer.FlowType; import org.eclipse.edc.token.JwtGenerationService; import org.eclipse.edc.token.TokenValidationServiceImpl; import org.junit.jupiter.api.BeforeEach; @@ -51,10 +52,6 @@ import java.util.Map; import static org.assertj.core.api.Assertions.assertThat; -import static org.eclipse.edc.connector.dataplane.framework.iam.DataPlaneAuthorizationServiceImpl.CLAIM_AGREEMENT_ID; -import static org.eclipse.edc.connector.dataplane.framework.iam.DataPlaneAuthorizationServiceImpl.CLAIM_ASSET_ID; -import static org.eclipse.edc.connector.dataplane.framework.iam.DataPlaneAuthorizationServiceImpl.CLAIM_FLOW_TYPE; -import static org.eclipse.edc.connector.dataplane.framework.iam.DataPlaneAuthorizationServiceImpl.CLAIM_PROCESS_ID; import static org.eclipse.edc.junit.assertions.AbstractResultAssert.assertThat; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; @@ -91,7 +88,9 @@ void setup() throws JOSEException { () -> privateKey, mock(), TEST_REFRESH_ENDPOINT, - 1); + 1, + new InMemoryVault(mock()), + new ObjectMapper()); when(didPkResolverMock.resolveKey(eq(consumerKey.getKeyID()))).thenReturn(Result.success(consumerKey.toPublicKey())); when(didPkResolverMock.resolveKey(eq(providerKey.getKeyID()))).thenReturn(Result.success(providerKey.toPublicKey())); @@ -105,9 +104,6 @@ void obtainToken() { assertThat(edr).isSucceeded(); // assert access token contents assertThat(asClaims(edr.getContent().getToken())) - .containsKey("asset_id") - .containsKey("process_id") - .containsKey("agreement_id") .containsEntry("iss", PROVIDER_BPN) .containsEntry("sub", PROVIDER_BPN) .containsEntry("aud", List.of(CONSUMER_BPN)) @@ -123,10 +119,8 @@ void obtainToken() { var storedData = tokenDataStore.getById(tokenId); assertThat(storedData).isNotNull(); assertThat(storedData.additionalProperties()) + .hasSize(2) .containsEntry("audience", CONSUMER_DID) - .containsEntry("refreshEndpoint", TEST_REFRESH_ENDPOINT) - .containsKey("refreshToken") - .containsKey("expiresIn") .containsEntry("authType", "bearer"); } @@ -150,6 +144,10 @@ void refresh_success() throws JOSEException { assertThat(tokenResponse).withFailMessage(tokenResponse::getFailureDetail).isSucceeded() .satisfies(tr -> assertThat(tr.refreshToken()).isNotNull()) .satisfies(tr -> assertThat(tr.accessToken()).isNotNull()); + + assertThat(tokenDataStore.getById(tokenId).additionalProperties()) + .hasSize(2) + .doesNotContainKey("refreshToken"); } @DisplayName("Verify that a refresh token can only be refreshed by the original recipient") @@ -307,10 +305,6 @@ private TokenParameters.Builder tokenParamsBuilder(String id) { .claims(JwtRegisteredClaimNames.SUBJECT, PROVIDER_BPN) .claims(JwtRegisteredClaimNames.EXPIRATION_TIME, Instant.now().plusSeconds(60).getEpochSecond()) .claims(JwtRegisteredClaimNames.ISSUED_AT, Instant.now().getEpochSecond()) - .claims(CLAIM_AGREEMENT_ID, "test-agreement-id") - .claims(CLAIM_ASSET_ID, "test-asset-id") - .claims(CLAIM_PROCESS_ID, "test-process-id") - .claims(CLAIM_FLOW_TYPE, FlowType.PULL.toString()) .header("kid", providerKey.getKeyID()); } diff --git a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImplTest.java b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImplTest.java index f57d674ea..1d3b58e2f 100644 --- a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImplTest.java +++ b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImplTest.java @@ -19,6 +19,7 @@ package org.eclipse.tractusx.edc.dataplane.tokenrefresh.core; +import com.fasterxml.jackson.databind.ObjectMapper; import org.eclipse.edc.connector.dataplane.spi.AccessTokenData; import org.eclipse.edc.connector.dataplane.spi.store.AccessTokenDataStore; import org.eclipse.edc.iam.did.spi.resolution.DidPublicKeyResolver; @@ -59,7 +60,9 @@ class DataPlaneTokenRefreshServiceImplTest { private final TokenValidationService tokenValidationService = mock(); private final DidPublicKeyResolver didPublicKeyResolver = mock(); - private final DataPlaneTokenRefreshServiceImpl accessTokenService = new DataPlaneTokenRefreshServiceImpl(Clock.systemUTC(), tokenValidationService, didPublicKeyResolver, accessTokenDataStore, tokenGenService, mock(), mock(), "https://example.com", 1); + private final DataPlaneTokenRefreshServiceImpl accessTokenService = new DataPlaneTokenRefreshServiceImpl(Clock.systemUTC(), tokenValidationService, didPublicKeyResolver, accessTokenDataStore, tokenGenService, mock(), mock(), "https://example.com", 1, + mock(), new ObjectMapper()); + @Test void obtainToken() { diff --git a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/TestFunctions.java b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/TestFunctions.java new file mode 100644 index 000000000..f67ab2ad7 --- /dev/null +++ b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/TestFunctions.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.eclipse.tractusx.edc.dataplane.tokenrefresh.core; + +import org.eclipse.edc.spi.iam.ClaimToken; + +public class TestFunctions { + public static ClaimToken createToken(String id) { + return ClaimToken.Builder.newInstance() + .claim("access_token", "test-access-token") + .claim("jti", id) + .claim("iss", "did:web:bob") + .build(); + } +} diff --git a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/rules/AuthTokenAudienceRuleTest.java b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/rules/AuthTokenAudienceRuleTest.java new file mode 100644 index 000000000..635e0ee71 --- /dev/null +++ b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/rules/AuthTokenAudienceRuleTest.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.eclipse.tractusx.edc.dataplane.tokenrefresh.core.rules; + +import org.eclipse.edc.connector.dataplane.spi.AccessTokenData; +import org.eclipse.edc.connector.dataplane.spi.store.AccessTokenDataStore; +import org.eclipse.edc.spi.iam.ClaimToken; +import org.eclipse.edc.spi.types.domain.DataAddress; +import org.junit.jupiter.api.Test; + +import java.util.Map; + +import static org.eclipse.edc.junit.assertions.AbstractResultAssert.assertThat; +import static org.eclipse.tractusx.edc.dataplane.tokenrefresh.core.TestFunctions.createToken; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +class AuthTokenAudienceRuleTest { + + private static final String TEST_TOKEN_ID = "token-id"; + private static final Object TEST_REFRESH_TOKEN = "refresh-token"; + private final AccessTokenDataStore store = mock(); + private final AuthTokenAudienceRule rule = new AuthTokenAudienceRule(store); + + @Test + void checkRule_issuerDoesNotMatchAudience() { + when(store.getById(TEST_TOKEN_ID)).thenReturn(new AccessTokenData(TEST_TOKEN_ID, + ClaimToken.Builder.newInstance().build(), + DataAddress.Builder.newInstance().type("test-type").build(), + Map.of("audience", "did:web:alice"))); + + assertThat(rule.checkRule(createToken(TEST_TOKEN_ID), Map.of())) + .isFailed() + .detail() + .isEqualTo("Principal 'did:web:bob' is not authorized to refresh this token."); + } + + @Test + void checkRule_audienceNotString() { + when(store.getById(TEST_TOKEN_ID)).thenReturn(new AccessTokenData(TEST_TOKEN_ID, + ClaimToken.Builder.newInstance().build(), + DataAddress.Builder.newInstance().type("test-type").build(), + Map.of("audience", 42L))); + + assertThat(rule.checkRule(createToken(TEST_TOKEN_ID), Map.of())) + .isFailed() + .detail() + .isEqualTo("Property 'audience' was expected to be java.lang.String but was class java.lang.Long."); + } + + @Test + void checkRule_audienceNotPresent() { + when(store.getById(TEST_TOKEN_ID)).thenReturn(new AccessTokenData(TEST_TOKEN_ID, + ClaimToken.Builder.newInstance().build(), + DataAddress.Builder.newInstance().type("test-type").build(), + Map.of())); + + assertThat(rule.checkRule(createToken(TEST_TOKEN_ID), Map.of())) + .isFailed() + .detail() + .isEqualTo("Property 'audience' was expected to be java.lang.String but was null."); + } +} \ No newline at end of file diff --git a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/rules/RefreshTokenMustExistRuleTest.java b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/rules/RefreshTokenMustExistRuleTest.java deleted file mode 100644 index e3e50d04e..000000000 --- a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/rules/RefreshTokenMustExistRuleTest.java +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -package org.eclipse.tractusx.edc.dataplane.tokenrefresh.core.rules; - -import org.eclipse.edc.connector.dataplane.spi.AccessTokenData; -import org.eclipse.edc.connector.dataplane.spi.store.AccessTokenDataStore; -import org.eclipse.edc.spi.iam.ClaimToken; -import org.eclipse.edc.spi.types.domain.DataAddress; -import org.junit.jupiter.api.Test; - -import java.util.Map; - -import static org.eclipse.edc.junit.assertions.AbstractResultAssert.assertThat; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -class RefreshTokenMustExistRuleTest { - - private static final String TEST_TOKEN_ID = "test-jti"; - private static final String TEST_REFRESH_TOKEN = "test-refresh-token"; - private final AccessTokenDataStore accessTokenData = mock(); - private final RefreshTokenMustExistRule rule = new RefreshTokenMustExistRule(accessTokenData, TEST_REFRESH_TOKEN); - - @Test - void checkRule_noAccessTokenDataEntryFound() { - when(accessTokenData.getById(TEST_TOKEN_ID)).thenReturn(null); - - assertThat(rule.checkRule(createToken(), Map.of())) - .isFailed() - .detail() - .isEqualTo("No AccessTokenData entry found for token-ID '%s'.".formatted(TEST_TOKEN_ID)); - } - - @Test - void checkRule_noRefreshTokenStored() { - when(accessTokenData.getById(TEST_TOKEN_ID)).thenReturn(new AccessTokenData(TEST_TOKEN_ID, - ClaimToken.Builder.newInstance().build(), - DataAddress.Builder.newInstance().type("test-type").build(), - Map.of("foo", "var"))); - - assertThat(rule.checkRule(createToken(), Map.of())) - .isFailed() - .detail() - .isEqualTo("Property 'refreshToken' expected to be String but was null"); - } - - @Test - void checkRule_refreshTokenNotString() { - when(accessTokenData.getById(TEST_TOKEN_ID)).thenReturn(new AccessTokenData(TEST_TOKEN_ID, - ClaimToken.Builder.newInstance().build(), - DataAddress.Builder.newInstance().type("test-type").build(), - Map.of("refreshToken", 42L))); - - assertThat(rule.checkRule(createToken(), Map.of())) - .isFailed() - .detail() - .isEqualTo("Property 'refreshToken' expected to be String but was class java.lang.Long"); - } - - @Test - void checkRule_refreshTokenDoesNotMatch() { - when(accessTokenData.getById(TEST_TOKEN_ID)).thenReturn(new AccessTokenData(TEST_TOKEN_ID, - ClaimToken.Builder.newInstance().build(), - DataAddress.Builder.newInstance().type("test-type").build(), - Map.of("refreshToken", "this-is-not-equal"))); - - assertThat(rule.checkRule(createToken(), Map.of())) - .isFailed() - .detail() - .isEqualTo("Provided refresh token does not match the stored refresh token."); - } - - @Test - void checkRule_issuerDoesNotMatchAudience() { - when(accessTokenData.getById(TEST_TOKEN_ID)).thenReturn(new AccessTokenData(TEST_TOKEN_ID, - ClaimToken.Builder.newInstance().build(), - DataAddress.Builder.newInstance().type("test-type").build(), - Map.of("refreshToken", TEST_REFRESH_TOKEN, "audience", "did:web:alice"))); - - assertThat(rule.checkRule(createToken(), Map.of())) - .isFailed() - .detail() - .isEqualTo("Principal 'did:web:bob' is not authorized to refresh this token."); - } - - @Test - void checkRule_success() { - when(accessTokenData.getById(TEST_TOKEN_ID)).thenReturn(new AccessTokenData(TEST_TOKEN_ID, - ClaimToken.Builder.newInstance().build(), - DataAddress.Builder.newInstance().type("test-type").build(), - Map.of("refreshToken", TEST_REFRESH_TOKEN, "audience", "did:web:bob"))); - - assertThat(rule.checkRule(createToken(), Map.of())) - .isSucceeded(); - } - - private ClaimToken createToken() { - return ClaimToken.Builder.newInstance() - .claim("access_token", "test-access-token") - .claim("jti", TEST_TOKEN_ID) - .claim("iss", "did:web:bob") - .build(); - } -} \ No newline at end of file diff --git a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/rules/RefreshTokenValidationRuleTest.java b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/rules/RefreshTokenValidationRuleTest.java new file mode 100644 index 000000000..60022ac35 --- /dev/null +++ b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/rules/RefreshTokenValidationRuleTest.java @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.eclipse.tractusx.edc.dataplane.tokenrefresh.core.rules; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.eclipse.edc.spi.security.Vault; +import org.junit.jupiter.api.Test; + +import java.util.Map; + +import static org.eclipse.edc.junit.assertions.AbstractResultAssert.assertThat; +import static org.eclipse.tractusx.edc.dataplane.tokenrefresh.core.TestFunctions.createToken; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +class RefreshTokenValidationRuleTest { + + private static final String TEST_TOKEN_ID = "test-jti"; + private static final String TEST_REFRESH_TOKEN = "test-refresh-token"; + private final Vault vault = mock(); + private final RefreshTokenValidationRule rule = new RefreshTokenValidationRule(vault, TEST_REFRESH_TOKEN, new ObjectMapper()); + + @Test + void checkRule_noAccessTokenDataEntryFound() { + when(vault.resolveSecret(TEST_TOKEN_ID)).thenReturn(null); + + assertThat(rule.checkRule(createToken(TEST_TOKEN_ID), Map.of())) + .isFailed() + .detail() + .isEqualTo("No refresh token with the ID '%s' was found in the vault.".formatted(TEST_TOKEN_ID)); + } + + @Test + void checkRule_noRefreshTokenStored() { + when(vault.resolveSecret(TEST_TOKEN_ID)).thenReturn(null); + + assertThat(rule.checkRule(createToken(TEST_TOKEN_ID), Map.of())) + .isFailed() + .detail() + .isEqualTo("No refresh token with the ID 'test-jti' was found in the vault."); + } + + @Test + void checkRule_refreshTokenNotString() { + when(vault.resolveSecret(TEST_TOKEN_ID)).thenReturn( + """ + { + "refreshToken": 42 + } + """); + + assertThat(rule.checkRule(createToken(TEST_TOKEN_ID), Map.of())) + .isFailed() + .detail() + .isEqualTo("Provided refresh token does not match the stored refresh token."); + } + + @Test + void checkRule_refreshTokenDoesNotMatch() { + when(vault.resolveSecret(TEST_TOKEN_ID)).thenReturn( + """ + { + "refreshToken": "someRefreshToken" + } + """); + + assertThat(rule.checkRule(createToken(TEST_TOKEN_ID), Map.of())) + .isFailed() + .detail() + .isEqualTo("Provided refresh token does not match the stored refresh token."); + } + + @Test + void checkRule_success() { + when(vault.resolveSecret(TEST_TOKEN_ID)).thenReturn( + """ + { + "refreshToken": "%s" + } + """.formatted(TEST_REFRESH_TOKEN)); + + assertThat(rule.checkRule(createToken(TEST_TOKEN_ID), Map.of())) + .isSucceeded(); + } + + @Test + void checkRule_invalidJson() { + when(vault.resolveSecret(TEST_TOKEN_ID)).thenReturn( + "nope-thats-not-json"); + + assertThat(rule.checkRule(createToken(TEST_TOKEN_ID), Map.of())) + .isFailed() + .detail() + .startsWith("Failed to parse stored secret"); + } + +} \ No newline at end of file From 597867349f28a9c52953a14fee9b4f6d04e47835 Mon Sep 17 00:00:00 2001 From: Paul Latzelsperger <43503240+paullatzelsperger@users.noreply.github.com> Date: Fri, 15 Mar 2024 10:51:15 +0100 Subject: [PATCH 054/100] feat: add TokenRefreshHandler (#1126) * feat: implement TokenRefreshhandler * DEPENDENCIES * checkstyle, sonar --- DEPENDENCIES | 1 + edc-extensions/README.md | 47 ---- .../api/TokenRefreshApiExtension.java | 2 +- .../tokenrefresh/api/v1/TokenRefreshApi.java | 2 +- .../api/v1/TokenRefreshApiController.java | 4 +- .../api/v1/TokenRefreshApiControllerTest.java | 4 +- ...DataPlaneTokenRefreshServiceExtension.java | 38 ++- .../DataPlaneTokenRefreshServiceImpl.java | 4 +- .../build.gradle.kts | 24 +- .../TokenRefreshHandlerExtension.java | 63 +++++ .../tokenrefresh/TokenRefreshHandlerImpl.java | 160 ++++++++++++ ...rg.eclipse.edc.spi.system.ServiceExtension | 20 ++ .../TokenRefreshHandlerImplTest.java | 228 ++++++++++++++++++ .../DataPlaneTokenRefreshEndToEndTest.java | 2 +- gradle/libs.versions.toml | 1 + settings.gradle.kts | 1 + .../common/TokenRefreshHandler.java | 38 +++ .../DataPlaneTokenRefreshService.java | 4 +- .../dataplane}/model/TokenResponse.java | 2 +- 19 files changed, 572 insertions(+), 73 deletions(-) delete mode 100644 edc-extensions/README.md rename edc-extensions/{ => tokenrefresh-handler}/build.gradle.kts (57%) create mode 100644 edc-extensions/tokenrefresh-handler/src/main/java/org/eclipse/tractusx/edc/common/tokenrefresh/TokenRefreshHandlerExtension.java create mode 100644 edc-extensions/tokenrefresh-handler/src/main/java/org/eclipse/tractusx/edc/common/tokenrefresh/TokenRefreshHandlerImpl.java create mode 100644 edc-extensions/tokenrefresh-handler/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension create mode 100644 edc-extensions/tokenrefresh-handler/src/test/java/org/eclipse/tractusx/edc/common/tokenrefresh/TokenRefreshHandlerImplTest.java create mode 100644 spi/tokenrefresh-spi/src/main/java/org/eclipse/tractusx/edc/spi/tokenrefresh/common/TokenRefreshHandler.java rename spi/tokenrefresh-spi/src/main/java/org/eclipse/tractusx/edc/{dataplane/tokenrefresh/spi => spi/tokenrefresh/dataplane}/DataPlaneTokenRefreshService.java (93%) rename spi/tokenrefresh-spi/src/main/java/org/eclipse/tractusx/edc/{dataplane/tokenrefresh/spi => spi/tokenrefresh/dataplane}/model/TokenResponse.java (95%) diff --git a/DEPENDENCIES b/DEPENDENCIES index bb4a66ac1..cb852668b 100644 --- a/DEPENDENCIES +++ b/DEPENDENCIES @@ -324,6 +324,7 @@ maven/mavencentral/org.eclipse.edc/dsp-transfer-process-transform/0.5.2-SNAPSHOT maven/mavencentral/org.eclipse.edc/dsp-transfer-process/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/dsp-version-api/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/dsp/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/edr-store-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/http-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/http/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/iam-mock/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc diff --git a/edc-extensions/README.md b/edc-extensions/README.md deleted file mode 100644 index e2c2855f9..000000000 --- a/edc-extensions/README.md +++ /dev/null @@ -1,47 +0,0 @@ -# EDC Extensions Overview - -The following extensions provide additional functionality to the core EDC. -They are currently only available in Tractus-X EDC. - -## Business Partner Validation - -This extension allows for validation of business partners within the access policy. - -## Control Plane EDR APIs - -The goal of this extension is to simplify the process of retrieving data out of EDC. -It returns `EndpointDataReference` object, hiding all the communication details for contract offers, -contract negotiation, transfer process and retrieving the underlying data through the data-planes. - -## Data Encryption - -The EDC encrypts sensitive information inside a token it sends to other applications (potentially cross-company). -This extension implements the encryption of this data and should be used with secure keys and algorithms at all times. - -## Data Plane Selector - -This control plane extension makes it possible to configure one or more data plane instances. -During a transfer the control plane will look for an instance with matching capabilities to transfer data. - -## Hashicorp Vault - -This extension allows for usage of Hashicorp Vault for secret storage. -It is the default used in Tractus-X EDC. - -## PostrgreSQL Migration - -While the core EDC is able to interact with PostgreSQL databases, -it does not automate migrations between schema versions. -This extension adds that functionality. - -## Transfer Process SFTP - -This extension allows for the use of SFTP backends for the data plane (but is not included in the provided control- and data plane). - -## NOTICE - -This work is licensed under the [Apache-2.0](https://www.apache.org/licenses/LICENSE-2.0). - -- SPDX-License-Identifier: Apache-2.0 -- SPDX-FileCopyrightText: 2021,2022,2023 Contributors to the Eclipse Foundation -- Source URL: diff --git a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-api/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/api/TokenRefreshApiExtension.java b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-api/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/api/TokenRefreshApiExtension.java index 3fb4a88b6..907e50169 100644 --- a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-api/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/api/TokenRefreshApiExtension.java +++ b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-api/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/api/TokenRefreshApiExtension.java @@ -25,7 +25,7 @@ import org.eclipse.edc.spi.system.ServiceExtensionContext; import org.eclipse.edc.web.spi.WebService; import org.eclipse.tractusx.edc.dataplane.tokenrefresh.api.v1.TokenRefreshApiController; -import org.eclipse.tractusx.edc.dataplane.tokenrefresh.spi.DataPlaneTokenRefreshService; +import org.eclipse.tractusx.edc.spi.tokenrefresh.dataplane.DataPlaneTokenRefreshService; import static org.eclipse.tractusx.edc.dataplane.tokenrefresh.api.TokenRefreshApiExtension.NAME; diff --git a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-api/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/api/v1/TokenRefreshApi.java b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-api/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/api/v1/TokenRefreshApi.java index f0a85a0ed..abaf84e3a 100644 --- a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-api/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/api/v1/TokenRefreshApi.java +++ b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-api/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/api/v1/TokenRefreshApi.java @@ -31,7 +31,7 @@ import io.swagger.v3.oas.annotations.security.SecurityScheme; import io.swagger.v3.oas.annotations.tags.Tag; import org.eclipse.edc.web.spi.ApiErrorDetail; -import org.eclipse.tractusx.edc.dataplane.tokenrefresh.spi.model.TokenResponse; +import org.eclipse.tractusx.edc.spi.tokenrefresh.dataplane.model.TokenResponse; @SecurityScheme(name = "Authentication", description = "Self-Issued ID token containing an access_token", diff --git a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-api/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/api/v1/TokenRefreshApiController.java b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-api/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/api/v1/TokenRefreshApiController.java index c2e08290f..4757fcae5 100644 --- a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-api/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/api/v1/TokenRefreshApiController.java +++ b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-api/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/api/v1/TokenRefreshApiController.java @@ -28,8 +28,8 @@ import jakarta.ws.rs.core.MediaType; import org.eclipse.edc.web.spi.exception.AuthenticationFailedException; import org.eclipse.edc.web.spi.exception.InvalidRequestException; -import org.eclipse.tractusx.edc.dataplane.tokenrefresh.spi.DataPlaneTokenRefreshService; -import org.eclipse.tractusx.edc.dataplane.tokenrefresh.spi.model.TokenResponse; +import org.eclipse.tractusx.edc.spi.tokenrefresh.dataplane.DataPlaneTokenRefreshService; +import org.eclipse.tractusx.edc.spi.tokenrefresh.dataplane.model.TokenResponse; import static jakarta.ws.rs.core.HttpHeaders.AUTHORIZATION; diff --git a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-api/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/api/v1/TokenRefreshApiControllerTest.java b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-api/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/api/v1/TokenRefreshApiControllerTest.java index bb2b805c2..d8fc82d13 100644 --- a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-api/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/api/v1/TokenRefreshApiControllerTest.java +++ b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-api/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/api/v1/TokenRefreshApiControllerTest.java @@ -23,8 +23,8 @@ import io.restassured.specification.RequestSpecification; import org.eclipse.edc.spi.result.Result; import org.eclipse.edc.web.jersey.testfixtures.RestControllerTestBase; -import org.eclipse.tractusx.edc.dataplane.tokenrefresh.spi.DataPlaneTokenRefreshService; -import org.eclipse.tractusx.edc.dataplane.tokenrefresh.spi.model.TokenResponse; +import org.eclipse.tractusx.edc.spi.tokenrefresh.dataplane.DataPlaneTokenRefreshService; +import org.eclipse.tractusx.edc.spi.tokenrefresh.dataplane.model.TokenResponse; import org.hamcrest.Matchers; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; diff --git a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceExtension.java b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceExtension.java index 553ea6665..e60aecca1 100644 --- a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceExtension.java +++ b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceExtension.java @@ -26,14 +26,16 @@ import org.eclipse.edc.runtime.metamodel.annotation.Inject; import org.eclipse.edc.runtime.metamodel.annotation.Provider; import org.eclipse.edc.runtime.metamodel.annotation.Setting; +import org.eclipse.edc.spi.monitor.Monitor; import org.eclipse.edc.spi.security.PrivateKeyResolver; import org.eclipse.edc.spi.security.Vault; +import org.eclipse.edc.spi.system.Hostname; import org.eclipse.edc.spi.system.ServiceExtension; import org.eclipse.edc.spi.system.ServiceExtensionContext; import org.eclipse.edc.spi.types.TypeManager; import org.eclipse.edc.token.JwtGenerationService; import org.eclipse.edc.token.spi.TokenValidationService; -import org.eclipse.tractusx.edc.dataplane.tokenrefresh.spi.DataPlaneTokenRefreshService; +import org.eclipse.tractusx.edc.spi.tokenrefresh.dataplane.DataPlaneTokenRefreshService; import org.jetbrains.annotations.NotNull; import java.security.PrivateKey; @@ -48,7 +50,11 @@ public class DataPlaneTokenRefreshServiceExtension implements ServiceExtension { public static final String NAME = "DataPlane Token Refresh Service extension"; public static final int DEFAULT_TOKEN_EXPIRY_TOLERANCE_SECONDS = 5; @Setting(value = "Token expiry tolerance period in seconds to allow for clock skew", defaultValue = "" + DEFAULT_TOKEN_EXPIRY_TOLERANCE_SECONDS) - public static final String TOKEN_EXPIRY_TOLERANCE_SECONDS_PROPERTY = "edc.dataplane.api.token.expiry.tolerance"; + public static final String TOKEN_EXPIRY_TOLERANCE_SECONDS_PROPERTY = "edc.dataplane.token.expiry.tolerance"; + + @Setting(value = "The HTTP endpoint where clients can request a renewal of their access token for the public dataplane API") + public static final String REFRESH_ENDPOINT_PROPERTY = "edc.dataplane.token.refresh.endpoint"; + @Inject private TokenValidationService tokenValidationService; @Inject @@ -63,6 +69,8 @@ public class DataPlaneTokenRefreshServiceExtension implements ServiceExtension { private Vault vault; @Inject private TypeManager typeManager; + @Inject + private Hostname hostname; private DataPlaneTokenRefreshServiceImpl tokenRefreshService; @@ -83,16 +91,36 @@ public DataPlaneTokenRefreshService createRefreshTokenService(ServiceExtensionCo return getTokenRefreshService(context); } + private int getExpiryToleranceConfig(ServiceExtensionContext context) { + return context.getConfig().getInteger(TOKEN_EXPIRY_TOLERANCE_SECONDS_PROPERTY, DEFAULT_TOKEN_EXPIRY_TOLERANCE_SECONDS); + } + @NotNull private DataPlaneTokenRefreshServiceImpl getTokenRefreshService(ServiceExtensionContext context) { if (tokenRefreshService == null) { - var epsilon = context.getConfig().getInteger(TOKEN_EXPIRY_TOLERANCE_SECONDS_PROPERTY, DEFAULT_TOKEN_EXPIRY_TOLERANCE_SECONDS); - tokenRefreshService = new DataPlaneTokenRefreshServiceImpl(clock, tokenValidationService, didPkResolver, accessTokenDataStore, new JwtGenerationService(), getPrivateKeySupplier(context), context.getMonitor(), null, - epsilon, vault, typeManager.getMapper()); + var monitor = context.getMonitor().withPrefix("DataPlane Token Refresh"); + var expiryTolerance = getExpiryToleranceConfig(context); + var refreshEndpoint = getRefreshEndpointConfig(context, monitor); + monitor.debug("Token refresh endpoint: %s".formatted(refreshEndpoint)); + monitor.debug("Token refresh time tolerance: %d s".formatted(expiryTolerance)); + tokenRefreshService = new DataPlaneTokenRefreshServiceImpl(clock, tokenValidationService, didPkResolver, accessTokenDataStore, new JwtGenerationService(), + getPrivateKeySupplier(context), context.getMonitor(), refreshEndpoint, expiryTolerance, + vault, typeManager.getMapper()); } return tokenRefreshService; } + private String getRefreshEndpointConfig(ServiceExtensionContext context, Monitor monitor) { + var refreshEndpoint = context.getConfig().getString(REFRESH_ENDPOINT_PROPERTY, null); + if (refreshEndpoint == null) { + var port = context.getConfig().getInteger("web.http.public.port", 8185); + var path = context.getConfig().getString("web.http.public.path", "/api/v2/public"); + refreshEndpoint = "http://%s:%d%s".formatted(hostname.get(), port, path); + monitor.warning("Config property '%s' was not specified, the default '%s' will be used.".formatted(REFRESH_ENDPOINT_PROPERTY, refreshEndpoint)); + } + return refreshEndpoint; + } + @NotNull private Supplier getPrivateKeySupplier(ServiceExtensionContext context) { return () -> { diff --git a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImpl.java b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImpl.java index 11769cd62..4c3cd8cb5 100644 --- a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImpl.java +++ b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImpl.java @@ -42,8 +42,8 @@ import org.eclipse.tractusx.edc.dataplane.tokenrefresh.core.rules.ClaimIsPresentRule; import org.eclipse.tractusx.edc.dataplane.tokenrefresh.core.rules.IssuerEqualsSubjectRule; import org.eclipse.tractusx.edc.dataplane.tokenrefresh.core.rules.RefreshTokenValidationRule; -import org.eclipse.tractusx.edc.dataplane.tokenrefresh.spi.DataPlaneTokenRefreshService; -import org.eclipse.tractusx.edc.dataplane.tokenrefresh.spi.model.TokenResponse; +import org.eclipse.tractusx.edc.spi.tokenrefresh.dataplane.DataPlaneTokenRefreshService; +import org.eclipse.tractusx.edc.spi.tokenrefresh.dataplane.model.TokenResponse; import java.security.PrivateKey; import java.time.Clock; diff --git a/edc-extensions/build.gradle.kts b/edc-extensions/tokenrefresh-handler/build.gradle.kts similarity index 57% rename from edc-extensions/build.gradle.kts rename to edc-extensions/tokenrefresh-handler/build.gradle.kts index a62e89ac7..c2612c77d 100644 --- a/edc-extensions/build.gradle.kts +++ b/edc-extensions/tokenrefresh-handler/build.gradle.kts @@ -1,5 +1,5 @@ /******************************************************************************** - * Copyright (c) 2023 Contributors to the Eclipse Foundation + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) * * See the NOTICE file(s) distributed with this work for additional * information regarding copyright ownership. @@ -18,16 +18,22 @@ ********************************************************************************/ plugins { + `maven-publish` `java-library` } dependencies { - implementation(project(":edc-extensions:bpn-validation")) - implementation(project(":edc-extensions:data-encryption")) - implementation(project(":edc-extensions:dataplane:dataplane-selector-configuration")) - implementation(project(":edc-extensions:postgresql-migration")) - implementation(project(":edc-extensions:provision-additional-headers")) - implementation(project(":edc-extensions:transferprocess-sftp-client")) - implementation(project(":edc-extensions:transferprocess-sftp-common")) - implementation(project(":edc-extensions:transferprocess-sftp-provisioner")) + implementation(project(":spi:tokenrefresh-spi")) + implementation(libs.edc.spi.core) + implementation(libs.edc.spi.edrstore) + implementation(libs.edc.spi.http) + implementation(libs.edc.spi.token) + implementation(libs.edc.spi.jwt) + implementation(libs.edc.spi.identitytrust) + implementation(libs.edc.util) + implementation(libs.nimbus.jwt) + + + testImplementation(libs.edc.junit) + testImplementation(libs.restAssured) } diff --git a/edc-extensions/tokenrefresh-handler/src/main/java/org/eclipse/tractusx/edc/common/tokenrefresh/TokenRefreshHandlerExtension.java b/edc-extensions/tokenrefresh-handler/src/main/java/org/eclipse/tractusx/edc/common/tokenrefresh/TokenRefreshHandlerExtension.java new file mode 100644 index 000000000..52d57b88b --- /dev/null +++ b/edc-extensions/tokenrefresh-handler/src/main/java/org/eclipse/tractusx/edc/common/tokenrefresh/TokenRefreshHandlerExtension.java @@ -0,0 +1,63 @@ +/******************************************************************************** + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +package org.eclipse.tractusx.edc.common.tokenrefresh; + +import org.eclipse.edc.edr.spi.store.EndpointDataReferenceStore; +import org.eclipse.edc.identitytrust.SecureTokenService; +import org.eclipse.edc.runtime.metamodel.annotation.Extension; +import org.eclipse.edc.runtime.metamodel.annotation.Inject; +import org.eclipse.edc.runtime.metamodel.annotation.Provider; +import org.eclipse.edc.spi.http.EdcHttpClient; +import org.eclipse.edc.spi.system.ServiceExtension; +import org.eclipse.edc.spi.system.ServiceExtensionContext; +import org.eclipse.edc.spi.types.TypeManager; +import org.eclipse.tractusx.edc.spi.tokenrefresh.common.TokenRefreshHandler; + +import static org.eclipse.tractusx.edc.common.tokenrefresh.TokenRefreshHandlerExtension.NAME; + + +@Extension(value = NAME) +public class TokenRefreshHandlerExtension implements ServiceExtension { + public static final String NAME = "Token Refresh Handler Extension"; + // this setting is defined by the IdentityAndTrustExtension + private static final String PARTICIPANT_DID_PROPERTY = "edc.iam.issuer.id"; + @Inject + private EndpointDataReferenceStore edrStore; + @Inject + private EdcHttpClient httpClient; + @Inject + private SecureTokenService secureTokenService; + @Inject + private TypeManager typeManager; + + @Override + public String name() { + return NAME; + } + + @Provider + public TokenRefreshHandler createTokenRefreshHander(ServiceExtensionContext context) { + return new TokenRefreshHandlerImpl(edrStore, httpClient, getOwnDid(context), context.getMonitor(), secureTokenService, typeManager.getMapper()); + } + + private String getOwnDid(ServiceExtensionContext context) { + return context.getConfig().getString(PARTICIPANT_DID_PROPERTY); + } +} diff --git a/edc-extensions/tokenrefresh-handler/src/main/java/org/eclipse/tractusx/edc/common/tokenrefresh/TokenRefreshHandlerImpl.java b/edc-extensions/tokenrefresh-handler/src/main/java/org/eclipse/tractusx/edc/common/tokenrefresh/TokenRefreshHandlerImpl.java new file mode 100644 index 000000000..b64904c30 --- /dev/null +++ b/edc-extensions/tokenrefresh-handler/src/main/java/org/eclipse/tractusx/edc/common/tokenrefresh/TokenRefreshHandlerImpl.java @@ -0,0 +1,160 @@ +/******************************************************************************** + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +package org.eclipse.tractusx.edc.common.tokenrefresh; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.nimbusds.jwt.SignedJWT; +import okhttp3.HttpUrl; +import okhttp3.Request; +import okhttp3.RequestBody; +import org.eclipse.edc.edr.spi.store.EndpointDataReferenceStore; +import org.eclipse.edc.identitytrust.SecureTokenService; +import org.eclipse.edc.spi.http.EdcHttpClient; +import org.eclipse.edc.spi.monitor.Monitor; +import org.eclipse.edc.spi.result.Result; +import org.eclipse.edc.util.string.StringUtils; +import org.eclipse.tractusx.edc.spi.tokenrefresh.common.TokenRefreshHandler; +import org.eclipse.tractusx.edc.spi.tokenrefresh.dataplane.model.TokenResponse; + +import java.io.IOException; +import java.text.ParseException; +import java.util.Map; + +import static org.eclipse.edc.jwt.spi.JwtRegisteredClaimNames.AUDIENCE; +import static org.eclipse.edc.jwt.spi.JwtRegisteredClaimNames.ISSUER; +import static org.eclipse.edc.jwt.spi.JwtRegisteredClaimNames.JWT_ID; +import static org.eclipse.edc.jwt.spi.JwtRegisteredClaimNames.SUBJECT; +import static org.eclipse.edc.util.string.StringUtils.isNullOrBlank; + +public class TokenRefreshHandlerImpl implements TokenRefreshHandler { + public static final String PROPERTY_AUTHORIZATION = "authorization"; + public static final String PROPERTY_REFRESH_TOKEN = "refreshToken"; + public static final String PROPERTY_REFRESH_ENDPOINT = "refreshEndpoint"; + private final EndpointDataReferenceStore edrStore; + private final EdcHttpClient httpClient; + private final String ownDid; + private final Monitor monitor; + private final SecureTokenService secureTokenService; + private final ObjectMapper objectMapper; + + /** + * Creates a new TokenRefreshHandler + * + * @param edrStore a persistent storage where {@link org.eclipse.edc.spi.types.domain.edr.EndpointDataReference} objects are stored. + * @param httpClient needed to make the actual refresh call against the refresh endpoint + * @param ownDid the DID of this connector + * @param secureTokenService Service to generate the authentication token + * @param objectMapper ObjectMapper to interpret JSON responses + */ + public TokenRefreshHandlerImpl(EndpointDataReferenceStore edrStore, + EdcHttpClient httpClient, + String ownDid, + Monitor monitor, + SecureTokenService secureTokenService, + ObjectMapper objectMapper) { + this.edrStore = edrStore; + this.httpClient = httpClient; + this.ownDid = ownDid; + this.monitor = monitor; + this.secureTokenService = secureTokenService; + this.objectMapper = objectMapper; + } + + @Override + public Result refreshToken(String tokenId) { + var edrResult = edrStore.resolveByTransferProcess(tokenId); + if (edrResult.failed()) { + return Result.failure(edrResult.getFailureDetail()); + } + var edr = edrResult.getContent(); + var accessToken = edr.getStringProperty(PROPERTY_AUTHORIZATION); + var refreshToken = edr.getProperties().get(PROPERTY_REFRESH_TOKEN); + var refreshEndpoint = edr.getProperties().get(PROPERTY_REFRESH_ENDPOINT); + + if (isNullOrBlank(accessToken)) { + return Result.failure("Cannot perform token refresh: required property 'authorization' not found on EDR."); + } + if (isNullOrBlank(StringUtils.toString(refreshToken))) { + return Result.failure("Cannot perform token refresh: required property 'refreshToken' not found on EDR."); + } + if (isNullOrBlank(StringUtils.toString(refreshEndpoint))) { + return Result.failure("Cannot perform token refresh: required property 'refreshEndpoint' not found on EDR."); + } + + return getStringClaim(accessToken, ISSUER) + .map(audience -> Map.of( + JWT_ID, tokenId, + ISSUER, ownDid, + SUBJECT, ownDid, + AUDIENCE, audience + )) + .compose(claims -> secureTokenService.createToken(claims, accessToken)) + .compose(authToken -> createTokenRefreshRequest(refreshEndpoint.toString(), refreshToken.toString(), "Bearer %s".formatted(authToken.getToken()))) + .compose(this::executeRequest); + } + + private Result executeRequest(Request tokenRefreshRequest) { + try (var response = httpClient.execute(tokenRefreshRequest)) { + if (response.isSuccessful()) { + if (response.body() != null) { + + var jsonBody = response.body().string(); + if (!StringUtils.isNullOrEmpty(jsonBody)) { + var tokenResponse = objectMapper.readValue(jsonBody, TokenResponse.class); + return Result.success(tokenResponse); + } + } + return Result.failure("Token refresh successful, but body was empty."); + } + return Result.failure("Token refresh not successful: %d, message: %s".formatted(response.code(), response.message())); + } catch (IOException e) { + monitor.warning("Error executing token refresh request", e); + return Result.failure("Error executing token refresh request: %s".formatted(e)); + } + } + + private Result createTokenRefreshRequest(String refreshEndpoint, String refreshToken, String bearerToken) { + // see https://github.com/eclipse-tractusx/tractusx-profiles/blob/main/tx/refresh/refresh.token.grant.profile.md#3-the-refresh-request + if (!refreshEndpoint.endsWith("/token")) { + refreshToken += "/token"; + } + var url = HttpUrl.parse(refreshEndpoint) + .newBuilder() + .addQueryParameter("grant_type", "refresh_token") + .addQueryParameter("refresh_token", refreshToken) + .build(); + + return Result.success(new Request.Builder() + .addHeader("Authorization", bearerToken) + .url(url) + .post(RequestBody.create(new byte[0])) + .build()); + } + + private Result getStringClaim(String accessToken, String claimName) { + try { + return Result.success(SignedJWT.parse(accessToken).getJWTClaimsSet().getStringClaim(claimName)); + } catch (ParseException e) { + monitor.warning("Failed to get string claim '%s'".formatted(claimName), e); + return Result.failure("Failed to parse string claim '%s': %s".formatted(claimName, e)); + } + } + +} diff --git a/edc-extensions/tokenrefresh-handler/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension b/edc-extensions/tokenrefresh-handler/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension new file mode 100644 index 000000000..4c237a271 --- /dev/null +++ b/edc-extensions/tokenrefresh-handler/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension @@ -0,0 +1,20 @@ +################################################################################# +# Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License, Version 2.0 which is available at +# https://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. +# +# SPDX-License-Identifier: Apache-2.0 +################################################################################# + +org.eclipse.tractusx.edc.common.tokenrefresh.TokenRefreshHandlerExtension \ No newline at end of file diff --git a/edc-extensions/tokenrefresh-handler/src/test/java/org/eclipse/tractusx/edc/common/tokenrefresh/TokenRefreshHandlerImplTest.java b/edc-extensions/tokenrefresh-handler/src/test/java/org/eclipse/tractusx/edc/common/tokenrefresh/TokenRefreshHandlerImplTest.java new file mode 100644 index 000000000..362e81fbc --- /dev/null +++ b/edc-extensions/tokenrefresh-handler/src/test/java/org/eclipse/tractusx/edc/common/tokenrefresh/TokenRefreshHandlerImplTest.java @@ -0,0 +1,228 @@ +/******************************************************************************** + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +package org.eclipse.tractusx.edc.common.tokenrefresh; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.nimbusds.jose.JOSEException; +import com.nimbusds.jose.JWSAlgorithm; +import com.nimbusds.jose.JWSHeader; +import com.nimbusds.jose.crypto.ECDSASigner; +import com.nimbusds.jose.jwk.Curve; +import com.nimbusds.jose.jwk.gen.ECKeyGenerator; +import com.nimbusds.jwt.JWTClaimsSet; +import com.nimbusds.jwt.SignedJWT; +import okhttp3.MediaType; +import okhttp3.Protocol; +import okhttp3.Request; +import okhttp3.Response; +import okhttp3.ResponseBody; +import org.eclipse.edc.edr.spi.store.EndpointDataReferenceStore; +import org.eclipse.edc.identitytrust.SecureTokenService; +import org.eclipse.edc.spi.http.EdcHttpClient; +import org.eclipse.edc.spi.iam.TokenRepresentation; +import org.eclipse.edc.spi.result.Result; +import org.eclipse.edc.spi.result.StoreResult; +import org.eclipse.edc.spi.types.domain.DataAddress; +import org.eclipse.tractusx.edc.spi.tokenrefresh.dataplane.model.TokenResponse; +import org.jetbrains.annotations.NotNull; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtensionContext; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.ArgumentsProvider; +import org.junit.jupiter.params.provider.ArgumentsSource; + +import java.io.IOException; +import java.security.PrivateKey; +import java.util.stream.Stream; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.eclipse.edc.junit.assertions.AbstractResultAssert.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyMap; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoInteractions; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.when; + +class TokenRefreshHandlerImplTest { + public static final String REFRESH_ENDPOINT = "http://fizz.buzz/quazz"; + private static final String CONSUMER_DID = "did:web:bob"; + private static final String PUBLIC_KEY_ID = CONSUMER_DID + "#key-1"; + private static final String PROVIDER_DID = "did:web:alice"; + private final EndpointDataReferenceStore edrStore = mock(); + private final EdcHttpClient mockedHttpClient = mock(); + private final SecureTokenService mockedTokenService = mock(); + private TokenRefreshHandlerImpl tokenRefreshHandler; + private PrivateKey consumerKey; + private ObjectMapper objectMapper; + + private static String createJwt() { + try { + var providerKey = new ECKeyGenerator(Curve.P_256).generate(); + var signedJwt = new SignedJWT(new JWSHeader(JWSAlgorithm.ES256), new JWTClaimsSet.Builder().issuer(PROVIDER_DID).build()); + signedJwt.sign(new ECDSASigner(providerKey)); + return signedJwt.serialize(); + } catch (JOSEException e) { + throw new RuntimeException(e); + } + } + + @BeforeEach + void setup() throws JOSEException { + consumerKey = new ECKeyGenerator(Curve.P_256).generate().toPrivateKey(); + objectMapper = new ObjectMapper(); + tokenRefreshHandler = new TokenRefreshHandlerImpl(edrStore, mockedHttpClient, CONSUMER_DID, mock(), + mockedTokenService, objectMapper); + } + + @Test + void refresh_validateCorrectRequest() throws IOException { + when(edrStore.resolveByTransferProcess(anyString())).thenReturn(StoreResult.success(createEdr().build())); + when(mockedTokenService.createToken(anyMap(), anyString())).thenReturn(Result.success(TokenRepresentation.Builder.newInstance().token("foo-auth-token").build())); + var tokenResponse = new TokenResponse("new-access-token", "new-refresh-token", 60 * 5L, "bearer"); + var successResponse = createResponse(tokenResponse, 200, ""); + when(mockedHttpClient.execute(any())).thenReturn(successResponse); + var res = tokenRefreshHandler.refreshToken("token-id"); + assertThat(res).isSucceeded() + .satisfies(tr -> { + assertThat(tr.accessToken()).isEqualTo("new-access-token"); + assertThat(tr.refreshToken()).isEqualTo("new-refresh-token"); + assertThat(tr.expiresInSeconds()).isEqualTo(300L); + assertThat(tr.tokenType()).isEqualTo("bearer"); + }); + } + + @Test + void refresh_edrNotFound() { + when(edrStore.resolveByTransferProcess(anyString())).thenReturn(StoreResult.notFound("foo")); + + assertThat(tokenRefreshHandler.refreshToken("token-id")).isFailed() + .detail().isEqualTo("foo"); + + verify(edrStore).resolveByTransferProcess(eq("token-id")); + verifyNoMoreInteractions(edrStore); + verifyNoInteractions(mockedHttpClient, mockedTokenService); + } + + @ParameterizedTest(name = "{3}") + @ArgumentsSource(InvalidEdrProvider.class) + void refresh_edrLacksRequiredProperties(String authorization, String refreshToken, String refreshEndpoint, String desc) { + var invalidEdr = DataAddress.Builder.newInstance().type("test-type") + .property("authorization", authorization) + .property("refreshToken", refreshToken) + .property("refreshEndpoint", refreshEndpoint) + .build(); + when(edrStore.resolveByTransferProcess(anyString())).thenReturn(StoreResult.success(invalidEdr)); + + assertThat(tokenRefreshHandler.refreshToken("token-id")).isFailed() + .detail() + .matches("^Cannot perform token refresh: required property '(authorization|refreshToken|refreshEndpoint)' not found on EDR.$"); + } + + @Test + void refresh_endpointReturnsFailure() throws IOException { + when(edrStore.resolveByTransferProcess(anyString())).thenReturn(StoreResult.success(createEdr().build())); + when(mockedTokenService.createToken(anyMap(), anyString())).thenReturn(Result.success(TokenRepresentation.Builder.newInstance().token("foo-auth-token").build())); + var response401 = createResponse(null, 401, "Not authorized"); + + when(mockedHttpClient.execute(any())).thenReturn(response401); + + var res = tokenRefreshHandler.refreshToken("token-id"); + assertThat(res).isFailed() + .detail().isEqualTo("Token refresh not successful: 401, message: Not authorized"); + } + + @Test + void refresh_endpointReturnsEmptyBody() throws IOException { + when(edrStore.resolveByTransferProcess(anyString())).thenReturn(StoreResult.success(createEdr().build())); + when(mockedTokenService.createToken(anyMap(), anyString())).thenReturn(Result.success(TokenRepresentation.Builder.newInstance().token("foo-auth-token").build())); + var successResponse = createResponse(null, 200, ""); + when(mockedHttpClient.execute(any())).thenReturn(successResponse); + var res = tokenRefreshHandler.refreshToken("token-id"); + assertThat(res).isFailed() + .detail().isEqualTo("Token refresh successful, but body was empty."); + } + + @Test + void refresh_ioException() throws IOException { + when(edrStore.resolveByTransferProcess(anyString())).thenReturn(StoreResult.success(createEdr().build())); + when(mockedTokenService.createToken(anyMap(), anyString())).thenReturn(Result.success(TokenRepresentation.Builder.newInstance().token("foo-auth-token").build())); + when(mockedHttpClient.execute(any())).thenThrow(new IOException("test exception")); + + assertThat(tokenRefreshHandler.refreshToken("token-id")).isFailed() + .detail().isEqualTo("Error executing token refresh request: java.io.IOException: test exception"); + } + + @Test + void refresh_accessTokenIsNotJwt() { + when(edrStore.resolveByTransferProcess(anyString())).thenReturn(StoreResult.success(createEdr().property("authorization", "not-jwt").build())); + assertThat(tokenRefreshHandler.refreshToken("token-id")).isFailed() + .detail().startsWith("Failed to parse string claim 'iss'"); + } + + @Test + void refresh_tokenGenerationFailed() { + when(edrStore.resolveByTransferProcess(anyString())).thenReturn(StoreResult.success(createEdr().build())); + when(mockedTokenService.createToken(anyMap(), anyString())).thenReturn(Result.failure("foobar")); + assertThat(tokenRefreshHandler.refreshToken("token-id")).isFailed() + .detail().isEqualTo("foobar"); + } + + @NotNull + private Response createResponse(Object responseBodyObject, int statusCode, String message) throws JsonProcessingException { + var body = responseBodyObject == null ? new byte[0] : objectMapper.writeValueAsBytes(responseBodyObject); + return new Response.Builder() + .code(statusCode) + .protocol(Protocol.HTTP_1_1) + .message(message) + .request(new Request.Builder().url(REFRESH_ENDPOINT).build()) + .body(ResponseBody.create(body, MediaType.parse("application/json"))) + .build(); + } + + private DataAddress.Builder createEdr() { + return DataAddress.Builder.newInstance() + .type("HttpData") + .property("authorization", createJwt()) + .property("refreshToken", "foo-refresh-token") + .property("refreshEndpoint", REFRESH_ENDPOINT); + } + + private static class InvalidEdrProvider implements ArgumentsProvider { + @Override + public Stream provideArguments(ExtensionContext extensionContext) { + return Stream.of( + Arguments.of(createJwt(), "foo-refresh-token", null, "refresh endpoint is null"), + Arguments.of(createJwt(), "foo-refresh-token", "", "refresh endpoint is empty"), + Arguments.of(createJwt(), "foo-refresh-token", " ", "refresh endpoint is blank"), + Arguments.of(createJwt(), null, REFRESH_ENDPOINT, "refresh token is null"), + Arguments.of(createJwt(), "", REFRESH_ENDPOINT, "refresh token is empty"), + Arguments.of(createJwt(), " ", REFRESH_ENDPOINT, "refresh token is blank"), + Arguments.of(null, "foo-refresh-token", REFRESH_ENDPOINT, "access token is null") + ); + } + } +} \ No newline at end of file diff --git a/edc-tests/edc-dataplane/edc-dataplane-tokenrefresh-tests/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/e2e/DataPlaneTokenRefreshEndToEndTest.java b/edc-tests/edc-dataplane/edc-dataplane-tokenrefresh-tests/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/e2e/DataPlaneTokenRefreshEndToEndTest.java index 2432700f7..23f2629e4 100644 --- a/edc-tests/edc-dataplane/edc-dataplane-tokenrefresh-tests/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/e2e/DataPlaneTokenRefreshEndToEndTest.java +++ b/edc-tests/edc-dataplane/edc-dataplane-tokenrefresh-tests/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/e2e/DataPlaneTokenRefreshEndToEndTest.java @@ -37,7 +37,7 @@ import org.eclipse.edc.spi.types.domain.DataAddress; import org.eclipse.edc.spi.types.domain.transfer.DataFlowStartMessage; import org.eclipse.edc.spi.types.domain.transfer.FlowType; -import org.eclipse.tractusx.edc.dataplane.tokenrefresh.spi.model.TokenResponse; +import org.eclipse.tractusx.edc.spi.tokenrefresh.dataplane.model.TokenResponse; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index c36742228..fae161a3a 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -45,6 +45,7 @@ edc-spi-jwt = { module = "org.eclipse.edc:jwt-spi", version.ref = "edc" } edc-spi-token = { module = "org.eclipse.edc:token-spi", version.ref = "edc" } edc-spi-transform = { module = "org.eclipse.edc:transform-spi", version.ref = "edc" } edc-spi-identity-did = { module = "org.eclipse.edc:identity-did-spi", version.ref = "edc" } +edc-spi-edrstore = { module = "org.eclipse.edc:edr-store-spi", version.ref = "edc" } edc-token-core = { module = "org.eclipse.edc:token-core", version.ref = "edc" } edc-spi-oauth2 = { module = "org.eclipse.edc:oauth2-spi", version.ref = "edc" } edc-util = { module = "org.eclipse.edc:util", version.ref = "edc" } diff --git a/settings.gradle.kts b/settings.gradle.kts index dffc3350d..93bdd0340 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -41,6 +41,7 @@ include(":edc-extensions:bpn-validation:bpn-validation-core") include(":edc-extensions:bpn-validation:business-partner-store-sql") include(":edc-extensions:data-encryption") include(":edc-extensions:postgresql-migration") +include(":edc-extensions:tokenrefresh-handler") include(":edc-extensions:provision-additional-headers") include(":edc-extensions:transferprocess-sftp-client") include(":edc-extensions:transferprocess-sftp-common") diff --git a/spi/tokenrefresh-spi/src/main/java/org/eclipse/tractusx/edc/spi/tokenrefresh/common/TokenRefreshHandler.java b/spi/tokenrefresh-spi/src/main/java/org/eclipse/tractusx/edc/spi/tokenrefresh/common/TokenRefreshHandler.java new file mode 100644 index 000000000..bbfa871ef --- /dev/null +++ b/spi/tokenrefresh-spi/src/main/java/org/eclipse/tractusx/edc/spi/tokenrefresh/common/TokenRefreshHandler.java @@ -0,0 +1,38 @@ +/******************************************************************************** + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +package org.eclipse.tractusx.edc.spi.tokenrefresh.common; + +import org.eclipse.edc.spi.result.Result; +import org.eclipse.tractusx.edc.spi.tokenrefresh.dataplane.model.TokenResponse; + +/** + * Handles token refreshing against an OAuth2-compliant token refresh endpoint. + */ +@FunctionalInterface +public interface TokenRefreshHandler { + /** + * Refreshes a token identified by the token ID and returns the updated token. If tokens are kept in persistent storage or + * a HSM, implementors must update that entry. + * + * @param tokenId The ID of the token, e.g. a {@code jti} claim in JWT tokens. + * @return An updated access+refresh token pair. + */ + Result refreshToken(String tokenId); +} diff --git a/spi/tokenrefresh-spi/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/spi/DataPlaneTokenRefreshService.java b/spi/tokenrefresh-spi/src/main/java/org/eclipse/tractusx/edc/spi/tokenrefresh/dataplane/DataPlaneTokenRefreshService.java similarity index 93% rename from spi/tokenrefresh-spi/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/spi/DataPlaneTokenRefreshService.java rename to spi/tokenrefresh-spi/src/main/java/org/eclipse/tractusx/edc/spi/tokenrefresh/dataplane/DataPlaneTokenRefreshService.java index a5f855de3..a5d04b2bf 100644 --- a/spi/tokenrefresh-spi/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/spi/DataPlaneTokenRefreshService.java +++ b/spi/tokenrefresh-spi/src/main/java/org/eclipse/tractusx/edc/spi/tokenrefresh/dataplane/DataPlaneTokenRefreshService.java @@ -17,10 +17,10 @@ * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ -package org.eclipse.tractusx.edc.dataplane.tokenrefresh.spi; +package org.eclipse.tractusx.edc.spi.tokenrefresh.dataplane; import org.eclipse.edc.spi.result.Result; -import org.eclipse.tractusx.edc.dataplane.tokenrefresh.spi.model.TokenResponse; +import org.eclipse.tractusx.edc.spi.tokenrefresh.dataplane.model.TokenResponse; /** * This service receives an incoming token refresh request, validates it and generates a new token pair (access token + refresh token). diff --git a/spi/tokenrefresh-spi/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/spi/model/TokenResponse.java b/spi/tokenrefresh-spi/src/main/java/org/eclipse/tractusx/edc/spi/tokenrefresh/dataplane/model/TokenResponse.java similarity index 95% rename from spi/tokenrefresh-spi/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/spi/model/TokenResponse.java rename to spi/tokenrefresh-spi/src/main/java/org/eclipse/tractusx/edc/spi/tokenrefresh/dataplane/model/TokenResponse.java index cf64c5c23..148bf95d8 100644 --- a/spi/tokenrefresh-spi/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/spi/model/TokenResponse.java +++ b/spi/tokenrefresh-spi/src/main/java/org/eclipse/tractusx/edc/spi/tokenrefresh/dataplane/model/TokenResponse.java @@ -17,7 +17,7 @@ * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ -package org.eclipse.tractusx.edc.dataplane.tokenrefresh.spi.model; +package org.eclipse.tractusx.edc.spi.tokenrefresh.dataplane.model; import com.fasterxml.jackson.annotation.JsonProperty; From cbcabb193f19b42cd68ca7dbe36cdce674d0d269 Mon Sep 17 00:00:00 2001 From: Benedikt Reister <131359742+BenediktSR@users.noreply.github.com> Date: Fri, 15 Mar 2024 14:56:33 +0100 Subject: [PATCH 055/100] doc(policies): add policy description in tractusx-edc (#856) * docs(mgmt): rework policy section * docs(mgmt): DEPENDENCIES --------- Co-authored-by: arnoweiss --- .../management-api-walkthrough/02_policies.md | 478 ++++++++++++++++-- 1 file changed, 446 insertions(+), 32 deletions(-) diff --git a/docs/usage/management-api-walkthrough/02_policies.md b/docs/usage/management-api-walkthrough/02_policies.md index f58ebf77f..f7c8650ec 100644 --- a/docs/usage/management-api-walkthrough/02_policies.md +++ b/docs/usage/management-api-walkthrough/02_policies.md @@ -1,7 +1,31 @@ -# Creating a Policy Definition +# Policies -A policy is a declaration of a Data Consumer's rights and duties. Policies themselves make no statements about the -object that they may grant access and usage permission to. They are created at the EDC like this: +## Policies in Catena-X + +In the EDC, policies are pure [ODRL (Open Digital Rights Language)](https://www.w3.org/TR/odrl-model/). +Like the payloads of the [Dataspace Protocol](README.md), they are written in **JSON-LD**. Even if the +user only has rudimentary knowledge of [JSON-LD](https://json-ld.org/), the [**policy playground +**](https://eclipse-tractusx.github.io/tutorial-resources/policy-playground/) will provide a good starting point to +start +writing policies. It is important to keep in mind that the extensive ODRL-context (that the EDC is aware of) allows for +ergonomic reuse of the vocabulary in individual policies. + +### Policies & Verifiable Credentials (VC) + +#### General Information + +Catena-X uses policies to determine access to and use of data. The policies refer to verifiable credentials (VC) that +are stored in the Wallets. Catena-X uses the principle of self-sovereign identity (SSI). + +The key architectural principle underlying this specification is that policy definitions must be decoupled from their +corresponding VC schema. Namely, the specific **constraints** ( +see [ODRL-classes](#odrl-information-model-classes-excerpt)) +and shape of the VC schema must not be reflected in the policy definition. This allows VC schemas to be altered without +impacting policy definitions. + +### Creating a Policy Definition + +Policies can be created in the EDC as follows: ```http POST /v3/assets HTTP/1.1 @@ -13,10 +37,191 @@ Content-Type: application/json ```json { "@context": { + "@vocab": "https://w3id.org/edc/v0.0.1/ns/", "odrl": "http://www.w3.org/ns/odrl/2/" }, - "@type": "PolicyDefinitionRequestDto", - "@id": "", + "@type": "PolicyDefinitionRequest", + "@id": "{{POLICY_ID}}", + "policy": { + "@type": "odrl:Set", + "odrl:permission": [ + { + "odrl:action": { + "@id": "odrl:use" + }, + "odrl:constraint": [ + { + "odrl:leftOperand": { + "@value": "BusinessPartnerNumber" + }, + "odrl:operator": { + "@id": "odrl:eq" + }, + "odrl:rightOperand": "" + } + ] + } + ] + } +} +``` + +| Variable | Content | +|------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `@context` | In JSON-LD, `@context` is a fundamental concept used to define the mapping of terms used within the JSON-LD document to specific IRIs (Internationalized Resource Identifiers). It provides a way to establish a shared understanding of the vocabulary used in a JSON-LD document, making it possible to create structured and semantically rich data that can be easily integrated with other data sources on the web. | +| `@context`.`odrl:` | Prefixes allow you to define short aliases for longer IRIs. For example, instead of repeatedly using the full IRI [http://www.w3.org/ns/odrl/2/](http://www.w3.org/ns/odrl/2/), you can define a prefix like "odrl" and append a segment/fragment to identify the resource in the namespace. | +| `@id` | A Policy MUST have one uid property value (of type IRI) to identify the Policy. Note: The `@id` is on the upper level. It is a database policy definition which wraps the ODRL policy. | +| `policy`.`@type` | A Set Policy is the default Policy subclass. The Set is aimed at scenarios where there is an open criteria for the semantics of the policy expressions and typically refined by other systems/profiles that process the information at a later time. No privileges are granted to any Party (if defined). More detailed information about the possible policy subclasses can be found [here](https://w3c.github.io/poe/model/#infoModel). | +| `policy`.`permission` | A Policy MUST have at least one permission, prohibition, or obligation property values. | +| `policy`.`permission`.`action` | "use" the target asset (under a specific permission), currently only the action "use" is used by Catena-X | +| `policy`.`permission`.`constraint` | A boolean/logical expression that refines an Action and Party/Asset collection or the conditions applicable to a Rule. The leftOperand instances MUST clearly be defined to indicate the semantics of the Constraint. Catena-X will use the **left operand** of a *constraint* to associate a specific verifiable credential (VC). As most are use-case-agreements, [this notation](https://github.com/eclipse-tractusx/tractusx-profiles/blob/main/cx/policy/specs/policy.mapping.md) is useful. **Right Operand:** The rightOperand is the value of the Constraint that is to be compared to the leftOperand. | + +Please note that in JSON-LD, structures that may look different may actually have the same meaning. They may be expanded +or compacted, define additional `@context` objects, refer to a predefined outside `context` or others. Using a parser +or the [json-ld playground](https://json-ld.org/playground/) helps to be consistent. + +If the creation of the `policy-definition` was successful, the Management-API will return HTTP 200. + +#### Catena-X specific `constraints` + +This implementation (`tractusx-edc`) contains extensions that trigger specific behavior when encountering specific +policies. + +1. **Checks against the use-case**: The [cx-policy extension](https://github.com/eclipse-tractusx/tractusx-edc/tree/main/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx) is responsible to resolve a use-case-specific + leftOperand against a VC. The list of use-case credentials can be found [here](https://github.com/eclipse-tractusx/tractusx-profiles/tree/main/cx/credentials/samples). +2. **Checks against the BPN**: The [BPN-validation extension](https://github.com/eclipse-tractusx/tractusx-edc/tree/main/edc-extensions/bpn-validation) allows to define either a single Business Partner + authorized to pass the constraint or define a group of BPNs that may pass and can be extended at runtime. +3. **Checks for temporal validity**: If a usage policy is defined against a HTTP-based asset accessible via EDR-tokens, + the Data Provider can prohibit issuance of new tokens by defining a specific constraint based on the + [contract validity check extension](https://github.com/eclipse-edc/Connector/blob/main/docs/developer/contract-duration/contract-validity-check.md) + +### Access & Usage Policies + +In Catena-X, a distinction is made between **Access** and **Usage** Policies. + +- **access policy:** determines whether a particular consumer is offered an asset or not. For example, we may want to + restrict certain assets such that only consumers within a particular geography can see them. Consumers outside that + geography wouldn't even have them in their catalog. +- **usage policy or contract policy:** determines the conditions for initiating a contract negotiation for a particular + asset. Note that does not automatically guarantee the successful creation of a contract, it merely expresses the + eligibility to start the negotiation. The terms "usage policy" and "contract policy" are used synonymously! + +**The Access and Usage Policies are not distinguished by any special semantics, but rather by the time at which they are +checked.** + +Whether a policy is used as access or usage policy is determined during [contract definition](03_contractdefinitions.md). + +### Exemplary scenarios + +For the following Scenarios, we assume there is a **Partner 1 (provider)** who wants to provide Data for **Partner 2 +(consumer)** + +- Partner 1 (provider) has the Business-Partner-Number BPN12345. +- Partner 2 (consumer) has the Business-Partner-Number BPN6789. + +Partner 2 (consumer) signed the **Traceability Framework Agreement** and followed all the necessary steps that the +Credential appears within Partner 2s identity. + +So for this example, if Partner 2 does a catalog request to Partner 1, the following credential is provided to +Partner 1: + +```json +{ + "@context": [ + "https://w3id.org/2023/catenax/credentials/summary/v1" + ], + "id": "", + "type": [ + "VerifiableCredential", + "SummaryCredential" + ], + "issuer": "", + "issuanceDate": "2023-06-02T12:00:00Z", + "expirationDate": "2022-06-16T18:56:59Z", + "credentialSubject": { + "id": "", + "holderIdentifier": "BPN6789", + "items": [ + "MembershipCredential", + "TraceabilityCredential" + ], + "contractTemplates": "https://public.catena-x.org/contracts/" + } +} +``` +> Note: This specific credential schema will not be supported in upcoming releases but serves the purpose to illustrate +> what such a credential may look like. + +#### Scenario 1 + +Partner 1 wants to create an Access Policy, that Partner 2 can only receive the Contract offer if its BPN matches AND if +it has the Traceability Credential (Traceability Contract Signed). If one of those is missing, Partner 2 won't receive a +Contract Offer. + +##### Partner 1 - Access Policy Example + +```json + { + "@context": { + "odrl": "http://www.w3.org/ns/odrl/2/" + }, + "@type": "PolicyDefinitionRequest", + "@id": "{{POLICY_ID}}", + "policy": { + "@type": "Policy", + "odrl:permission": [ + { + "odrl:action": "use", + "odrl:constraint": { + "@type": "LogicalConstraint", + "odrl:and": [ + { + "@type": "Constraint", + "odrl:leftOperand": "BusinessPartnerNumber", + "odrl:operator": { + "@id": "odrl:eq" + }, + "odrl:rightOperand": "{{CONSUMERS_BPN}}" + }, + { + "@type": "Constraint", + "odrl:leftOperand": "FrameworkAgreement.traceability", + "odrl:operator": { + "@id": "odrl:eq" + }, + "odrl:rightOperand": "active" + } + ] + } + } + ] + } +} +``` + +Each `leftOperand` is resolved by the EDC against a property in the participant's Verfiable Credential. Thus the exact +data structure may not always match between the VC and the policy. + +##### Desired Outcome + +Partner 2 receives the Contract Offer because the BPNs are matching and he owns the Traceability Credential. + +#### Scenario 2 + +Partner 1 wants to create an Access Policy, that Partner 2 can receive the Contract Offer if its BPN matches. But a +Contract Agreement should only be created if Partner 2 also signed the Traceability Framework Agreement. So in this +case, Partner 2 should receive the Contract Offer in the first place, regardless if it signed the Traceability Framework +Agreement. The signing of the Agreement should be checked at the time of contract negotiation. + +##### Partner 1 - Access Policy Example (Scenario 2) + +```json +{ + "@context": { + "odrl": "http://www.w3.org/ns/odrl/2/" + }, + "@type": "PolicyDefinitionRequest", + "@id": "{{POLICY_ID}}", "policy": { "@type": "Policy", "odrl:permission": [ @@ -28,29 +233,185 @@ Content-Type: application/json "odrl:operator": { "@id": "odrl:eq" }, - "odrl:rightOperand": "" + "odrl:rightOperand": "{{BPN6789}}" + } + } + ] + } +} +``` + +##### Partner 1 - Usage/Contract Policy Example (Scenario 2) + +```json + { + "@context": { + "odrl": "http://www.w3.org/ns/odrl/2/" + }, + "@type": "PolicyDefinitionRequest", + "@id": "{{POLICY_ID}}", + "policy": { + "@type": "Policy", + "odrl:permission": [ + { + "odrl:action": "use", + "odrl:constraint": { + "@type": "Constraint", + "odrl:leftOperand": "FrameworkAgreement.traceability", + "odrl:operator": { + "@id": "odrl:eq" + }, + "odrl:rightOperand": "active" } } ] } } +``` +##### Desired Outcome (Scenario 2) + +Partner 2 receives the Contract Offer and is able to negotiate the contract because he owns the Traceability Credential. + +#### Scenario 3 + +Partner 1 wants to create an Access Policy that Partner 2 can receive the Contract Offer if the BPN is matching AND +Partner 2 is identified as a Dismantler (owns the "DismantlerCredential"). + +##### Partner 1 - Access Policy Example (Scenario 3) + +```json +{ + "@context": { + "odrl": "http://www.w3.org/ns/odrl/2/" + }, + "@type": "PolicyDefinitionRequest", + "@id": "{{POLICY_ID}}", + "policy": { + "@type": "Policy", + "odrl:permission": [ + { + "odrl:action": "use", + "odrl:constraint": { + "@type": "LogicalConstraint", + "odrl:and": [ + { + "@type": "Constraint", + "odrl:leftOperand": "BusinessPartnerNumber", + "odrl:operator": { + "@id": "odrl:eq" + }, + "odrl:rightOperand": "{{BPN6789}}" + }, + { + "@type": "Constraint", + "odrl:leftOperand": "Dismantler", + "odrl:operator": { + "@id": "odrl:eq" + }, + "odrl:rightOperand": "active" + } + ] + } + } + ] + } +} ``` -In the EDC, policies are pure [ODRL (Open Digital Rights Language)](https://www.w3.org/TR/odrl-model/). -Like the payloads of the [Dataspace Protocol](1-management-api-overview), they are written in JSON-LD. Even if the user -only has rudimentary knowledge of JSON-LD, the [policy playground](https://eclipse-tractusx.github.io/tutorial-resources/policy-playground/) -will provide a good starting point to start writing policies. It is important to keep in mind that the extensive ODRL- -context (that the EDC is aware of) allows for ergonomic reuse of the vocabulary in individual policies. +##### Desired Outcome (Scenario 3) + +Partner 2 does not receive the Contract Offer as he does not own the Dismantler Credential and is therefore not able to +negotiate the contract or request the data. + +#### Scenario 4 + +Partner 1 wants to create an Access Policy that Partner 2 can receive the Contract Offer if the BPN is matching. +Further, Partner 1 only wants to create an Agreement if Partner 2 is identified as a Dismantler (owns the +"DismantlerCredential"). Otherwise the Negotiation has to fail. + +##### Partner 1 - Access Policy Example (Scenario 4) + +```json +{ + "@context": { + "odrl": "http://www.w3.org/ns/odrl/2/" + }, + "@type": "PolicyDefinitionRequest", + "@id": "{{POLICY_ID}}", + "policy": { + "@type": "Policy", + "odrl:permission": [ + { + "odrl:action": "use", + "odrl:constraint": { + "@type": "LogicalConstraint", + "odrl:and": [ + { + "@type": "Constraint", + "odrl:leftOperand": "BusinessPartnerNumber", + "odrl:operator": { + "@id": "odrl:eq" + }, + "odrl:rightOperand": "{{BPN6789}}" + } + ] + } + } + ] + } +} +``` + +##### Partner 1 - Usage/Contract Policy Example (Scenario 4) + +```json +{ + "@context": { + "odrl": "http://www.w3.org/ns/odrl/2/" + }, + "@type": "PolicyDefinitionRequest", + "@id": "{{POLICY_ID}}", + "policy": { + "@type": "Policy", + "odrl:permission": [ + { + "odrl:action": "use", + "odrl:constraint": { + "@type": "LogicalConstraint", + "odrl:and": [ + { + "@type": "Constraint", + "odrl:leftOperand": "Dismantler", + "odrl:operator": { + "@id": "odrl:eq" + }, + "odrl:rightOperand": "active" + } + ] + } + } + ] + } +} +``` + +##### Desired Outcome (Scenario 4) + +Partner 2 receives the Contract Offer in the first place. -## Writing Policies for the EDC +The contract negotiation, started by Partner 2 fails because he has not been identified as Dismantler and therefore does +not own the Dismantler Credential. -ODRL's model and expressiveness surpass the EDC's current ability to interpret the policies and derive behavior from -them. This must be kept in mind even when Data Offers based on policies are not yet published to the Dataspace. Here again, -configuring the wrong policies is a risk for unsafe and non-compliant behavior. This is exacerbated by the fact that -the EDC interprets policies it can't evaluate as true by default. A couple of examples: +#### Writing Policies for the EDC + +ℹ️ ODRL's model and expressiveness surpass the EDC's current ability to interpret the policies and derive behavior from +them. This must be kept in mind even when Data Offers based on policies are not yet published to the Dataspace. Here +again, configuring the wrong policies is a risk for unsafe and non-compliant behavior. This is exacerbated by the fact +that the EDC interprets policies it can't evaluate as true by default. A couple of examples: + +#### Let all pass -### Let all pass ```json { "@context": { @@ -69,12 +430,12 @@ the EDC interprets policies it can't evaluate as true by default. A couple of ex } ``` -### Only let a Business Partner Group pass +#### Only let a Business Partner Group pass A Business Partner Group is a group of BPNs that are allowed to pass this constraint. A BPN can be added to a group even after a Contract Offer for a certain BPN-Group was published. The groups are persisted and maintained in the Provider's Control Plane. The EDC-Management-API's `/business-partner-groups` endpoint offers CRUD-operations for -it. +it. ```json { @@ -103,7 +464,7 @@ it. ``` -### Chaining Constraints +#### Chaining Constraints Constraints can be chained together via logical constraints. This is currently implemented for `odrl:and`, `odrl:or` and `odrl:xone` (exactly one constraint evaluates to `true`). @@ -146,22 +507,75 @@ and `odrl:xone` (exactly one constraint evaluates to `true`). } ``` -Some permission-constraints trigger specific behavior in the EDC. That should be kept in mind when designing policies -and requires an understanding of how the EDC evaluates and acts upon them. +## Additional Information about Policies + +ℹ️ All explanations in this chapter "General Information about Policies" were taken from the +following [source](https://w3c.github.io/poe/model/). + +### Introduction + +Several business scenarios require expressing what are the permitted and prohibited actions over resources. These +permitted/prohibited actions are usually expressed under the form of policies, i.e., expressions that indicate those +uses and re-uses of the content which are conformant with existing regulations or to the constraints assigned by the +owner. Policies may also be enriched with additional information, i.e., who are the entities in charge of the definition +of such Policy and those who are required to conform to it, what are the additional constrains to be associated with the +Permissions, Prohibitions and Duties expressed by the Policy. The ability to express these concepts and relationships is +important both for the producers of content, i.e., they may state in a clear way what are the permitted and the +prohibited actions to prevent misuse, and for the consumers, i.e., they may know precisely what resources they are +allowed to use and re-use to avoid breaking any rules, laws or the owner's constraints. This specification describes a +common approach to expressing these policy concepts. + +### Semantic Model + +The ODRL Information Model defines the underlying semantic model for permission, prohibition, and obligation statements +describing content usage. The information model covers the core concepts, entities and relationships that provide the +foundational model for content usage statements. These machine-readable policies may be linked directly with the content +they are associated to with the aim to allow consumers to easily retrieve this information. + +#### ODRL Information Model classes (excerpt) -| `leftOperand` | `rightOperand` | usage in
    [Contract Definition](03_contractdefinitions.md) | description | -|--------------------------------------------------------------|--------------------------------------------------|-----------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `BusinessPartnerNumber` | a BPNL | access or contract | _This function is deprecated._
    The leftOperand "BusinessPartnerNumber" will trigger a check against the property in a Consumer's Verfifiable Credential (VC) that holds said BPNL. | -| `https://w3id.org/tractusx/v0.0.1/ns/BusinessPartnerGroup` | a Business Partner Group | access or contract | see [above](#only-let-a-business-partner-group-pass). The `leftOperand` is in this case not queried from the Consumer's VC but acts as a signal to check the Consumer's BPN for membership in the designated Business Partner Group. | -| `https://w3id.org/edc/v0.0.1/ns/InForceDate` | json-object with properties `@value` and `@type` | contract | If the negotiation via either [Contract Negotiation](05_contractnegotiations.md) or the [EDR process](07_edrs.md) is successful, the EDC will only renew short-lived Data-Plane tokens for a contract if the contract is still valid (in force). Start and end dates can be set with absolute timestamps or relative to the time of the contract agreement. For exact syntax, visit the [playground](https://eclipse-tractusx.github.io/tutorial-resources/policy-playground/). | -| `https://w3id.org/tractusx/v0.0.1/ns/FrameworkAgreement.pcf` | "active" | access or contract | Framework agreements in Catena-X are legal documents signed by a Business Partner to participate in a Business Scenario. In return, her credential is enhanced with a reference to the corresponding framework agreement - like in this case `pcf`. A complete list of framework agreements is maintained by the Catena-X association in standards CX-0049 and -0050. | +| Class | Description | +|--------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `Policy` | A non-empty group of Permissions (via the permission property) and/or Prohibitions (via the prohibition property) and/or Duties (via the obligation property). | +| `Set` | Subclass of `Policy`:Supports expressing generic Rules | +| `Action` | An operation on an Asset | +| `Rule` | An abstract concept that represents the common characteristics of Permissions, Prohibitions, and Duties. | +| `Prohibition` | Subclass of `Rule`: The ability to exercise an Action over an Asset. The Permission MAY also have the duty property that expresses an agreed Action that MUST be exercised (as a pre-condition to be granted the Permission). | +| `Permission` | Subclass of `Rule`: The inability to exercise an Action over an Asset. | +| `Duty` | Subclass of `Rule`: The obligation to exercise an Action. | +| `Constraint/LogicalConstraint` | A boolean/logical expression that refines an Action and Party/Asset collection or the conditions applicable to a Rule. | -For more on the integration of Verifiable Credentials and the EDC in Catena-X, see the [specification of the Identity -and Trust Protocol (IATP)](https://github.com/eclipse-tractusx/identity-trust). +#### The `Policy` Class (excerpt) -## Notice +The Policy class has the following properties (see example below): + +- A Policy MUST have one uid property value (of type IRI [rfc3987]) to identify the Policy. +- A Policy MUST have at least one permission, prohibition, or obligation property values of type Rule. (See the + Permission, Prohibition, and Obligation sections for more details.) + +#### The `Set` Class + +An ODRL Policy of subclass `Set` represents any combination of Rules. The `Set` Policy subclass is also the **default** +subclass of Policy (if none is specified). + +Example: + +```json +{ + "@context": "http://www.w3.org/ns/odrl.jsonld", + "@type": "Set", + "@id": "", + "target": "", + "permission": [ + { + "action": "use" + } + ] +} +``` -This work is licensed under the [CC-BY-4.0](https://creativecommons.org/licenses/by/4.0/legalcode). +ℹ️ For the examples in this document, the ODRL Policy subclasses are mapped to the JSON-LD `@type` tokens. The above +example could have also used `Policy` type instead of `Set` type (**as they are equivalent**). - SPDX-License-Identifier: CC-BY-4.0 - SPDX-FileCopyrightText: 2023 Contributors of the Eclipse Foundation From 1d5de46e303424d209317444b96e7a3070d8172f Mon Sep 17 00:00:00 2001 From: Enrico Risa Date: Mon, 18 Mar 2024 14:22:11 +0100 Subject: [PATCH 056/100] chore: fix with the latest EDC/IH changes (#1138) * chore: fix with the latest EDC/IH changes * chore: dependencies file --- DEPENDENCIES | 8 +++----- .../store/sql/SqlEndpointDataReferenceCacheTest.java | 4 ++-- ...SqlEndpointDataReferenceCacheTransactionalTest.java | 4 ++-- .../edc/iam/iatp/sts/dim/DimSecureTokenService.java | 4 ++-- .../iam/iatp/sts/dim/DimSecureTokenServiceTest.java | 10 +++++----- .../AssetPostgresqlMigrationExtensionTest.java | 7 ++++--- .../edc/tests/catalog/CatalogPostgresqlTest.java | 4 ++-- .../edc/tests/edr/DeleteEdrPostgresqlTest.java | 4 ++-- .../edr/NegotiateEdrPostgresqlHashicorpVaultTest.java | 4 ++-- .../edc/tests/edr/NegotiateEdrPostgresqlTest.java | 4 ++-- .../edc/tests/edr/RenewalEdrPostgresqlTest.java | 4 ++-- .../edc/tests/policy/PolicyMonitorPostgresqlTest.java | 4 ++-- .../edc/tests/proxy/DataPlaneProxyPostgresqlTest.java | 4 ++-- .../HttpConsumerPullWithProxyPostgresqlTest.java | 4 ++-- .../transfer/HttpProviderPushInPostgresqlTest.java | 4 ++-- .../org/eclipse/tractusx/edc/token/DimDispatcher.java | 4 ++-- 16 files changed, 38 insertions(+), 39 deletions(-) diff --git a/DEPENDENCIES b/DEPENDENCIES index cb852668b..0c1fe4674 100644 --- a/DEPENDENCIES +++ b/DEPENDENCIES @@ -70,12 +70,11 @@ maven/mavencentral/com.github.docker-java/docker-java-transport/3.3.6, Apache-2. maven/mavencentral/com.github.stephenc.jcip/jcip-annotations/1.0-1, Apache-2.0, approved, CQ21949 maven/mavencentral/com.google.code.findbugs/jsr305/3.0.2, Apache-2.0, approved, #20 maven/mavencentral/com.google.code.gson/gson/2.10.1, Apache-2.0, approved, #6159 -maven/mavencentral/com.google.collections/google-collections/1.0, Apache-2.0, approved, CQ3285 maven/mavencentral/com.google.crypto.tink/tink/1.12.0, Apache-2.0, approved, #12041 maven/mavencentral/com.google.errorprone/error_prone_annotations/2.22.0, Apache-2.0, approved, #10661 -maven/mavencentral/com.google.errorprone/error_prone_annotations/2.23.0, Apache-2.0, approved, #11083 +maven/mavencentral/com.google.errorprone/error_prone_annotations/2.26.1, Apache-2.0, approved, #13657 maven/mavencentral/com.google.guava/failureaccess/1.0.2, Apache-2.0, approved, CQ22654 -maven/mavencentral/com.google.guava/guava/33.0.0-jre, Apache-2.0 AND CC0-1.0, approved, #12173 +maven/mavencentral/com.google.guava/guava/33.1.0-jre, Apache-2.0 AND CC0-1.0, approved, #13675 maven/mavencentral/com.google.guava/listenablefuture/9999.0-empty-to-avoid-conflict-with-guava, Apache-2.0, approved, CQ22657 maven/mavencentral/com.google.protobuf/protobuf-java/3.24.3, BSD-3-Clause, approved, clearlydefined maven/mavencentral/com.microsoft.azure/msal4j-persistence-extension/1.2.0, MIT, approved, clearlydefined @@ -86,7 +85,7 @@ maven/mavencentral/com.nimbusds/lang-tag/1.7, Apache-2.0, approved, clearlydefin maven/mavencentral/com.nimbusds/nimbus-jose-jwt/9.30.2, Apache-2.0, approved, clearlydefined maven/mavencentral/com.nimbusds/nimbus-jose-jwt/9.37.3, Apache-2.0, approved, #11701 maven/mavencentral/com.nimbusds/oauth2-oidc-sdk/10.7.1, Apache-2.0, approved, clearlydefined -maven/mavencentral/com.puppycrawl.tools/checkstyle/10.14.0, LGPL-2.1-or-later AND (Apache-2.0 AND LGPL-2.1-or-later) AND Apache-2.0, approved, #13562 +maven/mavencentral/com.puppycrawl.tools/checkstyle/10.14.2, LGPL-2.1-or-later AND (Apache-2.0 AND LGPL-2.1-or-later) AND Apache-2.0, approved, #13562 maven/mavencentral/com.squareup.okhttp3/mockwebserver/5.0.0-alpha.12, Apache-2.0, approved, clearlydefined maven/mavencentral/com.squareup.okhttp3/mockwebserver3/5.0.0-alpha.12, Apache-2.0, approved, clearlydefined maven/mavencentral/com.squareup.okhttp3/okhttp-dnsoverhttps/4.12.0, Apache-2.0, approved, #11159 @@ -242,7 +241,6 @@ maven/mavencentral/org.bouncycastle/bcpkix-jdk18on/1.77, MIT, approved, #11593 maven/mavencentral/org.bouncycastle/bcprov-jdk18on/1.77, MIT AND CC0-1.0, approved, #11595 maven/mavencentral/org.bouncycastle/bcutil-jdk18on/1.77, MIT, approved, #11596 maven/mavencentral/org.ccil.cowan.tagsoup/tagsoup/1.2.1, Apache-2.0, approved, clearlydefined -maven/mavencentral/org.checkerframework/checker-qual/3.41.0, MIT, approved, #12032 maven/mavencentral/org.checkerframework/checker-qual/3.42.0, MIT, approved, clearlydefined maven/mavencentral/org.codehaus.plexus/plexus-classworlds/2.6.0, Apache-2.0 AND Plexus, approved, CQ22821 maven/mavencentral/org.codehaus.plexus/plexus-component-annotations/2.1.0, Apache-2.0, approved, #809 diff --git a/edc-extensions/edr/edr-cache-sql/src/test/java/org/eclipse/tractusx/edc/edr/store/sql/SqlEndpointDataReferenceCacheTest.java b/edc-extensions/edr/edr-cache-sql/src/test/java/org/eclipse/tractusx/edc/edr/store/sql/SqlEndpointDataReferenceCacheTest.java index afbe9025b..4faee82c0 100644 --- a/edc-extensions/edr/edr-cache-sql/src/test/java/org/eclipse/tractusx/edc/edr/store/sql/SqlEndpointDataReferenceCacheTest.java +++ b/edc-extensions/edr/edr-cache-sql/src/test/java/org/eclipse/tractusx/edc/edr/store/sql/SqlEndpointDataReferenceCacheTest.java @@ -19,7 +19,7 @@ package org.eclipse.tractusx.edc.edr.store.sql; -import org.eclipse.edc.junit.annotations.PostgresqlDbIntegrationTest; +import org.eclipse.edc.junit.annotations.PostgresqlIntegrationTest; import org.eclipse.edc.spi.result.Result; import org.eclipse.edc.spi.security.Vault; import org.eclipse.edc.spi.types.TypeManager; @@ -53,7 +53,7 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -@PostgresqlDbIntegrationTest +@PostgresqlIntegrationTest @ExtendWith(PostgresqlStoreSetupExtension.class) public class SqlEndpointDataReferenceCacheTest extends EndpointDataReferenceCacheTestBase { diff --git a/edc-extensions/edr/edr-cache-sql/src/test/java/org/eclipse/tractusx/edc/edr/store/sql/SqlEndpointDataReferenceCacheTransactionalTest.java b/edc-extensions/edr/edr-cache-sql/src/test/java/org/eclipse/tractusx/edc/edr/store/sql/SqlEndpointDataReferenceCacheTransactionalTest.java index 4e98b06ea..a3aae64c3 100644 --- a/edc-extensions/edr/edr-cache-sql/src/test/java/org/eclipse/tractusx/edc/edr/store/sql/SqlEndpointDataReferenceCacheTransactionalTest.java +++ b/edc-extensions/edr/edr-cache-sql/src/test/java/org/eclipse/tractusx/edc/edr/store/sql/SqlEndpointDataReferenceCacheTransactionalTest.java @@ -19,7 +19,7 @@ package org.eclipse.tractusx.edc.edr.store.sql; -import org.eclipse.edc.junit.annotations.PostgresqlDbIntegrationTest; +import org.eclipse.edc.junit.annotations.PostgresqlIntegrationTest; import org.eclipse.edc.spi.persistence.EdcPersistenceException; import org.eclipse.edc.spi.query.QuerySpec; import org.eclipse.edc.spi.result.Result; @@ -56,7 +56,7 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -@PostgresqlDbIntegrationTest +@PostgresqlIntegrationTest @ExtendWith(PostgresqlStoreSetupExtension.class) public class SqlEndpointDataReferenceCacheTransactionalTest { diff --git a/edc-extensions/iatp/tx-iatp-sts-dim/src/main/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/DimSecureTokenService.java b/edc-extensions/iatp/tx-iatp-sts-dim/src/main/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/DimSecureTokenService.java index 1de0a017f..95c45bcfe 100644 --- a/edc-extensions/iatp/tx-iatp-sts-dim/src/main/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/DimSecureTokenService.java +++ b/edc-extensions/iatp/tx-iatp-sts-dim/src/main/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/DimSecureTokenService.java @@ -47,7 +47,7 @@ import java.util.function.Consumer; import static java.lang.String.format; -import static org.eclipse.edc.identitytrust.SelfIssuedTokenConstants.PRESENTATION_ACCESS_TOKEN_CLAIM; +import static org.eclipse.edc.identitytrust.SelfIssuedTokenConstants.PRESENTATION_TOKEN_CLAIM; import static org.eclipse.edc.jwt.spi.JwtRegisteredClaimNames.AUDIENCE; import static org.eclipse.edc.jwt.spi.JwtRegisteredClaimNames.ISSUER; import static org.eclipse.edc.jwt.spi.JwtRegisteredClaimNames.SUBJECT; @@ -84,7 +84,7 @@ public class DimSecureTokenService implements SecureTokenService { AUDIENCE, "audience", ISSUER, "issuer", SUBJECT, "subject", - PRESENTATION_ACCESS_TOKEN_CLAIM, "token"); + PRESENTATION_TOKEN_CLAIM, PRESENTATION_TOKEN_CLAIM); public DimSecureTokenService(EdcHttpClient httpClient, String dimBaseUrl, DimOauth2Client dimOauth2Client, ObjectMapper mapper, Monitor monitor) { this.httpClient = httpClient; diff --git a/edc-extensions/iatp/tx-iatp-sts-dim/src/test/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/DimSecureTokenServiceTest.java b/edc-extensions/iatp/tx-iatp-sts-dim/src/test/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/DimSecureTokenServiceTest.java index 7254dac34..f0764b8d6 100644 --- a/edc-extensions/iatp/tx-iatp-sts-dim/src/test/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/DimSecureTokenServiceTest.java +++ b/edc-extensions/iatp/tx-iatp-sts-dim/src/test/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/DimSecureTokenServiceTest.java @@ -45,7 +45,7 @@ import java.util.function.Consumer; import static org.assertj.core.api.Assertions.assertThat; -import static org.eclipse.edc.identitytrust.SelfIssuedTokenConstants.PRESENTATION_ACCESS_TOKEN_CLAIM; +import static org.eclipse.edc.identitytrust.SelfIssuedTokenConstants.PRESENTATION_TOKEN_CLAIM; import static org.eclipse.edc.junit.assertions.AbstractResultAssert.assertThat; import static org.eclipse.edc.junit.testfixtures.TestUtils.testHttpClient; import static org.eclipse.edc.jwt.spi.JwtRegisteredClaimNames.AUDIENCE; @@ -130,7 +130,7 @@ void createToken_signToken() throws IOException { when(interceptor.intercept(isA(Interceptor.Chain.class))) .thenAnswer(invocation -> createResponse(200, invocation, requestAcceptor, response)); - var input = Map.of(ISSUER, "issuer", SUBJECT, "issuer", AUDIENCE, "audience", PRESENTATION_ACCESS_TOKEN_CLAIM, "accessToken"); + var input = Map.of(ISSUER, "issuer", SUBJECT, "issuer", AUDIENCE, "audience", PRESENTATION_TOKEN_CLAIM, "accessToken"); var result = client.createToken(input, null); assertThat(result).isSucceeded() @@ -209,7 +209,7 @@ void createToken_signFails_withDimFailure() throws IOException { when(interceptor.intercept(isA(Interceptor.Chain.class))) .thenAnswer(invocation -> createResponse(500, invocation)); - var input = Map.of(ISSUER, "issuer", SUBJECT, "issuer", AUDIENCE, "audience", PRESENTATION_ACCESS_TOKEN_CLAIM, "token"); + var input = Map.of(ISSUER, "issuer", SUBJECT, "issuer", AUDIENCE, "audience", PRESENTATION_TOKEN_CLAIM, "token"); var result = client.createToken(input, null); assertThat(result).isFailed() @@ -224,7 +224,7 @@ void createToken_signFails_whenBadResponsePayload() throws IOException { when(interceptor.intercept(isA(Interceptor.Chain.class))) .thenAnswer(invocation -> createResponse(200, invocation, Map.of())); - var input = Map.of(ISSUER, "issuer", SUBJECT, "issuer", AUDIENCE, "audience", PRESENTATION_ACCESS_TOKEN_CLAIM, "token"); + var input = Map.of(ISSUER, "issuer", SUBJECT, "issuer", AUDIENCE, "audience", PRESENTATION_TOKEN_CLAIM, "token"); var result = client.createToken(input, null); assertThat(result).isFailed() @@ -247,7 +247,7 @@ void createToken_signFails_whenClaimsMissing() throws IOException { .satisfies(failure -> assertThat(failure.getFailureDetail()) .contains("Key iss not found") .contains("Key sub not found") - .contains("Key access_token not found") + .contains("Key token not found") .contains("Key aud not found")); } diff --git a/edc-extensions/postgresql-migration/src/test/java/org/eclipse/tractusx/edc/postgresql/migration/AssetPostgresqlMigrationExtensionTest.java b/edc-extensions/postgresql-migration/src/test/java/org/eclipse/tractusx/edc/postgresql/migration/AssetPostgresqlMigrationExtensionTest.java index 29b3990dd..34a332f45 100644 --- a/edc-extensions/postgresql-migration/src/test/java/org/eclipse/tractusx/edc/postgresql/migration/AssetPostgresqlMigrationExtensionTest.java +++ b/edc-extensions/postgresql-migration/src/test/java/org/eclipse/tractusx/edc/postgresql/migration/AssetPostgresqlMigrationExtensionTest.java @@ -21,7 +21,7 @@ import org.eclipse.edc.connector.store.sql.assetindex.SqlAssetIndex; import org.eclipse.edc.connector.store.sql.assetindex.schema.postgres.PostgresDialectStatements; -import org.eclipse.edc.junit.annotations.PostgresqlDbIntegrationTest; +import org.eclipse.edc.junit.annotations.PostgresqlIntegrationTest; import org.eclipse.edc.spi.types.TypeManager; import org.eclipse.edc.spi.types.domain.asset.Asset; import org.eclipse.edc.sql.QueryExecutor; @@ -35,7 +35,7 @@ import static org.assertj.core.api.Assertions.assertThat; -@PostgresqlDbIntegrationTest +@PostgresqlIntegrationTest @ExtendWith(PostgresqlStoreSetupExtension.class) class AssetPostgresqlMigrationExtensionTest { @@ -48,7 +48,8 @@ void setUp(PostgresqlStoreSetupExtension extension, QueryExecutor queryExecutor) queryExecutor); } - @Test // bugfix https://github.com/eclipse-tractusx/tractusx-edc/issues/1003 + // bugfix https://github.com/eclipse-tractusx/tractusx-edc/issues/1003 + @Test void version006shouldTransformPropertiesListToMap(PostgresqlStoreSetupExtension extension) { var dataSource = extension.getDataSourceRegistry().resolve(extension.getDatasourceName()); FlywayManager.migrate(dataSource, "asset", "public", MigrationVersion.fromVersion("0.0.5")); diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/catalog/CatalogPostgresqlTest.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/catalog/CatalogPostgresqlTest.java index ffde53573..8c9a11e7b 100644 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/catalog/CatalogPostgresqlTest.java +++ b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/catalog/CatalogPostgresqlTest.java @@ -19,11 +19,11 @@ package org.eclipse.tractusx.edc.tests.catalog; -import org.eclipse.edc.junit.annotations.PostgresqlDbIntegrationTest; +import org.eclipse.edc.junit.annotations.PostgresqlIntegrationTest; import org.eclipse.tractusx.edc.lifecycle.PgParticipantRuntime; import org.junit.jupiter.api.extension.RegisterExtension; -@PostgresqlDbIntegrationTest +@PostgresqlIntegrationTest public class CatalogPostgresqlTest extends AbstractCatalogTest { @RegisterExtension diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/edr/DeleteEdrPostgresqlTest.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/edr/DeleteEdrPostgresqlTest.java index e86adb03a..518393325 100644 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/edr/DeleteEdrPostgresqlTest.java +++ b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/edr/DeleteEdrPostgresqlTest.java @@ -19,11 +19,11 @@ package org.eclipse.tractusx.edc.tests.edr; -import org.eclipse.edc.junit.annotations.PostgresqlDbIntegrationTest; +import org.eclipse.edc.junit.annotations.PostgresqlIntegrationTest; import org.eclipse.tractusx.edc.lifecycle.PgParticipantRuntime; import org.junit.jupiter.api.extension.RegisterExtension; -@PostgresqlDbIntegrationTest +@PostgresqlIntegrationTest public class DeleteEdrPostgresqlTest extends AbstractDeleteEdrTest { @RegisterExtension diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/edr/NegotiateEdrPostgresqlHashicorpVaultTest.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/edr/NegotiateEdrPostgresqlHashicorpVaultTest.java index 59de6d7dc..db2768d4d 100644 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/edr/NegotiateEdrPostgresqlHashicorpVaultTest.java +++ b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/edr/NegotiateEdrPostgresqlHashicorpVaultTest.java @@ -19,12 +19,12 @@ package org.eclipse.tractusx.edc.tests.edr; -import org.eclipse.edc.junit.annotations.PostgresqlDbIntegrationTest; +import org.eclipse.edc.junit.annotations.PostgresqlIntegrationTest; import org.eclipse.tractusx.edc.lifecycle.PgHashicorpParticipantRuntime; import org.eclipse.tractusx.edc.lifecycle.PgParticipantRuntime; import org.junit.jupiter.api.extension.RegisterExtension; -@PostgresqlDbIntegrationTest +@PostgresqlIntegrationTest public class NegotiateEdrPostgresqlHashicorpVaultTest extends AbstractNegotiateEdrTest { @RegisterExtension diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/edr/NegotiateEdrPostgresqlTest.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/edr/NegotiateEdrPostgresqlTest.java index 671298b12..f42c9bd3e 100644 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/edr/NegotiateEdrPostgresqlTest.java +++ b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/edr/NegotiateEdrPostgresqlTest.java @@ -19,11 +19,11 @@ package org.eclipse.tractusx.edc.tests.edr; -import org.eclipse.edc.junit.annotations.PostgresqlDbIntegrationTest; +import org.eclipse.edc.junit.annotations.PostgresqlIntegrationTest; import org.eclipse.tractusx.edc.lifecycle.PgParticipantRuntime; import org.junit.jupiter.api.extension.RegisterExtension; -@PostgresqlDbIntegrationTest +@PostgresqlIntegrationTest public class NegotiateEdrPostgresqlTest extends AbstractNegotiateEdrTest { @RegisterExtension diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/edr/RenewalEdrPostgresqlTest.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/edr/RenewalEdrPostgresqlTest.java index 0f8d81584..9a99b5378 100644 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/edr/RenewalEdrPostgresqlTest.java +++ b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/edr/RenewalEdrPostgresqlTest.java @@ -19,11 +19,11 @@ package org.eclipse.tractusx.edc.tests.edr; -import org.eclipse.edc.junit.annotations.PostgresqlDbIntegrationTest; +import org.eclipse.edc.junit.annotations.PostgresqlIntegrationTest; import org.eclipse.tractusx.edc.lifecycle.PgParticipantRuntime; import org.junit.jupiter.api.extension.RegisterExtension; -@PostgresqlDbIntegrationTest +@PostgresqlIntegrationTest public class RenewalEdrPostgresqlTest extends AbstractRenewalEdrTest { @RegisterExtension diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/policy/PolicyMonitorPostgresqlTest.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/policy/PolicyMonitorPostgresqlTest.java index b3bf139a1..76cd9be67 100644 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/policy/PolicyMonitorPostgresqlTest.java +++ b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/policy/PolicyMonitorPostgresqlTest.java @@ -19,11 +19,11 @@ package org.eclipse.tractusx.edc.tests.policy; -import org.eclipse.edc.junit.annotations.PostgresqlDbIntegrationTest; +import org.eclipse.edc.junit.annotations.PostgresqlIntegrationTest; import org.eclipse.tractusx.edc.lifecycle.PgParticipantRuntime; import org.junit.jupiter.api.extension.RegisterExtension; -@PostgresqlDbIntegrationTest +@PostgresqlIntegrationTest public class PolicyMonitorPostgresqlTest extends AbstractPolicyMonitorTest { @RegisterExtension diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/proxy/DataPlaneProxyPostgresqlTest.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/proxy/DataPlaneProxyPostgresqlTest.java index 09cbc7db7..9d70e013e 100644 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/proxy/DataPlaneProxyPostgresqlTest.java +++ b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/proxy/DataPlaneProxyPostgresqlTest.java @@ -19,11 +19,11 @@ package org.eclipse.tractusx.edc.tests.proxy; -import org.eclipse.edc.junit.annotations.PostgresqlDbIntegrationTest; +import org.eclipse.edc.junit.annotations.PostgresqlIntegrationTest; import org.eclipse.tractusx.edc.lifecycle.PgParticipantRuntime; import org.junit.jupiter.api.extension.RegisterExtension; -@PostgresqlDbIntegrationTest +@PostgresqlIntegrationTest public class DataPlaneProxyPostgresqlTest extends AbstractDataPlaneProxyTest { @RegisterExtension diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/HttpConsumerPullWithProxyPostgresqlTest.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/HttpConsumerPullWithProxyPostgresqlTest.java index a34768e88..14b76e8be 100644 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/HttpConsumerPullWithProxyPostgresqlTest.java +++ b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/HttpConsumerPullWithProxyPostgresqlTest.java @@ -19,11 +19,11 @@ package org.eclipse.tractusx.edc.tests.transfer; -import org.eclipse.edc.junit.annotations.PostgresqlDbIntegrationTest; +import org.eclipse.edc.junit.annotations.PostgresqlIntegrationTest; import org.eclipse.tractusx.edc.lifecycle.PgParticipantRuntime; import org.junit.jupiter.api.extension.RegisterExtension; -@PostgresqlDbIntegrationTest +@PostgresqlIntegrationTest public class HttpConsumerPullWithProxyPostgresqlTest extends AbstractHttpConsumerPullWithProxyTest { diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/HttpProviderPushInPostgresqlTest.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/HttpProviderPushInPostgresqlTest.java index 2c964aa5e..11f9a454e 100644 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/HttpProviderPushInPostgresqlTest.java +++ b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/HttpProviderPushInPostgresqlTest.java @@ -19,11 +19,11 @@ package org.eclipse.tractusx.edc.tests.transfer; -import org.eclipse.edc.junit.annotations.PostgresqlDbIntegrationTest; +import org.eclipse.edc.junit.annotations.PostgresqlIntegrationTest; import org.eclipse.tractusx.edc.lifecycle.PgParticipantRuntime; import org.junit.jupiter.api.extension.RegisterExtension; -@PostgresqlDbIntegrationTest +@PostgresqlIntegrationTest public class HttpProviderPushInPostgresqlTest extends AbstractHttpProviderPushTest { @RegisterExtension diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/token/DimDispatcher.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/token/DimDispatcher.java index b62a52f6b..f79d39d9b 100644 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/token/DimDispatcher.java +++ b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/token/DimDispatcher.java @@ -32,7 +32,7 @@ import java.util.Optional; import java.util.stream.Collectors; -import static org.eclipse.edc.identitytrust.SelfIssuedTokenConstants.PRESENTATION_ACCESS_TOKEN_CLAIM; +import static org.eclipse.edc.identitytrust.SelfIssuedTokenConstants.PRESENTATION_TOKEN_CLAIM; import static org.eclipse.edc.jwt.spi.JwtRegisteredClaimNames.AUDIENCE; import static org.eclipse.edc.jwt.spi.JwtRegisteredClaimNames.ISSUER; import static org.eclipse.edc.jwt.spi.JwtRegisteredClaimNames.SUBJECT; @@ -100,7 +100,7 @@ private MockResponse signTokenHandler(Map params) { ISSUER, issuer, SUBJECT, subject, AUDIENCE, audience, - PRESENTATION_ACCESS_TOKEN_CLAIM, accessToken); + PRESENTATION_TOKEN_CLAIM, accessToken); var sts = secureTokenServices.get(issuer); var token = sts.createToken(claims, null) From 7ddba8e7733d84a4e76a50c4597375f677bd8c50 Mon Sep 17 00:00:00 2001 From: "Sascha Isele (ZF Friedrichshafen AG)" <127207440+saschaisele-zf@users.noreply.github.com> Date: Mon, 18 Mar 2024 15:20:47 +0100 Subject: [PATCH 057/100] feature(api): Update NegotiateEdrRequestDto (#1135) * feature(api): Update NegotiateEdrRequestDto Signed-off-by: Sascha Isele * feature(api): adds `LogDeprecatedValue` to `NegotiateEdrRequestDtoValidator` Signed-off-by: Sascha Isele --------- Signed-off-by: Sascha Isele --- .../tractusx/edc/api/edr/EdrApiExtension.java | 4 +- .../api/edr/dto/NegotiateEdrRequestDto.java | 15 ++++++ .../edc/api/edr/schema/EdrSchema.java | 28 ++++++++++ ...ctToNegotiateEdrRequestDtoTransformer.java | 6 +++ ...tDtoToNegotiatedEdrRequestTransformer.java | 20 +++---- .../NegotiateEdrRequestDtoValidator.java | 47 +++++++++++++--- .../tractusx/edc/api/edr/EdrApiTest.java | 24 ++++++++- .../tractusx/edc/api/edr/TestFunctions.java | 7 +++ ...NegotiateEdrRequestDtoTransformerTest.java | 54 ++++++++++++++++++- ...oToNegotiateEdrRequestTransformerTest.java | 32 +++++++++-- .../NegotiateEdrRequestDtoValidatorTest.java | 25 +++++++-- 11 files changed, 234 insertions(+), 28 deletions(-) diff --git a/edc-extensions/edr/edr-api/src/main/java/org/eclipse/tractusx/edc/api/edr/EdrApiExtension.java b/edc-extensions/edr/edr-api/src/main/java/org/eclipse/tractusx/edc/api/edr/EdrApiExtension.java index 2eb9cdd9b..d4127a778 100644 --- a/edc-extensions/edr/edr-api/src/main/java/org/eclipse/tractusx/edc/api/edr/EdrApiExtension.java +++ b/edc-extensions/edr/edr-api/src/main/java/org/eclipse/tractusx/edc/api/edr/EdrApiExtension.java @@ -20,6 +20,7 @@ package org.eclipse.tractusx.edc.api.edr; import org.eclipse.edc.connector.api.management.configuration.ManagementApiConfiguration; +import org.eclipse.edc.connector.api.management.contractnegotiation.transform.JsonObjectToContractOfferTransformer; import org.eclipse.edc.jsonld.spi.JsonLd; import org.eclipse.edc.runtime.metamodel.annotation.Inject; import org.eclipse.edc.spi.monitor.Monitor; @@ -67,9 +68,10 @@ public void initialize(ServiceExtensionContext context) { var mgmtApiTransformerRegistry = transformerRegistry.forContext("management-api"); mgmtApiTransformerRegistry.register(new NegotiateEdrRequestDtoToNegotiatedEdrRequestTransformer()); mgmtApiTransformerRegistry.register(new JsonObjectToNegotiateEdrRequestDtoTransformer()); + mgmtApiTransformerRegistry.register(new JsonObjectToContractOfferTransformer()); mgmtApiTransformerRegistry.register(new JsonObjectFromEndpointDataReferenceEntryTransformer()); mgmtApiTransformerRegistry.register(new EndpointDataReferenceToDataAddressTransformer()); - validatorRegistry.register(EDR_REQUEST_DTO_TYPE, NegotiateEdrRequestDtoValidator.instance()); + validatorRegistry.register(EDR_REQUEST_DTO_TYPE, NegotiateEdrRequestDtoValidator.instance(context.getMonitor())); webService.registerResource(apiConfig.getContextAlias(), new EdrController(edrService, mgmtApiTransformerRegistry, validatorRegistry, monitor)); } } diff --git a/edc-extensions/edr/edr-api/src/main/java/org/eclipse/tractusx/edc/api/edr/dto/NegotiateEdrRequestDto.java b/edc-extensions/edr/edr-api/src/main/java/org/eclipse/tractusx/edc/api/edr/dto/NegotiateEdrRequestDto.java index cfce992ba..36032948c 100644 --- a/edc-extensions/edr/edr-api/src/main/java/org/eclipse/tractusx/edc/api/edr/dto/NegotiateEdrRequestDto.java +++ b/edc-extensions/edr/edr-api/src/main/java/org/eclipse/tractusx/edc/api/edr/dto/NegotiateEdrRequestDto.java @@ -21,6 +21,7 @@ import org.eclipse.edc.connector.api.management.contractnegotiation.model.ContractOfferDescription; import org.eclipse.edc.spi.types.domain.callback.CallbackAddress; +import org.eclipse.edc.spi.types.domain.offer.ContractOffer; import java.util.ArrayList; import java.util.List; @@ -37,6 +38,7 @@ public class NegotiateEdrRequestDto { public static final String EDR_REQUEST_DTO_COUNTERPARTY_ID = EDC_NAMESPACE + "counterPartyId"; public static final String EDR_REQUEST_DTO_PROVIDER_ID = EDC_NAMESPACE + "providerId"; public static final String EDR_REQUEST_DTO_OFFER = EDC_NAMESPACE + "offer"; + public static final String EDR_REQUEST_DTO_POLICY = EDC_NAMESPACE + "policy"; public static final String EDR_REQUEST_DTO_CALLBACK_ADDRESSES = EDC_NAMESPACE + "callbackAddresses"; private String counterPartyAddress; @@ -45,7 +47,9 @@ public class NegotiateEdrRequestDto { private String providerId; + @Deprecated(since = "0.6.1") private ContractOfferDescription offer; + private ContractOffer contractOffer; private List callbackAddresses = new ArrayList<>(); private NegotiateEdrRequestDto() { @@ -72,10 +76,15 @@ public List getCallbackAddresses() { return callbackAddresses; } + @Deprecated(since = "0.6.1") public ContractOfferDescription getOffer() { return offer; } + public ContractOffer getContractOffer() { + return contractOffer; + } + public static final class Builder { private final NegotiateEdrRequestDto dto; @@ -98,11 +107,17 @@ public Builder counterPartyId(String connectorId) { return this; } + @Deprecated(since = "0.6.1") public Builder offer(ContractOfferDescription offer) { dto.offer = offer; return this; } + public Builder contractOffer(ContractOffer contractOffer) { + dto.contractOffer = contractOffer; + return this; + } + public Builder providerId(String providerId) { dto.providerId = providerId; return this; diff --git a/edc-extensions/edr/edr-api/src/main/java/org/eclipse/tractusx/edc/api/edr/schema/EdrSchema.java b/edc-extensions/edr/edr-api/src/main/java/org/eclipse/tractusx/edc/api/edr/schema/EdrSchema.java index c7dd3fdcb..aaf158007 100644 --- a/edc-extensions/edr/edr-api/src/main/java/org/eclipse/tractusx/edc/api/edr/schema/EdrSchema.java +++ b/edc-extensions/edr/edr-api/src/main/java/org/eclipse/tractusx/edc/api/edr/schema/EdrSchema.java @@ -43,10 +43,38 @@ public record NegotiateEdrRequestSchema( @Schema(deprecated = true, description = "please use providerId instead") String connectorId, String providerId, + @Deprecated(since = "0.6.1") + @Schema(deprecated = true, description = "please use policy instead") ContractNegotiationApi.ContractOfferDescriptionSchema offer, + ManagementApiSchema.PolicySchema policy, List callbackAddresses) { public static final String NEGOTIATE_EDR_REQUEST_EXAMPLE = """ + { + "@context": { "edc": "https://w3id.org/edc/v0.0.1/ns/" }, + "@type": "NegotiateEdrRequestDto", + "counterPartyAddress": "http://provider-address", + "protocol": "dataspace-protocol-http", + "providerId": "provider-id", + "policy": { + "@context": "http://www.w3.org/ns/odrl.jsonld", + "@type": "Set", + "@id": "policy-id", + "target": "asset-id", + "permission": [{ + "action": "display" + }] + }, + "callbackAddresses": [{ + "transactional": false, + "uri": "http://callback/url", + "events": ["contract.negotiation", "transfer.process"] + }] + } + """; + + @Deprecated(since = "0.6.1") + public static final String NEGOTIATE_EDR_REQUEST_DEPRECATED_EXAMPLE = """ { "@context": { "edc": "https://w3id.org/edc/v0.0.1/ns/" }, "@type": "NegotiateEdrRequestDto", diff --git a/edc-extensions/edr/edr-api/src/main/java/org/eclipse/tractusx/edc/api/edr/transform/JsonObjectToNegotiateEdrRequestDtoTransformer.java b/edc-extensions/edr/edr-api/src/main/java/org/eclipse/tractusx/edc/api/edr/transform/JsonObjectToNegotiateEdrRequestDtoTransformer.java index 78ee54cbf..2ab415eeb 100644 --- a/edc-extensions/edr/edr-api/src/main/java/org/eclipse/tractusx/edc/api/edr/transform/JsonObjectToNegotiateEdrRequestDtoTransformer.java +++ b/edc-extensions/edr/edr-api/src/main/java/org/eclipse/tractusx/edc/api/edr/transform/JsonObjectToNegotiateEdrRequestDtoTransformer.java @@ -24,6 +24,7 @@ import org.eclipse.edc.connector.api.management.contractnegotiation.model.ContractOfferDescription; import org.eclipse.edc.jsonld.spi.transformer.AbstractJsonLdTransformer; import org.eclipse.edc.spi.types.domain.callback.CallbackAddress; +import org.eclipse.edc.spi.types.domain.offer.ContractOffer; import org.eclipse.edc.transform.spi.TransformerContext; import org.eclipse.tractusx.edc.api.edr.dto.NegotiateEdrRequestDto; import org.jetbrains.annotations.NotNull; @@ -35,6 +36,7 @@ import static org.eclipse.tractusx.edc.api.edr.dto.NegotiateEdrRequestDto.EDR_REQUEST_DTO_COUNTERPARTY_ADDRESS; import static org.eclipse.tractusx.edc.api.edr.dto.NegotiateEdrRequestDto.EDR_REQUEST_DTO_COUNTERPARTY_ID; import static org.eclipse.tractusx.edc.api.edr.dto.NegotiateEdrRequestDto.EDR_REQUEST_DTO_OFFER; +import static org.eclipse.tractusx.edc.api.edr.dto.NegotiateEdrRequestDto.EDR_REQUEST_DTO_POLICY; import static org.eclipse.tractusx.edc.api.edr.dto.NegotiateEdrRequestDto.EDR_REQUEST_DTO_PROTOCOL; import static org.eclipse.tractusx.edc.api.edr.dto.NegotiateEdrRequestDto.EDR_REQUEST_DTO_PROVIDER_ID; import static org.eclipse.tractusx.edc.api.edr.dto.NegotiateEdrRequestDto.EDR_REQUEST_DTO_TYPE; @@ -76,6 +78,9 @@ private void setProperties(String key, JsonValue value, NegotiateEdrRequestDto.B case EDR_REQUEST_DTO_OFFER: transformArrayOrObject(value, ContractOfferDescription.class, builder::offer, context); break; + case EDR_REQUEST_DTO_POLICY: + transformArrayOrObject(value, ContractOffer.class, builder::contractOffer, context); + break; default: context.problem() .unexpectedType() @@ -88,6 +93,7 @@ private void setProperties(String key, JsonValue value, NegotiateEdrRequestDto.B .expected(EDR_REQUEST_DTO_PROVIDER_ID) .expected(EDR_REQUEST_DTO_CALLBACK_ADDRESSES) .expected(EDR_REQUEST_DTO_OFFER) + .expected(EDR_REQUEST_DTO_POLICY) .report(); break; } diff --git a/edc-extensions/edr/edr-api/src/main/java/org/eclipse/tractusx/edc/api/edr/transform/NegotiateEdrRequestDtoToNegotiatedEdrRequestTransformer.java b/edc-extensions/edr/edr-api/src/main/java/org/eclipse/tractusx/edc/api/edr/transform/NegotiateEdrRequestDtoToNegotiatedEdrRequestTransformer.java index 46bf3e022..fbed87095 100644 --- a/edc-extensions/edr/edr-api/src/main/java/org/eclipse/tractusx/edc/api/edr/transform/NegotiateEdrRequestDtoToNegotiatedEdrRequestTransformer.java +++ b/edc-extensions/edr/edr-api/src/main/java/org/eclipse/tractusx/edc/api/edr/transform/NegotiateEdrRequestDtoToNegotiatedEdrRequestTransformer.java @@ -41,11 +41,17 @@ public Class getOutputType() { @Override public @Nullable NegotiateEdrRequest transform(@NotNull NegotiateEdrRequestDto object, @NotNull TransformerContext context) { - var contractOffer = ContractOffer.Builder.newInstance() - .id(object.getOffer().getOfferId()) - .assetId(object.getOffer().getAssetId()) - .policy(object.getOffer().getPolicy()) - .build(); + ContractOffer contractOffer = null; + + if (object.getContractOffer() != null) { + contractOffer = object.getContractOffer(); + } else if (object.getOffer() != null) { + contractOffer = ContractOffer.Builder.newInstance() + .id(object.getOffer().getOfferId()) + .assetId(object.getOffer().getAssetId()) + .policy(object.getOffer().getPolicy()) + .build(); + } return NegotiateEdrRequest.Builder.newInstance() .connectorId(object.getCounterPartyId()) @@ -56,8 +62,4 @@ public Class getOutputType() { .build(); } - private String getId(String value, String defaultValue) { - return value != null ? value : defaultValue; - } - } diff --git a/edc-extensions/edr/edr-api/src/main/java/org/eclipse/tractusx/edc/api/edr/validation/NegotiateEdrRequestDtoValidator.java b/edc-extensions/edr/edr-api/src/main/java/org/eclipse/tractusx/edc/api/edr/validation/NegotiateEdrRequestDtoValidator.java index 2650e2ba3..75fa1960d 100644 --- a/edc-extensions/edr/edr-api/src/main/java/org/eclipse/tractusx/edc/api/edr/validation/NegotiateEdrRequestDtoValidator.java +++ b/edc-extensions/edr/edr-api/src/main/java/org/eclipse/tractusx/edc/api/edr/validation/NegotiateEdrRequestDtoValidator.java @@ -20,17 +20,22 @@ package org.eclipse.tractusx.edc.api.edr.validation; import jakarta.json.JsonObject; +import org.eclipse.edc.spi.monitor.Monitor; +import org.eclipse.edc.validator.jsonobject.JsonLdPath; import org.eclipse.edc.validator.jsonobject.JsonObjectValidator; +import org.eclipse.edc.validator.jsonobject.validators.LogDeprecatedValue; import org.eclipse.edc.validator.jsonobject.validators.MandatoryObject; import org.eclipse.edc.validator.jsonobject.validators.MandatoryValue; +import org.eclipse.edc.validator.spi.ValidationResult; import org.eclipse.edc.validator.spi.Validator; import static org.eclipse.edc.connector.api.management.contractnegotiation.model.ContractOfferDescription.ASSET_ID; import static org.eclipse.edc.connector.api.management.contractnegotiation.model.ContractOfferDescription.OFFER_ID; -import static org.eclipse.edc.connector.api.management.contractnegotiation.model.ContractOfferDescription.POLICY; import static org.eclipse.tractusx.edc.api.edr.dto.NegotiateEdrRequestDto.EDR_REQUEST_DTO_COUNTERPARTY_ADDRESS; import static org.eclipse.tractusx.edc.api.edr.dto.NegotiateEdrRequestDto.EDR_REQUEST_DTO_OFFER; +import static org.eclipse.tractusx.edc.api.edr.dto.NegotiateEdrRequestDto.EDR_REQUEST_DTO_POLICY; import static org.eclipse.tractusx.edc.api.edr.dto.NegotiateEdrRequestDto.EDR_REQUEST_DTO_PROTOCOL; +import static org.eclipse.tractusx.edc.api.edr.dto.NegotiateEdrRequestDto.EDR_REQUEST_DTO_TYPE; public class NegotiateEdrRequestDtoValidator { @@ -38,16 +43,42 @@ public class NegotiateEdrRequestDtoValidator { private NegotiateEdrRequestDtoValidator() { } - public static Validator instance() { + public static Validator instance(Monitor monitor) { return JsonObjectValidator.newValidator() .verify(EDR_REQUEST_DTO_COUNTERPARTY_ADDRESS, MandatoryValue::new) .verify(EDR_REQUEST_DTO_PROTOCOL, MandatoryValue::new) - .verify(EDR_REQUEST_DTO_OFFER, MandatoryObject::new) - .verifyObject(EDR_REQUEST_DTO_OFFER, v -> v - .verify(OFFER_ID, MandatoryValue::new) - .verify(ASSET_ID, MandatoryValue::new) - .verify(POLICY, MandatoryObject::new) - ) + .verify(EDR_REQUEST_DTO_OFFER, path -> new LogDeprecatedValue(path, EDR_REQUEST_DTO_TYPE, EDR_REQUEST_DTO_POLICY, monitor)) + .verify(MandatoryOfferOrPolicy::new) .build(); } + + private record MandatoryOfferOrPolicy(JsonLdPath path) implements Validator { + @Override + public ValidationResult validate(JsonObject input) { + if (input.containsKey(EDR_REQUEST_DTO_OFFER)) { + return new OfferValidator(path.append(EDR_REQUEST_DTO_OFFER)).validate(input); + } + return new EdrPolicyValidator(path).validate(input); + } + } + + private record OfferValidator(JsonLdPath path) implements Validator { + @Override + public ValidationResult validate(JsonObject input) { + return JsonObjectValidator.newValidator() + .verifyObject(EDR_REQUEST_DTO_OFFER, v -> v + .verify(OFFER_ID, MandatoryValue::new) + .verify(ASSET_ID, MandatoryValue::new) + .verify(EDR_REQUEST_DTO_POLICY, MandatoryObject::new) + ).build().validate(input); + } + } + + private record EdrPolicyValidator(JsonLdPath path) implements Validator { + @Override + public ValidationResult validate(JsonObject input) { + return JsonObjectValidator.newValidator() + .verify(EDR_REQUEST_DTO_POLICY, MandatoryObject::new).build().validate(input); + } + } } diff --git a/edc-extensions/edr/edr-api/src/test/java/org/eclipse/tractusx/edc/api/edr/EdrApiTest.java b/edc-extensions/edr/edr-api/src/test/java/org/eclipse/tractusx/edc/api/edr/EdrApiTest.java index 6649d669a..ebbd44f5a 100644 --- a/edc-extensions/edr/edr-api/src/test/java/org/eclipse/tractusx/edc/api/edr/EdrApiTest.java +++ b/edc-extensions/edr/edr-api/src/test/java/org/eclipse/tractusx/edc/api/edr/EdrApiTest.java @@ -24,6 +24,7 @@ import jakarta.json.JsonObject; import org.eclipse.edc.api.transformer.JsonObjectToCallbackAddressTransformer; import org.eclipse.edc.connector.api.management.contractnegotiation.transform.JsonObjectToContractOfferDescriptionTransformer; +import org.eclipse.edc.connector.api.management.contractnegotiation.transform.JsonObjectToContractOfferTransformer; import org.eclipse.edc.connector.api.management.contractnegotiation.transform.JsonObjectToContractRequestTransformer; import org.eclipse.edc.core.transform.TypeTransformerRegistryImpl; import org.eclipse.edc.core.transform.transformer.odrl.OdrlTransformersFactory; @@ -43,6 +44,7 @@ import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.VALUE; import static org.eclipse.edc.junit.extensions.TestServiceExtensionContext.testServiceExtensionContext; import static org.eclipse.tractusx.edc.api.edr.schema.EdrSchema.EndpointDataReferenceEntrySchema.ENDPOINT_DATA_REFERENCE_ENTRY_EXAMPLE; +import static org.eclipse.tractusx.edc.api.edr.schema.EdrSchema.NegotiateEdrRequestSchema.NEGOTIATE_EDR_REQUEST_DEPRECATED_EXAMPLE; import static org.eclipse.tractusx.edc.api.edr.schema.EdrSchema.NegotiateEdrRequestSchema.NEGOTIATE_EDR_REQUEST_EXAMPLE; import static org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntry.EDR_ENTRY_AGREEMENT_ID; import static org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntry.EDR_ENTRY_ASSET_ID; @@ -66,6 +68,7 @@ public class EdrApiTest { void setUp() { transformer.register(new JsonObjectToContractRequestTransformer()); transformer.register(new JsonObjectToContractOfferDescriptionTransformer()); + transformer.register(new JsonObjectToContractOfferTransformer()); transformer.register(new JsonObjectToCallbackAddressTransformer()); transformer.register(new JsonObjectToNegotiateEdrRequestDtoTransformer()); var mapper = mock(ParticipantIdMapper.class); @@ -77,11 +80,30 @@ void setUp() { @Test void edrRequestExample() throws JsonProcessingException { - var validator = NegotiateEdrRequestDtoValidator.instance(); + var validator = NegotiateEdrRequestDtoValidator.instance(testServiceExtensionContext().getMonitor()); var jsonObject = objectMapper.readValue(NEGOTIATE_EDR_REQUEST_EXAMPLE, JsonObject.class); assertThat(jsonObject).isNotNull(); + var expanded = jsonLd.expand(jsonObject); + AbstractResultAssert.assertThat(expanded).isSucceeded() + .satisfies(exp -> AbstractResultAssert.assertThat(validator.validate(exp)).isSucceeded()) + .extracting(e -> transformer.transform(e, NegotiateEdrRequestDto.class)) + .satisfies(transformResult -> AbstractResultAssert.assertThat(transformResult).isSucceeded() + .satisfies(transformed -> { + assertThat(transformed.getContractOffer()).isNotNull(); + assertThat(transformed.getCallbackAddresses()).asList().hasSize(1); + assertThat(transformed.getProviderId()).isNotBlank(); + })); + } + + @Test + void edrDeprecatedRequestExample() throws JsonProcessingException { + var validator = NegotiateEdrRequestDtoValidator.instance(testServiceExtensionContext().getMonitor()); + + var jsonObject = objectMapper.readValue(NEGOTIATE_EDR_REQUEST_DEPRECATED_EXAMPLE, JsonObject.class); + assertThat(jsonObject).isNotNull(); + var expanded = jsonLd.expand(jsonObject); AbstractResultAssert.assertThat(expanded).isSucceeded() .satisfies(exp -> AbstractResultAssert.assertThat(validator.validate(exp)).isSucceeded()) diff --git a/edc-extensions/edr/edr-api/src/test/java/org/eclipse/tractusx/edc/api/edr/TestFunctions.java b/edc-extensions/edr/edr-api/src/test/java/org/eclipse/tractusx/edc/api/edr/TestFunctions.java index fc622b523..8b05acae7 100644 --- a/edc-extensions/edr/edr-api/src/test/java/org/eclipse/tractusx/edc/api/edr/TestFunctions.java +++ b/edc-extensions/edr/edr-api/src/test/java/org/eclipse/tractusx/edc/api/edr/TestFunctions.java @@ -58,6 +58,13 @@ public static ContractOfferDescription createOffer() { return createOffer(UUID.randomUUID().toString(), UUID.randomUUID().toString()); } + public static ContractOffer createContractOffer() { + return ContractOffer.Builder.newInstance() + .id("offerId") + .assetId("assetId") + .policy(Policy.Builder.newInstance().build()).build(); + } + public static JsonObject negotiationRequest() { return Json.createObjectBuilder() .add(TYPE, NegotiateEdrRequestDto.EDR_REQUEST_DTO_TYPE) diff --git a/edc-extensions/edr/edr-api/src/test/java/org/eclipse/tractusx/edc/api/edr/transform/JsonObjectToNegotiateEdrRequestDtoTransformerTest.java b/edc-extensions/edr/edr-api/src/test/java/org/eclipse/tractusx/edc/api/edr/transform/JsonObjectToNegotiateEdrRequestDtoTransformerTest.java index 5d493cd38..459423c9d 100644 --- a/edc-extensions/edr/edr-api/src/test/java/org/eclipse/tractusx/edc/api/edr/transform/JsonObjectToNegotiateEdrRequestDtoTransformerTest.java +++ b/edc-extensions/edr/edr-api/src/test/java/org/eclipse/tractusx/edc/api/edr/transform/JsonObjectToNegotiateEdrRequestDtoTransformerTest.java @@ -26,8 +26,10 @@ import org.eclipse.edc.connector.api.management.contractnegotiation.model.ContractOfferDescription; import org.eclipse.edc.jsonld.TitaniumJsonLd; import org.eclipse.edc.jsonld.spi.JsonLd; +import org.eclipse.edc.policy.model.Policy; import org.eclipse.edc.spi.monitor.Monitor; import org.eclipse.edc.spi.types.domain.callback.CallbackAddress; +import org.eclipse.edc.spi.types.domain.offer.ContractOffer; import org.eclipse.edc.transform.spi.ProblemBuilder; import org.eclipse.edc.transform.spi.TransformerContext; import org.junit.jupiter.api.BeforeEach; @@ -44,11 +46,13 @@ import static org.eclipse.edc.connector.contract.spi.types.negotiation.ContractRequest.OFFER; import static org.eclipse.edc.connector.contract.spi.types.negotiation.ContractRequest.PROTOCOL; import static org.eclipse.edc.connector.contract.spi.types.negotiation.ContractRequest.PROVIDER_ID; +import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.ID; import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.TYPE; import static org.eclipse.edc.jsonld.spi.PropertyAndTypeNames.ODRL_OBLIGATION_ATTRIBUTE; import static org.eclipse.edc.jsonld.spi.PropertyAndTypeNames.ODRL_PERMISSION_ATTRIBUTE; import static org.eclipse.edc.jsonld.spi.PropertyAndTypeNames.ODRL_POLICY_TYPE_SET; import static org.eclipse.edc.jsonld.spi.PropertyAndTypeNames.ODRL_PROHIBITION_ATTRIBUTE; +import static org.eclipse.edc.jsonld.spi.PropertyAndTypeNames.ODRL_TARGET_ATTRIBUTE; import static org.eclipse.edc.spi.CoreConstants.EDC_NAMESPACE; import static org.eclipse.edc.spi.types.domain.callback.CallbackAddress.EVENTS; import static org.eclipse.edc.spi.types.domain.callback.CallbackAddress.IS_TRANSACTIONAL; @@ -76,6 +80,46 @@ void setUp() { @Test void transform() { + var jsonObject = Json.createObjectBuilder() + .add(TYPE, CONTRACT_REQUEST_TYPE) + .add(EDR_REQUEST_DTO_COUNTERPARTY_ADDRESS, "test-address") + .add(EDR_REQUEST_DTO_COUNTERPARTY_ID, "test-conn-id") + .add(PROTOCOL, "test-protocol") + .add(PROVIDER_ID, "test-provider-id") + .add(CALLBACK_ADDRESSES, createCallbackAddress()) + .add(POLICY, createPolicyJson()) + .build(); + + when(context.transform(any(JsonValue.class), eq(ContractOffer.class))).thenReturn(ContractOffer.Builder.newInstance() + .id("test-offer-id") + .assetId("test-asset-id") + .policy(createPolicyObject()) + .build()); + + when(context.transform(any(JsonObject.class), eq(CallbackAddress.class))).thenReturn(CallbackAddress.Builder.newInstance() + .uri("http://test.local") + .events(Set.of("foo", "bar")) + .transactional(true) + .build()); + when(context.transform(any(CallbackAddress.class), eq(CallbackAddress.class))).thenReturn(CallbackAddress.Builder.newInstance() + .uri("http://test.local") + .events(Set.of("foo", "bar")) + .transactional(true) + .build()); + var dto = transformer.transform(jsonLd.expand(jsonObject).getContent(), context); + + assertThat(dto).isNotNull(); + assertThat(dto.getCallbackAddresses()).isNotEmpty(); + assertThat(dto.getProtocol()).isEqualTo("test-protocol"); + assertThat(dto.getCounterPartyAddress()).isEqualTo("test-address"); + assertThat(dto.getCounterPartyId()).isEqualTo("test-conn-id"); + assertThat(dto.getProviderId()).isEqualTo("test-provider-id"); + assertThat(dto.getContractOffer()).isNotNull(); + + } + + @Test + void transformDeprecatedOffer() { var jsonObject = Json.createObjectBuilder() .add(TYPE, CONTRACT_REQUEST_TYPE) .add(EDR_REQUEST_DTO_COUNTERPARTY_ADDRESS, "test-address") @@ -86,7 +130,7 @@ void transform() { .add(OFFER, Json.createObjectBuilder() .add(OFFER_ID, "test-offer-id") .add(ASSET_ID, "test-asset") - .add(POLICY, createPolicy()) + .add(POLICY, createPolicyJson()) .build()) .build(); @@ -138,18 +182,24 @@ private JsonArrayBuilder createCallbackAddress() { .add(EVENTS, Json.createArrayBuilder().build())); } - private JsonObject createPolicy() { + private JsonObject createPolicyJson() { var permissionJson = getJsonObject("permission"); var prohibitionJson = getJsonObject("prohibition"); var dutyJson = getJsonObject("duty"); return Json.createObjectBuilder() .add(TYPE, ODRL_POLICY_TYPE_SET) + .add(ID, "test-offer-id") .add(ODRL_PERMISSION_ATTRIBUTE, permissionJson) .add(ODRL_PROHIBITION_ATTRIBUTE, prohibitionJson) .add(ODRL_OBLIGATION_ATTRIBUTE, dutyJson) + .add(ODRL_TARGET_ATTRIBUTE, "test-asset-id") .build(); } + private Policy createPolicyObject() { + return Policy.Builder.newInstance().build(); + } + private JsonObject getJsonObject(String type) { return Json.createObjectBuilder() .add(TYPE, type) diff --git a/edc-extensions/edr/edr-api/src/test/java/org/eclipse/tractusx/edc/api/edr/transform/NegotiateEdrRequestDtoToNegotiateEdrRequestTransformerTest.java b/edc-extensions/edr/edr-api/src/test/java/org/eclipse/tractusx/edc/api/edr/transform/NegotiateEdrRequestDtoToNegotiateEdrRequestTransformerTest.java index ed7d31abb..e271eac72 100644 --- a/edc-extensions/edr/edr-api/src/test/java/org/eclipse/tractusx/edc/api/edr/transform/NegotiateEdrRequestDtoToNegotiateEdrRequestTransformerTest.java +++ b/edc-extensions/edr/edr-api/src/test/java/org/eclipse/tractusx/edc/api/edr/transform/NegotiateEdrRequestDtoToNegotiateEdrRequestTransformerTest.java @@ -27,6 +27,7 @@ import java.util.List; import static org.assertj.core.api.Assertions.assertThat; +import static org.eclipse.tractusx.edc.api.edr.TestFunctions.createContractOffer; import static org.eclipse.tractusx.edc.api.edr.TestFunctions.createOffer; import static org.mockito.Mockito.mock; @@ -44,6 +45,31 @@ void inputOutputType() { @Test void verify_transform() { + var callback = CallbackAddress.Builder.newInstance() + .uri("local://test") + .build(); + var dto = NegotiateEdrRequestDto.Builder.newInstance() + .counterPartyId("connectorId") + .connectorAddress("address") + .protocol("protocol") + .providerId("test-provider") + .contractOffer(createContractOffer()) + .callbackAddresses(List.of(callback)) + .build(); + + var request = transformer.transform(dto, context); + + assertThat(request).isNotNull(); + assertThat(request.getConnectorId()).isEqualTo("connectorId"); + assertThat(request.getConnectorAddress()).isEqualTo("address"); + assertThat(request.getProtocol()).isEqualTo("protocol"); + assertThat(request.getOffer().getId()).isEqualTo("offerId"); + assertThat(request.getOffer().getPolicy()).isNotNull(); + assertThat(request.getCallbackAddresses()).hasSize(1); + } + + @Test + void verify_transformDeprecatedOffer() { var callback = CallbackAddress.Builder.newInstance() .uri("local://test") .build(); @@ -68,13 +94,13 @@ void verify_transform() { } @Test - void verify_transfor_withNoProviderId() { + void verify_transform_withNoProviderId() { var dto = NegotiateEdrRequestDto.Builder.newInstance() .counterPartyId("connectorId") .connectorAddress("address") .protocol("protocol") // do not set provider ID - .offer(createOffer("offerId", "assetId")) + .contractOffer(createContractOffer()) .build(); var request = transformer.transform(dto, context); @@ -90,7 +116,7 @@ void verify_transform_withNoConsumerId() { .protocol("protocol") // do not set consumer ID .providerId("urn:connector:test-provider") - .offer(createOffer("offerId", "assetId")) + .contractOffer(createContractOffer()) .build(); var request = transformer.transform(dto, context); diff --git a/edc-extensions/edr/edr-api/src/test/java/org/eclipse/tractusx/edc/api/edr/validation/NegotiateEdrRequestDtoValidatorTest.java b/edc-extensions/edr/edr-api/src/test/java/org/eclipse/tractusx/edc/api/edr/validation/NegotiateEdrRequestDtoValidatorTest.java index 55f28eb91..c6f82df80 100644 --- a/edc-extensions/edr/edr-api/src/test/java/org/eclipse/tractusx/edc/api/edr/validation/NegotiateEdrRequestDtoValidatorTest.java +++ b/edc-extensions/edr/edr-api/src/test/java/org/eclipse/tractusx/edc/api/edr/validation/NegotiateEdrRequestDtoValidatorTest.java @@ -22,6 +22,7 @@ import jakarta.json.Json; import jakarta.json.JsonArrayBuilder; import jakarta.json.JsonObject; +import org.eclipse.edc.spi.monitor.Monitor; import org.eclipse.edc.validator.spi.ValidationFailure; import org.eclipse.edc.validator.spi.Validator; import org.eclipse.edc.validator.spi.Violation; @@ -38,15 +39,31 @@ import static org.eclipse.edc.junit.assertions.AbstractResultAssert.assertThat; import static org.eclipse.tractusx.edc.api.edr.dto.NegotiateEdrRequestDto.EDR_REQUEST_DTO_COUNTERPARTY_ADDRESS; import static org.eclipse.tractusx.edc.api.edr.dto.NegotiateEdrRequestDto.EDR_REQUEST_DTO_OFFER; +import static org.eclipse.tractusx.edc.api.edr.dto.NegotiateEdrRequestDto.EDR_REQUEST_DTO_POLICY; import static org.eclipse.tractusx.edc.api.edr.dto.NegotiateEdrRequestDto.EDR_REQUEST_DTO_PROTOCOL; import static org.eclipse.tractusx.edc.api.edr.dto.NegotiateEdrRequestDto.EDR_REQUEST_DTO_PROVIDER_ID; +import static org.mockito.Mockito.mock; public class NegotiateEdrRequestDtoValidatorTest { - private final Validator validator = NegotiateEdrRequestDtoValidator.instance(); + private final Validator validator = NegotiateEdrRequestDtoValidator.instance(mock(Monitor.class)); @Test - void shouldSuccess_whenObjectIsValid() { + void shouldSucceed_whenObjectIsValid() { + var input = Json.createObjectBuilder() + .add(EDR_REQUEST_DTO_COUNTERPARTY_ADDRESS, value("http://connector-address")) + .add(EDR_REQUEST_DTO_PROTOCOL, value("protocol")) + .add(EDR_REQUEST_DTO_PROVIDER_ID, value("connector-id")) + .add(EDR_REQUEST_DTO_POLICY, createArrayBuilder().add(createObjectBuilder())) + .build(); + + var result = validator.validate(input); + + assertThat(result).isSucceeded(); + } + + @Test + void shouldSucceed_whenDeprecatedOfferIsUsed() { var input = Json.createObjectBuilder() .add(EDR_REQUEST_DTO_COUNTERPARTY_ADDRESS, value("http://connector-address")) .add(EDR_REQUEST_DTO_PROTOCOL, value("protocol")) @@ -54,7 +71,7 @@ void shouldSuccess_whenObjectIsValid() { .add(EDR_REQUEST_DTO_OFFER, createArrayBuilder().add(createObjectBuilder() .add(OFFER_ID, value("offerId")) .add(ASSET_ID, value("offerId")) - .add(POLICY, createArrayBuilder().add(createObjectBuilder())) + .add(EDR_REQUEST_DTO_POLICY, createArrayBuilder().add(createObjectBuilder())) )) .build(); @@ -73,7 +90,7 @@ void shouldFail_whenMandatoryPropertiesAreMissing() { .isNotEmpty() .anySatisfy(violation -> assertThat(violation.path()).isEqualTo(EDR_REQUEST_DTO_COUNTERPARTY_ADDRESS)) .anySatisfy(violation -> assertThat(violation.path()).isEqualTo(EDR_REQUEST_DTO_PROTOCOL)) - .anySatisfy(violation -> assertThat(violation.path()).isEqualTo(EDR_REQUEST_DTO_OFFER)); + .anySatisfy(violation -> assertThat(violation.path()).isEqualTo(EDR_REQUEST_DTO_POLICY)); } @Test From 68e6b04d97e0f9df22f47d555bb96ad0983f847a Mon Sep 17 00:00:00 2001 From: Paul Latzelsperger <43503240+paullatzelsperger@users.noreply.github.com> Date: Mon, 18 Mar 2024 17:48:31 +0100 Subject: [PATCH 058/100] chore: add CodeQL workflow (#1143) --- .github/workflows/codeql.yaml | 84 ++++++++++++++++++++++++++++++ .github/workflows/veracode.yaml | 92 --------------------------------- 2 files changed, 84 insertions(+), 92 deletions(-) create mode 100644 .github/workflows/codeql.yaml delete mode 100644 .github/workflows/veracode.yaml diff --git a/.github/workflows/codeql.yaml b/.github/workflows/codeql.yaml new file mode 100644 index 000000000..57108b49d --- /dev/null +++ b/.github/workflows/codeql.yaml @@ -0,0 +1,84 @@ +################################################################################# +# Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License, Version 2.0 which is available at +# https://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. +# +# SPDX-License-Identifier: Apache-2.0 +################################################################################# + +name: "CodeQL" + +on: + push: + branches: [ "main" ] + paths-ignore: + - "**/*.md" + - "**/*.txt" + pull_request: + branches: [ "main" ] + paths-ignore: + - "**/*.md" + - "**/*.txt" + schedule: + - cron: "0 0 * * 0" + workflow_dispatch: + +jobs: + analyze: + name: Analyze + runs-on: ubuntu-latest + timeout-minutes: 360 + permissions: + actions: read + contents: read + security-events: write + + strategy: + fail-fast: false + matrix: + language: [ "java" ] # Define languages here + # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby', 'swift' ] + # Use only 'java' to analyze code written in Java, Kotlin or both + # Use only 'javascript' to analyze code written in JavaScript, TypeScript or both + # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v2 + with: + languages: ${{ matrix.language }} + # If you wish to specify custom queries, you can do so here or in a config file + # By default, queries listed here will override any specified in a config file + # Prefix the list here with "+" to use these queries and those in the config file + + # For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs + # Use +security-extended,security-and-quality for wider security and better code quality + queries: +security-extended,security-and-quality + + + # build only production code, no test sources + - uses: ./.github/actions/setup-java + - name: Build Production Code + run: | + ./gradlew compileJava --no-daemon + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v3 + with: + category: "/language:${{matrix.language}}" + fail-on: error \ No newline at end of file diff --git a/.github/workflows/veracode.yaml b/.github/workflows/veracode.yaml deleted file mode 100644 index 2ed6cae51..000000000 --- a/.github/workflows/veracode.yaml +++ /dev/null @@ -1,92 +0,0 @@ -################################################################################# -# Copyright (c) 2021,2023 Contributors to the Eclipse Foundation -# -# See the NOTICE file(s) distributed with this work for additional -# information regarding copyright ownership. -# -# This program and the accompanying materials are made available under the -# terms of the Apache License, Version 2.0 which is available at -# https://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. -# -# SPDX-License-Identifier: Apache-2.0 -################################################################################# - - ---- -name: "Veracode" - -on: - schedule: - - cron: '0 2 * * *' - workflow_dispatch: - -jobs: - secret-presence: - runs-on: ubuntu-latest - outputs: - ORG_VERACODE_API_ID: ${{ steps.secret-presence.outputs.ORG_VERACODE_API_ID }} - ORG_VERACODE_API_KEY: ${{ steps.secret-presence.outputs.ORG_VERACODE_API_KEY }} - steps: - - name: Check whether secrets exist - id: secret-presence - run: | - [ ! -z "${{ secrets.ORG_VERACODE_API_ID }}" ] && echo "ORG_VERACODE_API_ID=true" >> $GITHUB_OUTPUT - [ ! -z "${{ secrets.ORG_VERACODE_API_KEY }}" ] && echo "ORG_VERACODE_API_KEY=true" >> $GITHUB_OUTPUT - exit 0 - - verify-formatting: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - uses: ./.github/actions/setup-java - - name: Run Checkstyle - run: | - ./gradlew checkstyleMain checkstyleTest - - build: - runs-on: ubuntu-latest - needs: [ secret-presence, verify-formatting ] - permissions: - contents: read - strategy: - fail-fast: false - matrix: - variant: [ { dir: edc-controlplane, name: edc-runtime-memory }, - { dir: edc-controlplane, name: edc-controlplane-postgresql-hashicorp-vault }, - { dir: edc-controlplane, name: edc-controlplane-postgresql-azure-vault }, - { dir: edc-dataplane, name: edc-dataplane-azure-vault }, - { dir: edc-dataplane, name: edc-dataplane-hashicorp-vault } ] - steps: - # Set-Up - - uses: actions/checkout@v4 - - uses: ./.github/actions/setup-java - # Build - - name: Build ${{ matrix.variant.name }} - run: |- - ./gradlew -p ${{ matrix.variant.dir }}/${{ matrix.variant.name }} shadowJar - env: - GITHUB_PACKAGE_USERNAME: ${{ github.actor }} - GITHUB_PACKAGE_PASSWORD: ${{ secrets.GITHUB_TOKEN }} - - name: Tar gzip files for veracode upload - run: |- - tar -czvf ${{ matrix.variant.dir }}/${{ matrix.variant.name }}/build/libs/${{ matrix.variant.name }}.tar.gz ${{ matrix.variant.dir }}/${{ matrix.variant.name }}/build/libs/${{ matrix.variant.name }}.jar - - name: Veracode Upload And Scan - uses: veracode/veracode-uploadandscan-action@v1.0 - if: | - needs.secret-presence.outputs.ORG_VERACODE_API_ID && needs.secret-presence.outputs.ORG_VERACODE_API_KEY - continue-on-error: true - with: - appname: tractusx-edc/${{ matrix.variant.name }} - createprofile: true - version: ${{ matrix.variant.name }}-${{ github.sha }} - filepath: ${{ matrix.variant.dir }}/${{ matrix.variant.name }}/build/libs/${{ matrix.variant.name }}.tar.gz - vid: ${{ secrets.ORG_VERACODE_API_ID }} - vkey: ${{ secrets.ORG_VERACODE_API_KEY }} From e856f95c9fbd8e40a817528ea4381ab87b312e51 Mon Sep 17 00:00:00 2001 From: Paul Latzelsperger <43503240+paullatzelsperger@users.noreply.github.com> Date: Mon, 18 Mar 2024 19:44:18 +0100 Subject: [PATCH 059/100] feat: add new V2 EDR API (#1140) * feat: add new V2 EDR API * DEPENDENCIES * DEPENDENCIES * temporarily refresh deps * disable edr2 test * introduce separate test module for edr-v2 * pr remarks * parallelize e2e tests --- .github/workflows/verify.yaml | 13 +- DEPENDENCIES | 101 ++++++ .../edr/edr-api-v2/build.gradle.kts | 42 +++ .../tractusx/edc/api/edr/v2/EdrCacheApi.java | 129 +++++++ .../edc/api/edr/v2/EdrCacheApiController.java | 194 ++++++++++ .../edc/api/edr/v2/EdrCacheApiExtension.java | 84 +++++ .../edr/v2/dto/NegotiateEdrRequestDto.java | 124 +++++++ .../edc/api/edr/v2/schema/EdrSchema.java | 109 ++++++ ...DataReferenceToDataAddressTransformer.java | 57 +++ ...EndpointDataReferenceEntryTransformer.java | 62 ++++ ...ctToNegotiateEdrRequestDtoTransformer.java | 87 +++++ ...tDtoToNegotiatedEdrRequestTransformer.java | 63 ++++ .../NegotiateEdrRequestDtoValidator.java | 51 +++ ...rg.eclipse.edc.spi.system.ServiceExtension | 20 ++ .../api/edr/v2/EdrCacheApiControllerTest.java | 226 ++++++++++++ .../api/edr/v2/EdrCacheApiExtensionTest.java | 67 ++++ .../edc/api/edr/v2/EdrCacheApiTest.java | 61 ++++ .../edc/api/edr/v2/TestFunctions.java | 87 +++++ ...ReferenceToDataAddressTransformerTest.java | 66 ++++ ...ointDataReferenceEntryTransformerTest.java | 69 ++++ ...NegotiateEdrRequestDtoTransformerTest.java | 158 +++++++++ ...oToNegotiateEdrRequestTransformerTest.java | 99 ++++++ .../NegotiateEdrRequestDtoValidatorTest.java | 100 ++++++ .../tokenrefresh-handler/build.gradle.kts | 1 + .../TokenRefreshHandlerExtension.java | 4 +- .../tokenrefresh/TokenRefreshHandlerImpl.java | 86 +++-- .../TokenRefreshHandlerImplTest.java | 59 ++-- .../edc/lifecycle/tx/ParticipantEdrApi.java | 47 +++ .../edr-tests/build.gradle.kts | 51 +++ .../edc/tests/CatalogHelperFunctions.java | 76 ++++ .../tests/EdrNegotiationHelperFunctions.java | 68 ++++ .../eclipse/tractusx/edc/tests/Functions.java | 63 ++++ .../edc/tests/MockBpnIdentityService.java | 70 ++++ .../tractusx/edc/tests/ParticipantEdrApi.java | 206 +++++++++++ .../edc/tests/ParticipantRuntime.java | 108 ++++++ .../tractusx/edc/tests/TxParticipant.java | 116 ++++++ .../tests/edrv2/EdrCacheApiEndToEndTest.java | 332 ++++++++++++++++++ .../runtime-memory-signaling/README.md | 3 + .../runtime-memory-signaling/build.gradle.kts | 45 +++ gradle/libs.versions.toml | 5 + settings.gradle.kts | 7 +- .../tractusx/edc/edr/spi/CoreConstants.java | 1 + .../common/TokenRefreshHandler.java | 17 +- 43 files changed, 3369 insertions(+), 65 deletions(-) create mode 100644 edc-extensions/edr/edr-api-v2/build.gradle.kts create mode 100644 edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/EdrCacheApi.java create mode 100644 edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/EdrCacheApiController.java create mode 100644 edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/EdrCacheApiExtension.java create mode 100644 edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/dto/NegotiateEdrRequestDto.java create mode 100644 edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/schema/EdrSchema.java create mode 100644 edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/transform/EndpointDataReferenceToDataAddressTransformer.java create mode 100644 edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/transform/JsonObjectFromEndpointDataReferenceEntryTransformer.java create mode 100644 edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/transform/JsonObjectToNegotiateEdrRequestDtoTransformer.java create mode 100644 edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/transform/NegotiateEdrRequestDtoToNegotiatedEdrRequestTransformer.java create mode 100644 edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/validation/NegotiateEdrRequestDtoValidator.java create mode 100644 edc-extensions/edr/edr-api-v2/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension create mode 100644 edc-extensions/edr/edr-api-v2/src/test/java/org/eclipse/tractusx/edc/api/edr/v2/EdrCacheApiControllerTest.java create mode 100644 edc-extensions/edr/edr-api-v2/src/test/java/org/eclipse/tractusx/edc/api/edr/v2/EdrCacheApiExtensionTest.java create mode 100644 edc-extensions/edr/edr-api-v2/src/test/java/org/eclipse/tractusx/edc/api/edr/v2/EdrCacheApiTest.java create mode 100644 edc-extensions/edr/edr-api-v2/src/test/java/org/eclipse/tractusx/edc/api/edr/v2/TestFunctions.java create mode 100644 edc-extensions/edr/edr-api-v2/src/test/java/org/eclipse/tractusx/edc/api/edr/v2/transform/EndpointDataReferenceToDataAddressTransformerTest.java create mode 100644 edc-extensions/edr/edr-api-v2/src/test/java/org/eclipse/tractusx/edc/api/edr/v2/transform/JsonObjectFromEndpointDataReferenceEntryTransformerTest.java create mode 100644 edc-extensions/edr/edr-api-v2/src/test/java/org/eclipse/tractusx/edc/api/edr/v2/transform/JsonObjectToNegotiateEdrRequestDtoTransformerTest.java create mode 100644 edc-extensions/edr/edr-api-v2/src/test/java/org/eclipse/tractusx/edc/api/edr/v2/transform/NegotiateEdrRequestDtoToNegotiateEdrRequestTransformerTest.java create mode 100644 edc-extensions/edr/edr-api-v2/src/test/java/org/eclipse/tractusx/edc/api/edr/v2/validation/NegotiateEdrRequestDtoValidatorTest.java create mode 100644 edc-tests/edc-controlplane/edr-tests/build.gradle.kts create mode 100644 edc-tests/edc-controlplane/edr-tests/src/test/java/org/eclipse/tractusx/edc/tests/CatalogHelperFunctions.java create mode 100644 edc-tests/edc-controlplane/edr-tests/src/test/java/org/eclipse/tractusx/edc/tests/EdrNegotiationHelperFunctions.java create mode 100644 edc-tests/edc-controlplane/edr-tests/src/test/java/org/eclipse/tractusx/edc/tests/Functions.java create mode 100644 edc-tests/edc-controlplane/edr-tests/src/test/java/org/eclipse/tractusx/edc/tests/MockBpnIdentityService.java create mode 100644 edc-tests/edc-controlplane/edr-tests/src/test/java/org/eclipse/tractusx/edc/tests/ParticipantEdrApi.java create mode 100644 edc-tests/edc-controlplane/edr-tests/src/test/java/org/eclipse/tractusx/edc/tests/ParticipantRuntime.java create mode 100644 edc-tests/edc-controlplane/edr-tests/src/test/java/org/eclipse/tractusx/edc/tests/TxParticipant.java create mode 100644 edc-tests/edc-controlplane/edr-tests/src/test/java/org/eclipse/tractusx/edc/tests/edrv2/EdrCacheApiEndToEndTest.java create mode 100644 edc-tests/runtime/runtime-memory-signaling/README.md create mode 100644 edc-tests/runtime/runtime-memory-signaling/build.gradle.kts diff --git a/.github/workflows/verify.yaml b/.github/workflows/verify.yaml index 736fdae41..dc76681c9 100644 --- a/.github/workflows/verify.yaml +++ b/.github/workflows/verify.yaml @@ -113,13 +113,20 @@ jobs: end-to-end-tests: runs-on: ubuntu-latest needs: [ verify-formatting, verify-license-headers ] + strategy: + fail-fast: false + matrix: + variant: [ { dir: edc-tests/edc-controlplane}, + { dir: edc-tests/e2e-tests} + ] steps: - uses: actions/checkout@v4 - - uses: ./.github/actions/setup-java - - name: Run E2E tests - run: ./gradlew test -DincludeTags="EndToEndTest" + - name: Run E2E tests (${{ matrix.variant.dir }}) + run: | + ./gradlew compileJava compileTestJava + ./gradlew -p ${{ matrix.variant.dir }} test -DincludeTags="EndToEndTest" postgres-tests: runs-on: ubuntu-latest diff --git a/DEPENDENCIES b/DEPENDENCIES index 0c1fe4674..54d232212 100644 --- a/DEPENDENCIES +++ b/DEPENDENCIES @@ -18,19 +18,26 @@ maven/mavencentral/com.azure/azure-security-keyvault-secrets/4.8.0, MIT, approve maven/mavencentral/com.azure/azure-storage-blob/12.25.2, MIT, approved, #13400 maven/mavencentral/com.azure/azure-storage-common/12.24.2, MIT, approved, #13402 maven/mavencentral/com.azure/azure-storage-internal-avro/12.10.2, MIT, approved, #13399 +maven/mavencentral/com.ethlo.time/itu/1.7.0, Apache-2.0, approved, clearlydefined maven/mavencentral/com.fasterxml.jackson.core/jackson-annotations/2.10.3, Apache-2.0, approved, CQ21280 maven/mavencentral/com.fasterxml.jackson.core/jackson-annotations/2.13.5, Apache-2.0, approved, clearlydefined +maven/mavencentral/com.fasterxml.jackson.core/jackson-annotations/2.14.0, Apache-2.0, approved, #5303 +maven/mavencentral/com.fasterxml.jackson.core/jackson-annotations/2.14.1, Apache-2.0, approved, #5303 maven/mavencentral/com.fasterxml.jackson.core/jackson-annotations/2.15.1, Apache-2.0, approved, #7947 maven/mavencentral/com.fasterxml.jackson.core/jackson-annotations/2.15.2, Apache-2.0, approved, #7947 maven/mavencentral/com.fasterxml.jackson.core/jackson-annotations/2.15.3, Apache-2.0, approved, #7947 maven/mavencentral/com.fasterxml.jackson.core/jackson-annotations/2.16.1, Apache-2.0, approved, #11606 maven/mavencentral/com.fasterxml.jackson.core/jackson-annotations/2.16.2, Apache-2.0, approved, #11606 maven/mavencentral/com.fasterxml.jackson.core/jackson-core/2.13.5, Apache-2.0, approved, #2133 +maven/mavencentral/com.fasterxml.jackson.core/jackson-core/2.14.1, Apache-2.0 AND MIT, approved, #4303 maven/mavencentral/com.fasterxml.jackson.core/jackson-core/2.15.1, MIT AND Apache-2.0, approved, #7932 maven/mavencentral/com.fasterxml.jackson.core/jackson-core/2.16.1, Apache-2.0 AND MIT, approved, #11602 maven/mavencentral/com.fasterxml.jackson.core/jackson-core/2.16.2, Apache-2.0 AND MIT, approved, #11602 +maven/mavencentral/com.fasterxml.jackson.core/jackson-databind/2.11.0, Apache-2.0, approved, CQ23093 maven/mavencentral/com.fasterxml.jackson.core/jackson-databind/2.13.4.2, Apache-2.0, approved, #2134 maven/mavencentral/com.fasterxml.jackson.core/jackson-databind/2.13.5, Apache-2.0, approved, #2134 +maven/mavencentral/com.fasterxml.jackson.core/jackson-databind/2.14.0, Apache-2.0, approved, #4105 +maven/mavencentral/com.fasterxml.jackson.core/jackson-databind/2.14.1, Apache-2.0, approved, #4105 maven/mavencentral/com.fasterxml.jackson.core/jackson-databind/2.14.2, Apache-2.0, approved, #4105 maven/mavencentral/com.fasterxml.jackson.core/jackson-databind/2.15.1, Apache-2.0, approved, #7934 maven/mavencentral/com.fasterxml.jackson.core/jackson-databind/2.15.2, Apache-2.0, approved, #7934 @@ -41,12 +48,14 @@ maven/mavencentral/com.fasterxml.jackson.dataformat/jackson-dataformat-toml/2.15 maven/mavencentral/com.fasterxml.jackson.dataformat/jackson-dataformat-toml/2.16.2, Apache-2.0, approved, #13145 maven/mavencentral/com.fasterxml.jackson.dataformat/jackson-dataformat-xml/2.13.5, Apache-2.0, approved, #3768 maven/mavencentral/com.fasterxml.jackson.dataformat/jackson-dataformat-xml/2.16.2, Apache-2.0, approved, #12438 +maven/mavencentral/com.fasterxml.jackson.dataformat/jackson-dataformat-yaml/2.14.0, Apache-2.0, approved, #5933 maven/mavencentral/com.fasterxml.jackson.dataformat/jackson-dataformat-yaml/2.15.1, Apache-2.0, approved, #8802 maven/mavencentral/com.fasterxml.jackson.dataformat/jackson-dataformat-yaml/2.15.2, Apache-2.0, approved, #8802 maven/mavencentral/com.fasterxml.jackson.dataformat/jackson-dataformat-yaml/2.16.2, Apache-2.0, approved, #11855 maven/mavencentral/com.fasterxml.jackson.datatype/jackson-datatype-jakarta-jsonp/2.16.1, Apache-2.0, approved, #11854 maven/mavencentral/com.fasterxml.jackson.datatype/jackson-datatype-jakarta-jsonp/2.16.2, Apache-2.0, approved, #11854 maven/mavencentral/com.fasterxml.jackson.datatype/jackson-datatype-jsr310/2.13.5, Apache-2.0, approved, clearlydefined +maven/mavencentral/com.fasterxml.jackson.datatype/jackson-datatype-jsr310/2.14.0, Apache-2.0, approved, #4699 maven/mavencentral/com.fasterxml.jackson.datatype/jackson-datatype-jsr310/2.15.1, Apache-2.0, approved, #7930 maven/mavencentral/com.fasterxml.jackson.datatype/jackson-datatype-jsr310/2.15.2, Apache-2.0, approved, #7930 maven/mavencentral/com.fasterxml.jackson.datatype/jackson-datatype-jsr310/2.16.1, Apache-2.0, approved, #11853 @@ -60,32 +69,57 @@ maven/mavencentral/com.fasterxml.jackson.module/jackson-module-jakarta-xmlbind-a maven/mavencentral/com.fasterxml.jackson/jackson-bom/2.15.1, Apache-2.0, approved, #7929 maven/mavencentral/com.fasterxml.jackson/jackson-bom/2.16.1, Apache-2.0, approved, #11852 maven/mavencentral/com.fasterxml.jackson/jackson-bom/2.16.2, Apache-2.0, approved, #11852 +maven/mavencentral/com.fasterxml.uuid/java-uuid-generator/4.1.0, Apache-2.0, approved, clearlydefined maven/mavencentral/com.fasterxml.woodstox/woodstox-core/6.5.1, Apache-2.0, approved, #7950 +maven/mavencentral/com.github.cliftonlabs/json-simple/3.0.2, Apache-2.0, approved, clearlydefined maven/mavencentral/com.github.docker-java/docker-java-api/3.3.5, Apache-2.0, approved, #10346 maven/mavencentral/com.github.docker-java/docker-java-api/3.3.6, Apache-2.0, approved, #10346 maven/mavencentral/com.github.docker-java/docker-java-transport-zerodep/3.3.5, Apache-2.0 AND (Apache-2.0 AND BSD-3-Clause), approved, #7946 maven/mavencentral/com.github.docker-java/docker-java-transport-zerodep/3.3.6, Apache-2.0 AND (Apache-2.0 AND BSD-3-Clause), approved, #7946 maven/mavencentral/com.github.docker-java/docker-java-transport/3.3.5, Apache-2.0, approved, #7942 maven/mavencentral/com.github.docker-java/docker-java-transport/3.3.6, Apache-2.0, approved, #7942 +maven/mavencentral/com.github.java-json-tools/btf/1.3, Apache-2.0 OR LGPL-3.0-or-later, approved, #2721 +maven/mavencentral/com.github.java-json-tools/jackson-coreutils-equivalence/1.0, LGPL-3.0 OR Apache-2.0, approved, clearlydefined +maven/mavencentral/com.github.java-json-tools/jackson-coreutils/2.0, Apache-2.0 OR LGPL-3.0-or-later, approved, #2719 +maven/mavencentral/com.github.java-json-tools/json-patch/1.13, Apache-2.0 OR LGPL-3.0-or-later, approved, CQ23929 +maven/mavencentral/com.github.java-json-tools/json-schema-core/1.2.14, Apache-2.0 OR LGPL-3.0-or-later, approved, #2722 +maven/mavencentral/com.github.java-json-tools/json-schema-validator/2.2.14, Apache-2.0 OR LGPL-3.0-or-later, approved, CQ20779 +maven/mavencentral/com.github.java-json-tools/msg-simple/1.2, Apache-2.0 OR LGPL-3.0-or-later, approved, #2720 +maven/mavencentral/com.github.java-json-tools/uri-template/0.10, Apache-2.0 OR LGPL-3.0-only, approved, #2723 maven/mavencentral/com.github.stephenc.jcip/jcip-annotations/1.0-1, Apache-2.0, approved, CQ21949 +maven/mavencentral/com.google.code.findbugs/jsr305/2.0.1, BSD-3-Clause AND CC-BY-2.5 AND LGPL-2.1+, approved, CQ13390 maven/mavencentral/com.google.code.findbugs/jsr305/3.0.2, Apache-2.0, approved, #20 maven/mavencentral/com.google.code.gson/gson/2.10.1, Apache-2.0, approved, #6159 maven/mavencentral/com.google.crypto.tink/tink/1.12.0, Apache-2.0, approved, #12041 +maven/mavencentral/com.google.errorprone/error_prone_annotations/2.11.0, Apache-2.0, approved, clearlydefined maven/mavencentral/com.google.errorprone/error_prone_annotations/2.22.0, Apache-2.0, approved, #10661 maven/mavencentral/com.google.errorprone/error_prone_annotations/2.26.1, Apache-2.0, approved, #13657 +maven/mavencentral/com.google.guava/failureaccess/1.0.1, Apache-2.0, approved, CQ22654 maven/mavencentral/com.google.guava/failureaccess/1.0.2, Apache-2.0, approved, CQ22654 +maven/mavencentral/com.google.guava/guava/28.1-android, Apache-2.0, approved, clearlydefined +maven/mavencentral/com.google.guava/guava/28.2-android, Apache-2.0 AND LicenseRef-Public-Domain, approved, CQ22437 +maven/mavencentral/com.google.guava/guava/31.0.1-android, Apache-2.0, approved, clearlydefined +maven/mavencentral/com.google.guava/guava/31.1-jre, Apache-2.0, approved, clearlydefined maven/mavencentral/com.google.guava/guava/33.1.0-jre, Apache-2.0 AND CC0-1.0, approved, #13675 maven/mavencentral/com.google.guava/listenablefuture/9999.0-empty-to-avoid-conflict-with-guava, Apache-2.0, approved, CQ22657 +maven/mavencentral/com.google.j2objc/j2objc-annotations/1.3, Apache-2.0, approved, CQ21195 maven/mavencentral/com.google.protobuf/protobuf-java/3.24.3, BSD-3-Clause, approved, clearlydefined +maven/mavencentral/com.googlecode.libphonenumber/libphonenumber/8.11.1, Apache-2.0, approved, clearlydefined +maven/mavencentral/com.jayway.jsonpath/json-path/2.7.0, Apache-2.0, approved, clearlydefined +maven/mavencentral/com.jcraft/jzlib/1.1.3, BSD-2-Clause, approved, CQ6218 +maven/mavencentral/com.lmax/disruptor/3.4.4, Apache-2.0, approved, clearlydefined maven/mavencentral/com.microsoft.azure/msal4j-persistence-extension/1.2.0, MIT, approved, clearlydefined maven/mavencentral/com.microsoft.azure/msal4j/1.14.0, MIT, approved, clearlydefined maven/mavencentral/com.microsoft.azure/msal4j/1.4.0, MIT, approved, clearlydefined +maven/mavencentral/com.networknt/json-schema-validator/1.0.76, Apache-2.0, approved, CQ22638 maven/mavencentral/com.nimbusds/content-type/2.2, Apache-2.0, approved, clearlydefined maven/mavencentral/com.nimbusds/lang-tag/1.7, Apache-2.0, approved, clearlydefined +maven/mavencentral/com.nimbusds/nimbus-jose-jwt/9.28, Apache-2.0, approved, clearlydefined maven/mavencentral/com.nimbusds/nimbus-jose-jwt/9.30.2, Apache-2.0, approved, clearlydefined maven/mavencentral/com.nimbusds/nimbus-jose-jwt/9.37.3, Apache-2.0, approved, #11701 maven/mavencentral/com.nimbusds/oauth2-oidc-sdk/10.7.1, Apache-2.0, approved, clearlydefined maven/mavencentral/com.puppycrawl.tools/checkstyle/10.14.2, LGPL-2.1-or-later AND (Apache-2.0 AND LGPL-2.1-or-later) AND Apache-2.0, approved, #13562 +maven/mavencentral/com.samskivert/jmustache/1.15, BSD-2-Clause, approved, clearlydefined maven/mavencentral/com.squareup.okhttp3/mockwebserver/5.0.0-alpha.12, Apache-2.0, approved, clearlydefined maven/mavencentral/com.squareup.okhttp3/mockwebserver3/5.0.0-alpha.12, Apache-2.0, approved, clearlydefined maven/mavencentral/com.squareup.okhttp3/okhttp-dnsoverhttps/4.12.0, Apache-2.0, approved, #11159 @@ -98,10 +132,17 @@ maven/mavencentral/com.squareup.okio/okio-jvm/3.7.0, Apache-2.0, approved, clear maven/mavencentral/com.squareup.okio/okio/3.6.0, Apache-2.0, approved, #11155 maven/mavencentral/com.squareup.okio/okio/3.7.0, Apache-2.0, approved, clearlydefined maven/mavencentral/com.sun.activation/jakarta.activation/2.0.0, EPL-2.0 OR BSD-3-Clause OR GPL-2.0-only with Classpath-exception-2.0, approved, ee4j.jaf +maven/mavencentral/com.sun.activation/jakarta.activation/2.0.1, EPL-2.0 OR BSD-3-Clause OR GPL-2.0-only with Classpath-exception-2.0, approved, ee4j.jaf +maven/mavencentral/com.sun.mail/mailapi/1.6.2, CDDL-1.1 OR GPL-2.0-only WITH Classpath-exception-2.0, approved, clearlydefined +maven/mavencentral/com.sun.xml.bind/jaxb-core/4.0.1, BSD-3-Clause, approved, ee4j.jaxb-impl +maven/mavencentral/com.sun.xml.bind/jaxb-impl/4.0.1, BSD-3-Clause, approved, ee4j.jaxb-impl +maven/mavencentral/commons-beanutils/commons-beanutils/1.8.3, Apache-2.0, approved, CQ4968 maven/mavencentral/commons-beanutils/commons-beanutils/1.9.4, Apache-2.0, approved, CQ12654 maven/mavencentral/commons-codec/commons-codec/1.11, Apache-2.0 AND BSD-3-Clause, approved, CQ15971 maven/mavencentral/commons-codec/commons-codec/1.15, Apache-2.0 AND BSD-3-Clause AND LicenseRef-Public-Domain, approved, CQ22641 maven/mavencentral/commons-collections/commons-collections/3.2.2, Apache-2.0, approved, CQ10385 +maven/mavencentral/commons-io/commons-io/2.11.0, Apache-2.0, approved, CQ23745 +maven/mavencentral/commons-logging/commons-logging/1.1.1, Apache-2.0, approved, CQ1907 maven/mavencentral/commons-logging/commons-logging/1.2, Apache-2.0, approved, CQ10162 maven/mavencentral/dev.failsafe/failsafe-okhttp/3.3.2, Apache-2.0, approved, #9178 maven/mavencentral/dev.failsafe/failsafe/3.3.1, Apache-2.0, approved, #9268 @@ -115,31 +156,42 @@ maven/mavencentral/io.micrometer/micrometer-observation/1.12.4, Apache-2.0, appr maven/mavencentral/io.netty/netty-buffer/4.1.100.Final, Apache-2.0, approved, CQ21842 maven/mavencentral/io.netty/netty-buffer/4.1.101.Final, Apache-2.0, approved, CQ21842 maven/mavencentral/io.netty/netty-buffer/4.1.107.Final, Apache-2.0, approved, CQ21842 +maven/mavencentral/io.netty/netty-buffer/4.1.86.Final, Apache-2.0, approved, CQ21842 maven/mavencentral/io.netty/netty-codec-dns/4.1.101.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 maven/mavencentral/io.netty/netty-codec-http/4.1.100.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 maven/mavencentral/io.netty/netty-codec-http/4.1.101.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 maven/mavencentral/io.netty/netty-codec-http/4.1.107.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 +maven/mavencentral/io.netty/netty-codec-http/4.1.86.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 maven/mavencentral/io.netty/netty-codec-http2/4.1.100.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 maven/mavencentral/io.netty/netty-codec-http2/4.1.101.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 maven/mavencentral/io.netty/netty-codec-http2/4.1.107.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 +maven/mavencentral/io.netty/netty-codec-http2/4.1.86.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 maven/mavencentral/io.netty/netty-codec-socks/4.1.101.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 +maven/mavencentral/io.netty/netty-codec-socks/4.1.86.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 maven/mavencentral/io.netty/netty-codec/4.1.100.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 maven/mavencentral/io.netty/netty-codec/4.1.101.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 maven/mavencentral/io.netty/netty-codec/4.1.107.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 +maven/mavencentral/io.netty/netty-codec/4.1.86.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 maven/mavencentral/io.netty/netty-common/4.1.100.Final, Apache-2.0 AND MIT AND CC0-1.0, approved, CQ21843 maven/mavencentral/io.netty/netty-common/4.1.101.Final, Apache-2.0 AND MIT AND CC0-1.0, approved, CQ21843 maven/mavencentral/io.netty/netty-common/4.1.107.Final, Apache-2.0 AND MIT AND CC0-1.0, approved, CQ21843 +maven/mavencentral/io.netty/netty-common/4.1.86.Final, Apache-2.0 AND MIT AND CC0-1.0, approved, CQ21843 maven/mavencentral/io.netty/netty-handler-proxy/4.1.101.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 +maven/mavencentral/io.netty/netty-handler-proxy/4.1.86.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 maven/mavencentral/io.netty/netty-handler/4.1.100.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 maven/mavencentral/io.netty/netty-handler/4.1.101.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 maven/mavencentral/io.netty/netty-handler/4.1.107.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 +maven/mavencentral/io.netty/netty-handler/4.1.86.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 maven/mavencentral/io.netty/netty-resolver-dns-classes-macos/4.1.101.Final, Apache-2.0, approved, #6367 maven/mavencentral/io.netty/netty-resolver-dns-native-macos/4.1.101.Final, Apache-2.0, approved, #7004 maven/mavencentral/io.netty/netty-resolver-dns/4.1.101.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 maven/mavencentral/io.netty/netty-resolver/4.1.100.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 maven/mavencentral/io.netty/netty-resolver/4.1.101.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 maven/mavencentral/io.netty/netty-resolver/4.1.107.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 +maven/mavencentral/io.netty/netty-resolver/4.1.86.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 +maven/mavencentral/io.netty/netty-tcnative-boringssl-static/2.0.56.Final, Apache-2.0 OR LicenseRef-Public-Domain OR BSD-2-Clause OR MIT, approved, CQ15280 maven/mavencentral/io.netty/netty-tcnative-boringssl-static/2.0.62.Final, Apache-2.0 OR LicenseRef-Public-Domain OR BSD-2-Clause OR MIT, approved, CQ15280 +maven/mavencentral/io.netty/netty-tcnative-classes/2.0.56.Final, Apache-2.0, approved, clearlydefined maven/mavencentral/io.netty/netty-tcnative-classes/2.0.62.Final, Apache-2.0, approved, clearlydefined maven/mavencentral/io.netty/netty-transport-classes-epoll/4.1.100.Final, Apache-2.0, approved, #6366 maven/mavencentral/io.netty/netty-transport-classes-epoll/4.1.101.Final, Apache-2.0, approved, #6366 @@ -149,15 +201,23 @@ maven/mavencentral/io.netty/netty-transport-native-epoll/4.1.101.Final, Apache-2 maven/mavencentral/io.netty/netty-transport-native-kqueue/4.1.101.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 maven/mavencentral/io.netty/netty-transport-native-unix-common/4.1.101.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 maven/mavencentral/io.netty/netty-transport-native-unix-common/4.1.107.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 +maven/mavencentral/io.netty/netty-transport-native-unix-common/4.1.86.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 maven/mavencentral/io.netty/netty-transport/4.1.100.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 maven/mavencentral/io.netty/netty-transport/4.1.101.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 maven/mavencentral/io.netty/netty-transport/4.1.107.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 +maven/mavencentral/io.netty/netty-transport/4.1.86.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 maven/mavencentral/io.opentelemetry.instrumentation/opentelemetry-instrumentation-annotations/1.32.0, Apache-2.0, approved, #11684 maven/mavencentral/io.opentelemetry/opentelemetry-api/1.32.0, Apache-2.0, approved, #11682 maven/mavencentral/io.opentelemetry/opentelemetry-context/1.32.0, Apache-2.0, approved, #11683 maven/mavencentral/io.projectreactor.netty/reactor-netty-core/1.0.40, Apache-2.0, approved, #9687 maven/mavencentral/io.projectreactor.netty/reactor-netty-http/1.0.40, Apache-2.0, approved, #11661 maven/mavencentral/io.projectreactor/reactor-core/3.4.34, Apache-2.0, approved, #7517 +maven/mavencentral/io.prometheus/simpleclient/0.16.0, Apache-2.0, approved, clearlydefined +maven/mavencentral/io.prometheus/simpleclient_common/0.16.0, Apache-2.0, approved, clearlydefined +maven/mavencentral/io.prometheus/simpleclient_httpserver/0.16.0, Apache-2.0, approved, clearlydefined +maven/mavencentral/io.prometheus/simpleclient_tracer_common/0.16.0, Apache-2.0, approved, clearlydefined +maven/mavencentral/io.prometheus/simpleclient_tracer_otel/0.16.0, Apache-2.0, approved, clearlydefined +maven/mavencentral/io.prometheus/simpleclient_tracer_otel_agent/0.16.0, Apache-2.0, approved, clearlydefined maven/mavencentral/io.rest-assured/json-path/5.4.0, Apache-2.0, approved, #12042 maven/mavencentral/io.rest-assured/rest-assured-common/5.4.0, Apache-2.0, approved, #12039 maven/mavencentral/io.rest-assured/rest-assured/5.4.0, Apache-2.0, approved, #12040 @@ -167,9 +227,11 @@ maven/mavencentral/io.swagger.core.v3/swagger-annotations-jakarta/2.2.15, Apache maven/mavencentral/io.swagger.core.v3/swagger-annotations-jakarta/2.2.18, Apache-2.0, approved, #5947 maven/mavencentral/io.swagger.core.v3/swagger-annotations-jakarta/2.2.20, Apache-2.0, approved, #5947 maven/mavencentral/io.swagger.core.v3/swagger-annotations/2.2.15, Apache-2.0, approved, #11362 +maven/mavencentral/io.swagger.core.v3/swagger-annotations/2.2.8, Apache-2.0, approved, #11362 maven/mavencentral/io.swagger.core.v3/swagger-core-jakarta/2.2.15, Apache-2.0, approved, #5929 maven/mavencentral/io.swagger.core.v3/swagger-core-jakarta/2.2.18, Apache-2.0, approved, #5929 maven/mavencentral/io.swagger.core.v3/swagger-core/2.2.15, Apache-2.0, approved, #9265 +maven/mavencentral/io.swagger.core.v3/swagger-core/2.2.8, Apache-2.0, approved, #9265 maven/mavencentral/io.swagger.core.v3/swagger-integration-jakarta/2.2.15, Apache-2.0, approved, #11475 maven/mavencentral/io.swagger.core.v3/swagger-integration-jakarta/2.2.18, Apache-2.0, approved, #11475 maven/mavencentral/io.swagger.core.v3/swagger-integration/2.2.15, Apache-2.0, approved, #10352 @@ -179,6 +241,16 @@ maven/mavencentral/io.swagger.core.v3/swagger-jaxrs2/2.2.15, Apache-2.0, approve maven/mavencentral/io.swagger.core.v3/swagger-models-jakarta/2.2.15, Apache-2.0, approved, #5919 maven/mavencentral/io.swagger.core.v3/swagger-models-jakarta/2.2.18, Apache-2.0, approved, #5919 maven/mavencentral/io.swagger.core.v3/swagger-models/2.2.15, Apache-2.0, approved, #10353 +maven/mavencentral/io.swagger.core.v3/swagger-models/2.2.8, Apache-2.0, approved, #10353 +maven/mavencentral/io.swagger.parser.v3/swagger-parser-core/2.1.10, Apache-2.0, approved, #11478 +maven/mavencentral/io.swagger.parser.v3/swagger-parser-v2-converter/2.1.10, Apache-2.0, approved, #9330 +maven/mavencentral/io.swagger.parser.v3/swagger-parser-v3/2.1.10, Apache-2.0, approved, #9323 +maven/mavencentral/io.swagger.parser.v3/swagger-parser/2.1.10, Apache-2.0, approved, #11316 +maven/mavencentral/io.swagger/swagger-annotations/1.6.9, Apache-2.0, approved, #3792 +maven/mavencentral/io.swagger/swagger-compat-spec-parser/1.0.64, Apache-2.0, approved, #11479 +maven/mavencentral/io.swagger/swagger-core/1.6.9, Apache-2.0, approved, #4358 +maven/mavencentral/io.swagger/swagger-models/1.6.9, Apache-2.0, approved, #11476 +maven/mavencentral/io.swagger/swagger-parser/1.0.64, Apache-2.0, approved, #4359 maven/mavencentral/jakarta.activation/jakarta.activation-api/1.2.1, EPL-2.0 OR BSD-3-Clause OR GPL-2.0-only with Classpath-exception-2.0, approved, ee4j.jaf maven/mavencentral/jakarta.activation/jakarta.activation-api/2.1.0, EPL-2.0 OR BSD-3-Clause OR GPL-2.0-only with Classpath-exception-2.0, approved, ee4j.jaf maven/mavencentral/jakarta.annotation/jakarta.annotation-api/2.1.1, EPL-2.0 OR GPL-2.0-only with Classpath-exception-2.0, approved, ee4j.ca @@ -190,9 +262,12 @@ maven/mavencentral/jakarta.validation/jakarta.validation-api/3.0.2, Apache-2.0, maven/mavencentral/jakarta.ws.rs/jakarta.ws.rs-api/3.1.0, EPL-2.0 OR GPL-2.0-only with Classpath-exception-2.0, approved, ee4j.rest maven/mavencentral/jakarta.xml.bind/jakarta.xml.bind-api/2.3.2, BSD-3-Clause, approved, ee4j.jaxb maven/mavencentral/jakarta.xml.bind/jakarta.xml.bind-api/3.0.0, BSD-3-Clause, approved, ee4j.jaxb +maven/mavencentral/jakarta.xml.bind/jakarta.xml.bind-api/3.0.1, BSD-3-Clause, approved, ee4j.jaxb maven/mavencentral/jakarta.xml.bind/jakarta.xml.bind-api/4.0.0, BSD-3-Clause, approved, ee4j.jaxb maven/mavencentral/javax.servlet/javax.servlet-api/3.1.0, (CDDL-1.1 OR GPL-2.0-only WITH Classpath-exception-2.0) AND Apache-2.0, approved, CQ7248 +maven/mavencentral/javax.servlet/javax.servlet-api/4.0.1, (CDDL-1.1 OR GPL-2.0-only WITH Classpath-exception-2.0) AND Apache-2.0, approved, CQ16125 maven/mavencentral/javax.ws.rs/javax.ws.rs-api/2.1, (CDDL-1.1 OR GPL-2.0 WITH Classpath-exception-2.0) AND Apache-2.0, approved, CQ18121 +maven/mavencentral/joda-time/joda-time/2.10.5, Apache-2.0, approved, clearlydefined maven/mavencentral/junit/junit/4.13.2, EPL-2.0, approved, CQ23636 maven/mavencentral/net.bytebuddy/byte-buddy-agent/1.14.1, Apache-2.0, approved, #7164 maven/mavencentral/net.bytebuddy/byte-buddy-agent/1.14.12, Apache-2.0, approved, #7164 @@ -202,18 +277,24 @@ maven/mavencentral/net.bytebuddy/byte-buddy/1.14.12, Apache-2.0 AND BSD-3-Clause maven/mavencentral/net.java.dev.jna/jna-platform/5.13.0, Apache-2.0 OR LGPL-2.1-or-later, approved, #6707 maven/mavencentral/net.java.dev.jna/jna-platform/5.6.0, Apache-2.0 OR LGPL-2.1-or-later, approved, CQ22390 maven/mavencentral/net.java.dev.jna/jna/5.13.0, Apache-2.0 AND LGPL-2.1-or-later, approved, #6709 +maven/mavencentral/net.javacrumbs.json-unit/json-unit-core/2.36.0, Apache-2.0, approved, clearlydefined maven/mavencentral/net.minidev/accessors-smart/2.5.0, Apache-2.0, approved, clearlydefined maven/mavencentral/net.minidev/json-smart/2.4.10, Apache-2.0, approved, #3288 +maven/mavencentral/net.minidev/json-smart/2.4.7, Apache-2.0, approved, #3288 maven/mavencentral/net.minidev/json-smart/2.5.0, Apache-2.0, approved, clearlydefined +maven/mavencentral/net.sf.jopt-simple/jopt-simple/5.0.4, MIT, approved, CQ13174 maven/mavencentral/net.sf.saxon/Saxon-HE/12.4, MPL-2.0 AND (MPL-2.0 AND Apache-2.0) AND (MPL-2.0 AND LicenseRef-X11-style) AND MPL-1.0 AND W3C, approved, #12716 maven/mavencentral/org.antlr/antlr4-runtime/4.13.1, BSD-3-Clause, approved, #10767 maven/mavencentral/org.apache.commons/commons-compress/1.24.0, Apache-2.0 AND BSD-3-Clause AND bzip2-1.0.6 AND LicenseRef-Public-Domain, approved, #10368 +maven/mavencentral/org.apache.commons/commons-digester3/3.2, Apache-2.0, approved, clearlydefined +maven/mavencentral/org.apache.commons/commons-lang3/3.10, Apache-2.0, approved, clearlydefined maven/mavencentral/org.apache.commons/commons-lang3/3.11, Apache-2.0, approved, CQ22642 maven/mavencentral/org.apache.commons/commons-lang3/3.12.0, Apache-2.0, approved, clearlydefined maven/mavencentral/org.apache.commons/commons-lang3/3.13.0, Apache-2.0, approved, #9820 maven/mavencentral/org.apache.commons/commons-lang3/3.7, Apache-2.0, approved, clearlydefined maven/mavencentral/org.apache.commons/commons-lang3/3.8.1, Apache-2.0, approved, #815 maven/mavencentral/org.apache.commons/commons-pool2/2.12.0, Apache-2.0 AND LicenseRef-Public-Domain, approved, #10843 +maven/mavencentral/org.apache.commons/commons-text/1.10.0, Apache-2.0, approved, clearlydefined maven/mavencentral/org.apache.commons/commons-text/1.3, Apache-2.0, approved, clearlydefined maven/mavencentral/org.apache.groovy/groovy-bom/4.0.16, Apache-2.0, approved, #9266 maven/mavencentral/org.apache.groovy/groovy-json/4.0.16, Apache-2.0, approved, #7411 @@ -233,14 +314,20 @@ maven/mavencentral/org.apache.maven.doxia/doxia-sink-api/1.12.0, Apache-2.0, app maven/mavencentral/org.apache.sshd/sshd-common/2.12.1, Apache-2.0 AND ISC, approved, #12842 maven/mavencentral/org.apache.sshd/sshd-core/2.12.1, Apache-2.0, approved, #12841 maven/mavencentral/org.apache.sshd/sshd-sftp/2.12.1, Apache-2.0, approved, #12840 +maven/mavencentral/org.apache.velocity.tools/velocity-tools-generic/3.1, Apache-2.0, approved, #9331 +maven/mavencentral/org.apache.velocity/velocity-engine-core/2.3, Apache-2.0, approved, #2478 +maven/mavencentral/org.apache.velocity/velocity-engine-scripting/2.3, Apache-2.0, approved, clearlydefined maven/mavencentral/org.apache.xbean/xbean-reflect/3.7, Apache-2.0, approved, clearlydefined maven/mavencentral/org.apiguardian/apiguardian-api/1.1.2, Apache-2.0, approved, clearlydefined maven/mavencentral/org.assertj/assertj-core/3.25.3, Apache-2.0, approved, #12585 maven/mavencentral/org.awaitility/awaitility/4.2.0, Apache-2.0, approved, clearlydefined +maven/mavencentral/org.bouncycastle/bcpkix-jdk18on/1.72, MIT, approved, #3789 maven/mavencentral/org.bouncycastle/bcpkix-jdk18on/1.77, MIT, approved, #11593 +maven/mavencentral/org.bouncycastle/bcprov-jdk18on/1.72, MIT AND CC0-1.0, approved, #3538 maven/mavencentral/org.bouncycastle/bcprov-jdk18on/1.77, MIT AND CC0-1.0, approved, #11595 maven/mavencentral/org.bouncycastle/bcutil-jdk18on/1.77, MIT, approved, #11596 maven/mavencentral/org.ccil.cowan.tagsoup/tagsoup/1.2.1, Apache-2.0, approved, clearlydefined +maven/mavencentral/org.checkerframework/checker-qual/3.12.0, MIT, approved, clearlydefined maven/mavencentral/org.checkerframework/checker-qual/3.42.0, MIT, approved, clearlydefined maven/mavencentral/org.codehaus.plexus/plexus-classworlds/2.6.0, Apache-2.0 AND Plexus, approved, CQ22821 maven/mavencentral/org.codehaus.plexus/plexus-component-annotations/2.1.0, Apache-2.0, approved, #809 @@ -248,6 +335,7 @@ maven/mavencentral/org.codehaus.plexus/plexus-container-default/2.1.0, Apache-2. maven/mavencentral/org.codehaus.plexus/plexus-utils/3.1.1, , approved, CQ16492 maven/mavencentral/org.codehaus.plexus/plexus-utils/3.3.0, , approved, CQ21066 maven/mavencentral/org.codehaus.woodstox/stax2-api/4.2.1, BSD-2-Clause, approved, #2670 +maven/mavencentral/org.eclipse.angus/angus-activation/1.0.0, EPL-2.0 OR GPL-2.0-only with Classpath-exception-2.0, approved, ee4j.angus maven/mavencentral/org.eclipse.edc/api-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/api-observability/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/asset-api/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc @@ -322,6 +410,8 @@ maven/mavencentral/org.eclipse.edc/dsp-transfer-process-transform/0.5.2-SNAPSHOT maven/mavencentral/org.eclipse.edc/dsp-transfer-process/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/dsp-version-api/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/dsp/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/edr-store-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/edr-store-receiver/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/edr-store-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/http-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/http/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc @@ -443,6 +533,7 @@ maven/mavencentral/org.glassfish.jersey.media/jersey-media-json-jackson/3.1.5, E maven/mavencentral/org.glassfish.jersey.media/jersey-media-multipart/3.1.5, EPL-2.0 OR GPL-2.0-only with Classpath-exception-2.0, approved, ee4j.jersey maven/mavencentral/org.glassfish/jakarta.json/2.0.1, EPL-2.0 OR GPL-2.0-only with Classpath-exception-2.0, approved, ee4j.jsonp maven/mavencentral/org.hamcrest/hamcrest-core/1.3, BSD-2-Clause, approved, CQ11429 +maven/mavencentral/org.hamcrest/hamcrest-core/2.2, BSD-3-Clause, approved, clearlydefined maven/mavencentral/org.hamcrest/hamcrest/2.1, BSD-3-Clause, approved, clearlydefined maven/mavencentral/org.hamcrest/hamcrest/2.2, BSD-3-Clause, approved, clearlydefined maven/mavencentral/org.hdrhistogram/HdrHistogram/2.1.12, BSD-2-Clause OR LicenseRef-Public-Domain, approved, CQ13192 @@ -479,8 +570,12 @@ maven/mavencentral/org.junit/junit-bom/5.10.2, EPL-2.0, approved, #9844 maven/mavencentral/org.junit/junit-bom/5.9.2, EPL-2.0, approved, #4711 maven/mavencentral/org.jvnet.mimepull/mimepull/1.9.15, CDDL-1.1 OR GPL-2.0-only WITH Classpath-exception-2.0, approved, CQ21484 maven/mavencentral/org.latencyutils/LatencyUtils/2.0.3, BSD-2-Clause, approved, CQ17408 +maven/mavencentral/org.mock-server/mockserver-client-java/5.15.0, Apache-2.0 AND LGPL-3.0-only, approved, #9324 +maven/mavencentral/org.mock-server/mockserver-core/5.15.0, Apache-2.0, approved, clearlydefined +maven/mavencentral/org.mock-server/mockserver-netty/5.15.0, Apache-2.0, approved, #9276 maven/mavencentral/org.mockito/mockito-core/5.11.0, MIT AND (Apache-2.0 AND MIT) AND Apache-2.0, approved, #13505 maven/mavencentral/org.mockito/mockito-core/5.2.0, MIT AND (Apache-2.0 AND MIT) AND Apache-2.0, approved, #7401 +maven/mavencentral/org.mozilla/rhino/1.7.7.2, MPL-2.0 AND BSD-3-Clause AND ISC, approved, CQ16320 maven/mavencentral/org.objenesis/objenesis/3.3, Apache-2.0, approved, clearlydefined maven/mavencentral/org.opentest4j/opentest4j/1.3.0, Apache-2.0, approved, #9713 maven/mavencentral/org.ow2.asm/asm-commons/9.5, BSD-3-Clause, approved, #7553 @@ -495,13 +590,16 @@ maven/mavencentral/org.reactivestreams/reactive-streams/1.0.4, CC0-1.0, approved maven/mavencentral/org.reflections/reflections/0.10.2, Apache-2.0 AND WTFPL, approved, clearlydefined maven/mavencentral/org.rnorth.duct-tape/duct-tape/1.0.8, MIT, approved, clearlydefined maven/mavencentral/org.slf4j/jcl-over-slf4j/1.7.32, Apache-2.0, approved, CQ12843 +maven/mavencentral/org.slf4j/slf4j-api/1.7.22, MIT, approved, CQ11943 maven/mavencentral/org.slf4j/slf4j-api/1.7.25, MIT, approved, CQ13368 maven/mavencentral/org.slf4j/slf4j-api/1.7.30, MIT, approved, CQ13368 maven/mavencentral/org.slf4j/slf4j-api/1.7.32, MIT, approved, CQ13368 +maven/mavencentral/org.slf4j/slf4j-api/1.7.33, MIT, approved, CQ13368 maven/mavencentral/org.slf4j/slf4j-api/1.7.35, MIT, approved, CQ13368 maven/mavencentral/org.slf4j/slf4j-api/1.7.36, MIT, approved, CQ13368 maven/mavencentral/org.slf4j/slf4j-api/1.7.7, MIT, approved, CQ9827 maven/mavencentral/org.slf4j/slf4j-api/2.0.12, MIT, approved, #5915 +maven/mavencentral/org.slf4j/slf4j-api/2.0.6, MIT, approved, #5915 maven/mavencentral/org.slf4j/slf4j-api/2.0.9, MIT, approved, #5915 maven/mavencentral/org.testcontainers/database-commons/1.19.6, Apache-2.0, approved, #10345 maven/mavencentral/org.testcontainers/database-commons/1.19.7, Apache-2.0, approved, #10345 @@ -515,6 +613,9 @@ maven/mavencentral/org.testcontainers/testcontainers/1.19.6, Apache-2.0 AND MIT, maven/mavencentral/org.testcontainers/testcontainers/1.19.7, Apache-2.0 AND MIT, approved, #10347 maven/mavencentral/org.testcontainers/vault/1.19.6, MIT, approved, #10852 maven/mavencentral/org.xmlresolver/xmlresolver/5.2.2, Apache-2.0, approved, clearlydefined +maven/mavencentral/org.xmlunit/xmlunit-core/2.9.1, Apache-2.0, approved, #6272 +maven/mavencentral/org.xmlunit/xmlunit-placeholders/2.9.1, Apache-2.0, approved, clearlydefined +maven/mavencentral/org.yaml/snakeyaml/1.33, Apache-2.0, approved, clearlydefined maven/mavencentral/org.yaml/snakeyaml/2.0, Apache-2.0 AND (Apache-2.0 OR BSD-3-Clause OR EPL-1.0 OR GPL-2.0-or-later OR LGPL-2.1-or-later), approved, #7275 maven/mavencentral/org.yaml/snakeyaml/2.2, Apache-2.0 AND (Apache-2.0 OR BSD-3-Clause OR EPL-1.0 OR GPL-2.0-or-later OR LGPL-2.1-or-later), approved, #10232 maven/mavencentral/software.amazon.awssdk/annotations/2.24.10, Apache-2.0, approved, #13251 diff --git a/edc-extensions/edr/edr-api-v2/build.gradle.kts b/edc-extensions/edr/edr-api-v2/build.gradle.kts new file mode 100644 index 000000000..1e9cf0074 --- /dev/null +++ b/edc-extensions/edr/edr-api-v2/build.gradle.kts @@ -0,0 +1,42 @@ +/******************************************************************************** + * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +plugins { + `java-library` + `maven-publish` + id("io.swagger.core.v3.swagger-gradle-plugin") +} + +dependencies { + implementation(project(":spi:callback-spi")) + implementation(project(":spi:edr-spi")) + implementation(project(":spi:core-spi")) + implementation(project(":spi:tokenrefresh-spi")) + + implementation(libs.edc.api.management) + implementation(libs.edc.core.validator) + implementation(libs.edc.spi.edrstore) + implementation(libs.jakarta.rsApi) + + testImplementation(testFixtures(libs.edc.core.jersey)) + testImplementation(libs.restAssured) + testImplementation(libs.edc.junit) + testImplementation(libs.edc.ext.jersey.providers) + testImplementation(libs.edc.core.transform) +} diff --git a/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/EdrCacheApi.java b/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/EdrCacheApi.java new file mode 100644 index 000000000..994f7709e --- /dev/null +++ b/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/EdrCacheApi.java @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.eclipse.tractusx.edc.api.edr.v2; + +import io.swagger.v3.oas.annotations.OpenAPIDefinition; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.ArraySchema; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.parameters.RequestBody; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.json.JsonArray; +import jakarta.json.JsonObject; +import org.eclipse.edc.api.model.ApiCoreSchema; +import org.eclipse.edc.connector.api.management.configuration.ManagementApiSchema; +import org.eclipse.edc.web.spi.ApiErrorDetail; +import org.eclipse.tractusx.edc.api.edr.v2.schema.EdrSchema; +import org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntry; + +import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.ID; +import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.TYPE; + +@OpenAPIDefinition +@Tag(name = "Control Plane EDR Api") +public interface EdrCacheApi { + + @Operation(description = "Initiates an EDR negotiation by handling a contract negotiation first and then a transfer process for a given offer and with the given counter part. Please note that successfully invoking this endpoint " + + "only means that the negotiation was initiated.", + responses = { + @ApiResponse(responseCode = "200", description = "The negotiation was successfully initiated.", + content = @Content(schema = @Schema(implementation = ApiCoreSchema.IdResponseSchema.class))), + @ApiResponse(responseCode = "400", description = "Request body was malformed", + content = @Content(array = @ArraySchema(schema = @Schema(implementation = ApiErrorDetail.class)))), + }) + JsonObject initiateEdrNegotiation(@Schema(implementation = EdrSchema.NegotiateEdrRequestSchema.class) JsonObject dto); + + @Operation(description = "Request all Edr entries according to a particular query", + requestBody = @RequestBody( + content = @Content(schema = @Schema(implementation = ApiCoreSchema.QuerySpecSchema.class)) + ), + responses = { + @ApiResponse(responseCode = "200", description = "The edr entries matching the query", + content = @Content(array = @ArraySchema(schema = @Schema(implementation = EndpointDataReferenceEntrySchema.class)))), + @ApiResponse(responseCode = "400", description = "Request body was malformed", + content = @Content(array = @ArraySchema(schema = @Schema(implementation = ApiCoreSchema.ApiErrorDetailSchema.class)))) + }) + JsonArray requestEdrEntries(JsonObject querySpecJson); + + @Operation(description = "Gets the EDR data address with the given transfer process ID", + parameters = { @Parameter(name = "transferProcessId", description = "The ID of the transferprocess for which the EDR should be fetched", required = true), + @Parameter(name = "auto_refresh", description = "Whether the access token that is stored on the EDR should be checked for expiry, and renewed if necessary. Default is true") + }, + responses = { + @ApiResponse(responseCode = "200", description = "The data address", + content = @Content(schema = @Schema(implementation = ManagementApiSchema.DataAddressSchema.class))), + @ApiResponse(responseCode = "400", description = "Request was malformed, e.g. id was null", + content = @Content(array = @ArraySchema(schema = @Schema(implementation = ApiCoreSchema.ApiErrorDetailSchema.class)))), + @ApiResponse(responseCode = "404", description = "An EDR data address with the given transfer process ID does not exist", + content = @Content(array = @ArraySchema(schema = @Schema(implementation = ApiCoreSchema.ApiErrorDetailSchema.class)))) + } + ) + JsonObject getEdrEntryDataAddress(String transferProcessId, boolean autoRefresh); + + @Operation(description = "Removes an EDR entry given the transfer process ID", + responses = { + @ApiResponse(responseCode = "204", description = "EDR entry was deleted successfully"), + @ApiResponse(responseCode = "400", description = "Request was malformed, e.g. id was null", + content = @Content(array = @ArraySchema(schema = @Schema(implementation = ApiCoreSchema.ApiErrorDetailSchema.class)))), + @ApiResponse(responseCode = "404", description = "An EDR entry with the given ID does not exist", + content = @Content(array = @ArraySchema(schema = @Schema(implementation = ApiCoreSchema.ApiErrorDetailSchema.class)))) + }) + void removeEdrEntry(String transferProcessId); + + @Operation(description = "Refreshes and returns the EDR data address with the given transfer process ID", + parameters = { @Parameter(name = "transferProcessId", description = "The ID of the transferprocess for which the EDR should be fetched", required = true), + }, + responses = { + @ApiResponse(responseCode = "200", description = "The data address", + content = @Content(schema = @Schema(implementation = ManagementApiSchema.DataAddressSchema.class))), + @ApiResponse(responseCode = "400", description = "Request was malformed, e.g. id was null", + content = @Content(array = @ArraySchema(schema = @Schema(implementation = ApiCoreSchema.ApiErrorDetailSchema.class)))), + @ApiResponse(responseCode = "404", description = "An EDR data address with the given transfer process ID does not exist", + content = @Content(array = @ArraySchema(schema = @Schema(implementation = ApiCoreSchema.ApiErrorDetailSchema.class)))) + } + ) + JsonObject refreshEdr(String transferProcessId); + + + @ArraySchema() + @Schema(name = "EndpointDataReferenceEntry", example = EndpointDataReferenceEntrySchema.EDR_ENTRY_OUTPUT_EXAMPLE) + record EndpointDataReferenceEntrySchema( + @Schema(name = ID) + String id, + @Schema(name = TYPE, example = EndpointDataReferenceEntry.EDR_ENTRY_TYPE) + String type + ) { + public static final String EDR_ENTRY_OUTPUT_EXAMPLE = """ + { + "@context": { "@vocab": "https://w3id.org/edc/v0.0.1/ns/" }, + "@id": "transfer-process-id", + "transferProcessId": "transfer-process-id", + "agreementId": "agreement-id", + "contractNegotiationId": "contract-negotiation-id", + "assetId": "asset-id", + "providerId": "provider-id", + "createdAt": 1688465655 + } + """; + } +} diff --git a/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/EdrCacheApiController.java b/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/EdrCacheApiController.java new file mode 100644 index 000000000..68eaf8ca1 --- /dev/null +++ b/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/EdrCacheApiController.java @@ -0,0 +1,194 @@ +/* + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.eclipse.tractusx.edc.api.edr.v2; + +import jakarta.json.JsonArray; +import jakarta.json.JsonObject; +import jakarta.ws.rs.Consumes; +import jakarta.ws.rs.DELETE; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.POST; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.PathParam; +import jakarta.ws.rs.Produces; +import jakarta.ws.rs.QueryParam; +import jakarta.ws.rs.core.MediaType; +import org.eclipse.edc.api.model.IdResponse; +import org.eclipse.edc.edr.spi.store.EndpointDataReferenceStore; +import org.eclipse.edc.spi.EdcException; +import org.eclipse.edc.spi.monitor.Monitor; +import org.eclipse.edc.spi.query.QuerySpec; +import org.eclipse.edc.spi.result.Result; +import org.eclipse.edc.spi.result.ServiceResult; +import org.eclipse.edc.spi.types.domain.DataAddress; +import org.eclipse.edc.transform.spi.TypeTransformerRegistry; +import org.eclipse.edc.validator.spi.JsonObjectValidatorRegistry; +import org.eclipse.edc.web.spi.exception.InvalidRequestException; +import org.eclipse.edc.web.spi.exception.ValidationFailureException; +import org.eclipse.tractusx.edc.api.edr.v2.dto.NegotiateEdrRequestDto; +import org.eclipse.tractusx.edc.edr.spi.service.EdrService; +import org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntry; +import org.eclipse.tractusx.edc.edr.spi.types.NegotiateEdrRequest; +import org.eclipse.tractusx.edc.spi.tokenrefresh.common.TokenRefreshHandler; + +import java.time.Instant; + +import static jakarta.json.stream.JsonCollectors.toJsonArray; +import static org.eclipse.edc.spi.query.QuerySpec.EDC_QUERY_SPEC_TYPE; +import static org.eclipse.edc.spi.result.ServiceResult.success; +import static org.eclipse.edc.web.spi.exception.ServiceResultHandler.exceptionMapper; +import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.TX_AUTH_NS; + +@Consumes({ MediaType.APPLICATION_JSON }) +@Produces({ MediaType.APPLICATION_JSON }) +@Path("/v2/edrs") +public class EdrCacheApiController implements EdrCacheApi { + private final EndpointDataReferenceStore edrStore; + private final TypeTransformerRegistry transformerRegistry; + private final JsonObjectValidatorRegistry validator; + private final Monitor monitor; + private final EdrService edrService; + private final TokenRefreshHandler tokenRefreshHandler; + + public EdrCacheApiController(EndpointDataReferenceStore edrStore, + TypeTransformerRegistry transformerRegistry, + JsonObjectValidatorRegistry validator, + Monitor monitor, + EdrService edrService, + TokenRefreshHandler tokenRefreshHandler) { + this.edrStore = edrStore; + this.transformerRegistry = transformerRegistry; + this.validator = validator; + this.monitor = monitor; + this.edrService = edrService; + this.tokenRefreshHandler = tokenRefreshHandler; + } + + @POST + @Override + public JsonObject initiateEdrNegotiation(JsonObject requestObject) { + validator.validate(NegotiateEdrRequestDto.EDR_REQUEST_DTO_TYPE, requestObject).orElseThrow(ValidationFailureException::new); + + var edrNegotiationRequest = transformerRegistry.transform(requestObject, NegotiateEdrRequestDto.class) + .compose(dto -> transformerRegistry.transform(dto, NegotiateEdrRequest.class)) + .orElseThrow(InvalidRequestException::new); + + var contractNegotiation = edrService.initiateEdrNegotiation(edrNegotiationRequest).orElseThrow(exceptionMapper(NegotiateEdrRequest.class)); + + var idResponse = IdResponse.Builder.newInstance() + .id(contractNegotiation.getId()) + .createdAt(contractNegotiation.getCreatedAt()) + .build(); + + return transformerRegistry.transform(idResponse, JsonObject.class) + .orElseThrow(f -> new EdcException("Error creating response body: " + f.getFailureDetail())); + } + + @POST + @Path("/request") + @Override + public JsonArray requestEdrEntries(JsonObject querySpecJson) { + QuerySpec querySpec; + if (querySpecJson == null) { + querySpec = QuerySpec.Builder.newInstance().build(); + } else { + validator.validate(EDC_QUERY_SPEC_TYPE, querySpecJson).orElseThrow(ValidationFailureException::new); + + querySpec = transformerRegistry.transform(querySpecJson, QuerySpec.class) + .orElseThrow(InvalidRequestException::new); + } + + return edrStore.query(querySpec) + .flatMap(ServiceResult::from) + .orElseThrow(exceptionMapper(QuerySpec.class, null)).stream() + .map(it -> transformerRegistry.transform(it, JsonObject.class)) + .peek(r -> r.onFailure(f -> monitor.warning(f.getFailureDetail()))) + .filter(Result::succeeded) + .map(Result::getContent) + .collect(toJsonArray()); + } + + @GET + @Path("{transferProcessId}/dataaddress") + @Override + public JsonObject getEdrEntryDataAddress(@PathParam("transferProcessId") String transferProcessId, @QueryParam("auto_refresh") boolean autoRefresh) { + + var dataAddress = edrStore.resolveByTransferProcess(transferProcessId) + .flatMap(ServiceResult::from) + .compose(edr -> autoRefresh ? refreshAndUpdateToken(edr, transferProcessId) : success(edr)) + .orElseThrow(exceptionMapper(EndpointDataReferenceEntry.class, transferProcessId)); + + return transformerRegistry.transform(dataAddress, JsonObject.class) + .orElseThrow(f -> new EdcException(f.getFailureDetail())); + + + } + + @DELETE + @Path("{transferProcessId}") + @Override + public void removeEdrEntry(@PathParam("transferProcessId") String transferProcessId) { + edrStore.delete(transferProcessId) + .flatMap(ServiceResult::from) + .orElseThrow(exceptionMapper(EndpointDataReferenceEntry.class, transferProcessId)); + } + + @POST + @Path("{transferProcessId}/refresh") + @Override + public JsonObject refreshEdr(@PathParam("transferProcessId") String transferProcessId) { + var updatedEdr = tokenRefreshHandler.refreshToken(transferProcessId) + .orElseThrow(exceptionMapper(DataAddress.class, transferProcessId)); + + return transformerRegistry.transform(updatedEdr, JsonObject.class) + .orElseThrow(f -> new EdcException(f.getFailureDetail())); + } + + // todo: move this method into a service once the "old" EDR api,service,etc. is removed + private ServiceResult refreshAndUpdateToken(DataAddress edr, String id) { + + var edrEntry = edrStore.findById(id); + if (edrEntry == null) { + return ServiceResult.notFound("An EndpointDataReferenceEntry with ID '%s' does not exist".formatted(id)); + } + + if (isExpired(edr, edrEntry)) { + monitor.debug("Token expired, need to refresh."); + return tokenRefreshHandler.refreshToken(id, edr); + } + return ServiceResult.success(edr); + } + + // todo: move this method into a service once the "old" EDR api,service,etc. is removed + private boolean isExpired(DataAddress edr, org.eclipse.edc.edr.spi.types.EndpointDataReferenceEntry metadata) { + var expiresInString = edr.getStringProperty(TX_AUTH_NS + "expiresIn"); + if (expiresInString == null) { + return false; + } + + var expiresIn = Long.parseLong(expiresInString); + // createdAt is in millis, expires-in is in seconds + var expiresAt = metadata.getCreatedAt() / 1000L + expiresIn; + var expiresAtInstant = Instant.ofEpochSecond(expiresAt); + + return expiresAtInstant.isBefore(Instant.now()); + } + +} diff --git a/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/EdrCacheApiExtension.java b/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/EdrCacheApiExtension.java new file mode 100644 index 000000000..6f5a428c6 --- /dev/null +++ b/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/EdrCacheApiExtension.java @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.eclipse.tractusx.edc.api.edr.v2; + +import jakarta.json.Json; +import org.eclipse.edc.connector.api.management.configuration.ManagementApiConfiguration; +import org.eclipse.edc.edr.spi.store.EndpointDataReferenceStore; +import org.eclipse.edc.jsonld.spi.JsonLd; +import org.eclipse.edc.runtime.metamodel.annotation.Inject; +import org.eclipse.edc.spi.monitor.Monitor; +import org.eclipse.edc.spi.system.ServiceExtension; +import org.eclipse.edc.spi.system.ServiceExtensionContext; +import org.eclipse.edc.transform.spi.TypeTransformerRegistry; +import org.eclipse.edc.validator.spi.JsonObjectValidatorRegistry; +import org.eclipse.edc.web.spi.WebService; +import org.eclipse.tractusx.edc.api.edr.v2.dto.NegotiateEdrRequestDto; +import org.eclipse.tractusx.edc.api.edr.v2.transform.EndpointDataReferenceToDataAddressTransformer; +import org.eclipse.tractusx.edc.api.edr.v2.transform.JsonObjectFromEndpointDataReferenceEntryTransformer; +import org.eclipse.tractusx.edc.api.edr.v2.transform.JsonObjectToNegotiateEdrRequestDtoTransformer; +import org.eclipse.tractusx.edc.api.edr.v2.transform.NegotiateEdrRequestDtoToNegotiatedEdrRequestTransformer; +import org.eclipse.tractusx.edc.api.edr.v2.validation.NegotiateEdrRequestDtoValidator; +import org.eclipse.tractusx.edc.edr.spi.service.EdrService; +import org.eclipse.tractusx.edc.spi.tokenrefresh.common.TokenRefreshHandler; + +import java.util.Map; + +import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.TX_NAMESPACE; +import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.TX_PREFIX; + +public class EdrCacheApiExtension implements ServiceExtension { + + @Inject + private WebService webService; + @Inject + private ManagementApiConfiguration apiConfig; + + @Inject + private EdrService edrService; + + @Inject + private TypeTransformerRegistry transformerRegistry; + + @Inject + private JsonLd jsonLdService; + + @Inject + private JsonObjectValidatorRegistry validatorRegistry; + + @Inject + private Monitor monitor; + @Inject + private EndpointDataReferenceStore edrStore; + @Inject + private TokenRefreshHandler tokenRefreshHandler; + + @Override + public void initialize(ServiceExtensionContext context) { + jsonLdService.registerNamespace(TX_PREFIX, TX_NAMESPACE); + var mgmtApiTransformerRegistry = transformerRegistry.forContext("management-api"); + mgmtApiTransformerRegistry.register(new NegotiateEdrRequestDtoToNegotiatedEdrRequestTransformer()); + mgmtApiTransformerRegistry.register(new JsonObjectToNegotiateEdrRequestDtoTransformer()); + mgmtApiTransformerRegistry.register(new JsonObjectFromEndpointDataReferenceEntryTransformer(Json.createBuilderFactory(Map.of()))); + mgmtApiTransformerRegistry.register(new EndpointDataReferenceToDataAddressTransformer()); + validatorRegistry.register(NegotiateEdrRequestDto.EDR_REQUEST_DTO_TYPE, NegotiateEdrRequestDtoValidator.instance()); + webService.registerResource(apiConfig.getContextAlias(), new EdrCacheApiController(edrStore, mgmtApiTransformerRegistry, validatorRegistry, monitor, edrService, tokenRefreshHandler)); + } +} diff --git a/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/dto/NegotiateEdrRequestDto.java b/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/dto/NegotiateEdrRequestDto.java new file mode 100644 index 000000000..de05beb78 --- /dev/null +++ b/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/dto/NegotiateEdrRequestDto.java @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.eclipse.tractusx.edc.api.edr.v2.dto; + +import org.eclipse.edc.connector.api.management.contractnegotiation.model.ContractOfferDescription; +import org.eclipse.edc.spi.types.domain.callback.CallbackAddress; + +import java.util.ArrayList; +import java.util.List; + +import static org.eclipse.edc.spi.CoreConstants.EDC_NAMESPACE; +import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.TX_NAMESPACE; + +public class NegotiateEdrRequestDto { + + public static final String EDR_REQUEST_SIMPLE_DTO_TYPE = "NegotiateEdrRequestDto"; + public static final String EDR_REQUEST_DTO_TYPE = TX_NAMESPACE + EDR_REQUEST_SIMPLE_DTO_TYPE; + public static final String EDR_REQUEST_DTO_COUNTERPARTY_ADDRESS = EDC_NAMESPACE + "counterPartyAddress"; + public static final String EDR_REQUEST_DTO_PROTOCOL = EDC_NAMESPACE + "protocol"; + public static final String EDR_REQUEST_DTO_COUNTERPARTY_ID = EDC_NAMESPACE + "counterPartyId"; + public static final String EDR_REQUEST_DTO_PROVIDER_ID = EDC_NAMESPACE + "providerId"; + public static final String EDR_REQUEST_DTO_OFFER = EDC_NAMESPACE + "offer"; + public static final String EDR_REQUEST_DTO_CALLBACK_ADDRESSES = EDC_NAMESPACE + "callbackAddresses"; + + private String counterPartyAddress; + private String protocol = "ids-multipart"; + private String counterPartyId; + + private String providerId; + + private ContractOfferDescription offer; + private List callbackAddresses = new ArrayList<>(); + + private NegotiateEdrRequestDto() { + + } + + public String getCounterPartyAddress() { + return counterPartyAddress; + } + + public String getProtocol() { + return protocol; + } + + public String getCounterPartyId() { + return counterPartyId; + } + + public String getProviderId() { + return providerId; + } + + public List getCallbackAddresses() { + return callbackAddresses; + } + + public ContractOfferDescription getOffer() { + return offer; + } + + public static final class Builder { + private final NegotiateEdrRequestDto dto; + + private Builder() { + dto = new NegotiateEdrRequestDto(); + } + + public static Builder newInstance() { + return new Builder(); + } + + public Builder connectorAddress(String connectorAddress) { + dto.counterPartyAddress = connectorAddress; + return this; + } + + public Builder protocol(String protocol) { + dto.protocol = protocol; + return this; + } + + public Builder counterPartyId(String connectorId) { + dto.counterPartyId = connectorId; + return this; + } + + public Builder offer(ContractOfferDescription offer) { + dto.offer = offer; + return this; + } + + public Builder providerId(String providerId) { + dto.providerId = providerId; + return this; + } + + public Builder callbackAddresses(List callbackAddresses) { + dto.callbackAddresses = callbackAddresses; + return this; + } + + public NegotiateEdrRequestDto build() { + return dto; + } + } +} diff --git a/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/schema/EdrSchema.java b/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/schema/EdrSchema.java new file mode 100644 index 000000000..ae337815b --- /dev/null +++ b/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/schema/EdrSchema.java @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.eclipse.tractusx.edc.api.edr.v2.schema; + +import io.swagger.v3.oas.annotations.media.Schema; +import org.eclipse.edc.connector.api.management.configuration.ManagementApiSchema; +import org.eclipse.edc.connector.api.management.contractnegotiation.ContractNegotiationApi; +import org.eclipse.tractusx.edc.api.edr.v2.dto.NegotiateEdrRequestDto; +import org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntry; + +import java.util.List; + +import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.TYPE; +import static org.eclipse.tractusx.edc.api.edr.v2.schema.EdrSchema.EndpointDataReferenceEntrySchema.ENDPOINT_DATA_REFERENCE_ENTRY_EXAMPLE; +import static org.eclipse.tractusx.edc.api.edr.v2.schema.EdrSchema.NegotiateEdrRequestSchema.NEGOTIATE_EDR_REQUEST_EXAMPLE; + +public class EdrSchema { + + @Schema(name = "NegotiateEdrRequest", example = NEGOTIATE_EDR_REQUEST_EXAMPLE) + public record NegotiateEdrRequestSchema( + @Schema(name = TYPE, example = NegotiateEdrRequestDto.EDR_REQUEST_DTO_TYPE) + String type, + String protocol, + String connectorAddress, + @Deprecated(since = "0.1.3") + @Schema(deprecated = true, description = "please use providerId instead") + String connectorId, + String providerId, + ContractNegotiationApi.ContractOfferDescriptionSchema offer, + List callbackAddresses) { + + public static final String NEGOTIATE_EDR_REQUEST_EXAMPLE = """ + { + "@context": { "edc": "https://w3id.org/edc/v0.0.1/ns/" }, + "@type": "NegotiateEdrRequestDto", + "counterPartyAddress": "http://provider-address", + "protocol": "dataspace-protocol-http", + "providerId": "provider-id", + "offer": { + "offerId": "offer-id", + "assetId": "asset-id", + "policy": { + "@context": "http://www.w3.org/ns/odrl.jsonld", + "@type": "Set", + "@id": "offer-id", + "permission": [{ + "target": "asset-id", + "action": "display" + }] + } + }, + "callbackAddresses": [{ + "transactional": false, + "uri": "http://callback/url", + "events": ["contract.negotiation", "transfer.process"] + }] + } + """; + } + + @Schema(name = "EndpointDataReferenceEntry", example = ENDPOINT_DATA_REFERENCE_ENTRY_EXAMPLE) + public record EndpointDataReferenceEntrySchema( + @Schema(name = TYPE, example = EndpointDataReferenceEntry.SIMPLE_TYPE) + String type, + String agreementId, + String assetId, + String providerId, + String edrState, + Long expirationDate + ) { + public static final String ENDPOINT_DATA_REFERENCE_ENTRY_EXAMPLE = """ + { + "@type": "tx:EndpointDataReferenceEntry", + "agreementId": "MQ==:MQ==:ZTY3MzQ4YWEtNTdmZC00YzA0LTg2ZmQtMGMxNzk0MWM3OTkw", + "transferProcessId": "78a66945-d638-4c0a-be71-b35a0318a410", + "assetId": "1", + "providerId": "BPNL00DATAP00001", + "tx:edrState": "NEGOTIATED", + "tx:expirationDate": 1690811364000, + "@context": { + "dct": "https://purl.org/dc/terms/", + "tx": "https://w3id.org/tractusx/v0.0.1/ns/", + "edc": "https://w3id.org/edc/v0.0.1/ns/", + "dcat": "https://www.w3.org/ns/dcat/", + "odrl": "http://www.w3.org/ns/odrl/2/", + "dspace": "https://w3id.org/dspace/v0.8/" + } + } + """; + } + +} diff --git a/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/transform/EndpointDataReferenceToDataAddressTransformer.java b/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/transform/EndpointDataReferenceToDataAddressTransformer.java new file mode 100644 index 000000000..bfe73fe19 --- /dev/null +++ b/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/transform/EndpointDataReferenceToDataAddressTransformer.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.eclipse.tractusx.edc.api.edr.v2.transform; + +import org.eclipse.edc.spi.types.domain.DataAddress; +import org.eclipse.edc.spi.types.domain.edr.EndpointDataReference; +import org.eclipse.edc.transform.spi.TransformerContext; +import org.eclipse.edc.transform.spi.TypeTransformer; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import static org.eclipse.edc.spi.types.domain.edr.EndpointDataReference.AUTH_CODE; +import static org.eclipse.edc.spi.types.domain.edr.EndpointDataReference.AUTH_KEY; +import static org.eclipse.edc.spi.types.domain.edr.EndpointDataReference.EDR_SIMPLE_TYPE; +import static org.eclipse.edc.spi.types.domain.edr.EndpointDataReference.ENDPOINT; +import static org.eclipse.edc.spi.types.domain.edr.EndpointDataReference.ID; + +public class EndpointDataReferenceToDataAddressTransformer implements TypeTransformer { + @Override + public Class getInputType() { + return EndpointDataReference.class; + } + + @Override + public Class getOutputType() { + return DataAddress.class; + } + + @Override + public @Nullable DataAddress transform(@NotNull EndpointDataReference edr, @NotNull TransformerContext context) { + return DataAddress.Builder.newInstance() + .type(EDR_SIMPLE_TYPE) + .property(ID, edr.getId()) + .property(AUTH_CODE, edr.getAuthCode()) + .property(AUTH_KEY, edr.getAuthKey()) + .property(ENDPOINT, edr.getEndpoint()) + .properties(edr.getProperties()) + .build(); + } +} diff --git a/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/transform/JsonObjectFromEndpointDataReferenceEntryTransformer.java b/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/transform/JsonObjectFromEndpointDataReferenceEntryTransformer.java new file mode 100644 index 000000000..64ef0a33b --- /dev/null +++ b/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/transform/JsonObjectFromEndpointDataReferenceEntryTransformer.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.eclipse.tractusx.edc.api.edr.v2.transform; + +import jakarta.json.JsonBuilderFactory; +import jakarta.json.JsonObject; +import org.eclipse.edc.edr.spi.types.EndpointDataReferenceEntry; +import org.eclipse.edc.jsonld.spi.transformer.AbstractJsonLdTransformer; +import org.eclipse.edc.transform.spi.TransformerContext; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import static org.eclipse.edc.edr.spi.types.EndpointDataReferenceEntry.EDR_ENTRY_AGREEMENT_ID; +import static org.eclipse.edc.edr.spi.types.EndpointDataReferenceEntry.EDR_ENTRY_ASSET_ID; +import static org.eclipse.edc.edr.spi.types.EndpointDataReferenceEntry.EDR_ENTRY_CONTRACT_NEGOTIATION_ID; +import static org.eclipse.edc.edr.spi.types.EndpointDataReferenceEntry.EDR_ENTRY_CREATED_AT; +import static org.eclipse.edc.edr.spi.types.EndpointDataReferenceEntry.EDR_ENTRY_PROVIDER_ID; +import static org.eclipse.edc.edr.spi.types.EndpointDataReferenceEntry.EDR_ENTRY_TRANSFER_PROCESS_ID; +import static org.eclipse.edc.edr.spi.types.EndpointDataReferenceEntry.EDR_ENTRY_TYPE; +import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.ID; +import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.TYPE; + +public class JsonObjectFromEndpointDataReferenceEntryTransformer extends AbstractJsonLdTransformer { + private final JsonBuilderFactory jsonFactory; + + + public JsonObjectFromEndpointDataReferenceEntryTransformer(JsonBuilderFactory jsonFactory) { + super(EndpointDataReferenceEntry.class, JsonObject.class); + this.jsonFactory = jsonFactory; + } + + @Override + public @Nullable JsonObject transform(@NotNull EndpointDataReferenceEntry entry, @NotNull TransformerContext context) { + return jsonFactory.createObjectBuilder() + .add(ID, entry.getId()) + .add(TYPE, EDR_ENTRY_TYPE) + .add(EDR_ENTRY_PROVIDER_ID, entry.getProviderId()) + .add(EDR_ENTRY_ASSET_ID, entry.getAssetId()) + .add(EDR_ENTRY_AGREEMENT_ID, entry.getAgreementId()) + .add(EDR_ENTRY_TRANSFER_PROCESS_ID, entry.getTransferProcessId()) + .add(EDR_ENTRY_CREATED_AT, entry.getCreatedAt()) + .add(EDR_ENTRY_CONTRACT_NEGOTIATION_ID, entry.getContractNegotiationId()) + .build(); + } +} diff --git a/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/transform/JsonObjectToNegotiateEdrRequestDtoTransformer.java b/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/transform/JsonObjectToNegotiateEdrRequestDtoTransformer.java new file mode 100644 index 000000000..721743466 --- /dev/null +++ b/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/transform/JsonObjectToNegotiateEdrRequestDtoTransformer.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.eclipse.tractusx.edc.api.edr.v2.transform; + +import jakarta.json.JsonObject; +import jakarta.json.JsonValue; +import org.eclipse.edc.connector.api.management.contractnegotiation.model.ContractOfferDescription; +import org.eclipse.edc.jsonld.spi.transformer.AbstractJsonLdTransformer; +import org.eclipse.edc.spi.types.domain.callback.CallbackAddress; +import org.eclipse.edc.transform.spi.TransformerContext; +import org.eclipse.tractusx.edc.api.edr.v2.dto.NegotiateEdrRequestDto; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; + + +public class JsonObjectToNegotiateEdrRequestDtoTransformer extends AbstractJsonLdTransformer { + + public JsonObjectToNegotiateEdrRequestDtoTransformer() { + super(JsonObject.class, NegotiateEdrRequestDto.class); + } + + @Override + public @Nullable NegotiateEdrRequestDto transform(@NotNull JsonObject jsonObject, @NotNull TransformerContext context) { + var builder = NegotiateEdrRequestDto.Builder.newInstance(); + + visitProperties(jsonObject, (k, v) -> setProperties(k, v, builder, context)); + return builder.build(); + } + + private void setProperties(String key, JsonValue value, NegotiateEdrRequestDto.Builder builder, TransformerContext context) { + switch (key) { + case NegotiateEdrRequestDto.EDR_REQUEST_DTO_COUNTERPARTY_ADDRESS: + transformString(value, builder::connectorAddress, context); + break; + case NegotiateEdrRequestDto.EDR_REQUEST_DTO_PROTOCOL: + transformString(value, builder::protocol, context); + break; + case NegotiateEdrRequestDto.EDR_REQUEST_DTO_COUNTERPARTY_ID: + transformString(value, builder::counterPartyId, context); + break; + case NegotiateEdrRequestDto.EDR_REQUEST_DTO_PROVIDER_ID: + transformString(value, builder::providerId, context); + break; + case NegotiateEdrRequestDto.EDR_REQUEST_DTO_CALLBACK_ADDRESSES: + var addresses = new ArrayList(); + transformArrayOrObject(value, CallbackAddress.class, addresses::add, context); + builder.callbackAddresses(addresses); + break; + case NegotiateEdrRequestDto.EDR_REQUEST_DTO_OFFER: + transformArrayOrObject(value, ContractOfferDescription.class, builder::offer, context); + break; + default: + context.problem() + .unexpectedType() + .type(NegotiateEdrRequestDto.EDR_REQUEST_DTO_TYPE) + .property(key) + .actual(key) + .expected(NegotiateEdrRequestDto.EDR_REQUEST_DTO_COUNTERPARTY_ADDRESS) + .expected(NegotiateEdrRequestDto.EDR_REQUEST_DTO_PROTOCOL) + .expected(NegotiateEdrRequestDto.EDR_REQUEST_DTO_COUNTERPARTY_ID) + .expected(NegotiateEdrRequestDto.EDR_REQUEST_DTO_PROVIDER_ID) + .expected(NegotiateEdrRequestDto.EDR_REQUEST_DTO_CALLBACK_ADDRESSES) + .expected(NegotiateEdrRequestDto.EDR_REQUEST_DTO_OFFER) + .report(); + break; + } + } +} diff --git a/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/transform/NegotiateEdrRequestDtoToNegotiatedEdrRequestTransformer.java b/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/transform/NegotiateEdrRequestDtoToNegotiatedEdrRequestTransformer.java new file mode 100644 index 000000000..24bd3e533 --- /dev/null +++ b/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/transform/NegotiateEdrRequestDtoToNegotiatedEdrRequestTransformer.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.eclipse.tractusx.edc.api.edr.v2.transform; + +import org.eclipse.edc.spi.types.domain.offer.ContractOffer; +import org.eclipse.edc.transform.spi.TransformerContext; +import org.eclipse.edc.transform.spi.TypeTransformer; +import org.eclipse.tractusx.edc.api.edr.v2.dto.NegotiateEdrRequestDto; +import org.eclipse.tractusx.edc.edr.spi.types.NegotiateEdrRequest; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class NegotiateEdrRequestDtoToNegotiatedEdrRequestTransformer implements TypeTransformer { + + @Override + public Class getInputType() { + return NegotiateEdrRequestDto.class; + } + + @Override + public Class getOutputType() { + return NegotiateEdrRequest.class; + } + + @Override + public @Nullable NegotiateEdrRequest transform(@NotNull NegotiateEdrRequestDto object, @NotNull TransformerContext context) { + var contractOffer = ContractOffer.Builder.newInstance() + .id(object.getOffer().getOfferId()) + .assetId(object.getOffer().getAssetId()) + .policy(object.getOffer().getPolicy()) + .build(); + + return NegotiateEdrRequest.Builder.newInstance() + .connectorId(object.getCounterPartyId()) + .connectorAddress(object.getCounterPartyAddress()) + .protocol(object.getProtocol()) + .offer(contractOffer) + .callbackAddresses(object.getCallbackAddresses()) + .build(); + } + + private String getId(String value, String defaultValue) { + return value != null ? value : defaultValue; + } + +} diff --git a/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/validation/NegotiateEdrRequestDtoValidator.java b/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/validation/NegotiateEdrRequestDtoValidator.java new file mode 100644 index 000000000..667a37afd --- /dev/null +++ b/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/validation/NegotiateEdrRequestDtoValidator.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.eclipse.tractusx.edc.api.edr.v2.validation; + +import jakarta.json.JsonObject; +import org.eclipse.edc.validator.jsonobject.JsonObjectValidator; +import org.eclipse.edc.validator.jsonobject.validators.MandatoryObject; +import org.eclipse.edc.validator.jsonobject.validators.MandatoryValue; +import org.eclipse.edc.validator.spi.Validator; +import org.eclipse.tractusx.edc.api.edr.v2.dto.NegotiateEdrRequestDto; + +import static org.eclipse.edc.connector.api.management.contractnegotiation.model.ContractOfferDescription.ASSET_ID; +import static org.eclipse.edc.connector.api.management.contractnegotiation.model.ContractOfferDescription.OFFER_ID; +import static org.eclipse.edc.connector.api.management.contractnegotiation.model.ContractOfferDescription.POLICY; + + +public class NegotiateEdrRequestDtoValidator { + + private NegotiateEdrRequestDtoValidator() { + } + + public static Validator instance() { + return JsonObjectValidator.newValidator() + .verify(NegotiateEdrRequestDto.EDR_REQUEST_DTO_COUNTERPARTY_ADDRESS, MandatoryValue::new) + .verify(NegotiateEdrRequestDto.EDR_REQUEST_DTO_PROTOCOL, MandatoryValue::new) + .verify(NegotiateEdrRequestDto.EDR_REQUEST_DTO_OFFER, MandatoryObject::new) + .verifyObject(NegotiateEdrRequestDto.EDR_REQUEST_DTO_OFFER, v -> v + .verify(OFFER_ID, MandatoryValue::new) + .verify(ASSET_ID, MandatoryValue::new) + .verify(POLICY, MandatoryObject::new) + ) + .build(); + } +} diff --git a/edc-extensions/edr/edr-api-v2/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension b/edc-extensions/edr/edr-api-v2/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension new file mode 100644 index 000000000..d415057f4 --- /dev/null +++ b/edc-extensions/edr/edr-api-v2/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension @@ -0,0 +1,20 @@ +################################################################################# +# Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License, Version 2.0 which is available at +# https://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. +# +# SPDX-License-Identifier: Apache-2.0 +################################################################################# + +org.eclipse.tractusx.edc.api.edr.v2.EdrCacheApiExtension diff --git a/edc-extensions/edr/edr-api-v2/src/test/java/org/eclipse/tractusx/edc/api/edr/v2/EdrCacheApiControllerTest.java b/edc-extensions/edr/edr-api-v2/src/test/java/org/eclipse/tractusx/edc/api/edr/v2/EdrCacheApiControllerTest.java new file mode 100644 index 000000000..bc62d0511 --- /dev/null +++ b/edc-extensions/edr/edr-api-v2/src/test/java/org/eclipse/tractusx/edc/api/edr/v2/EdrCacheApiControllerTest.java @@ -0,0 +1,226 @@ +/* + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.eclipse.tractusx.edc.api.edr.v2; + +import io.restassured.specification.RequestSpecification; +import jakarta.json.JsonObject; +import jakarta.json.JsonObjectBuilder; +import org.eclipse.edc.edr.spi.store.EndpointDataReferenceStore; +import org.eclipse.edc.edr.spi.types.EndpointDataReferenceEntry; +import org.eclipse.edc.junit.annotations.ApiTest; +import org.eclipse.edc.spi.query.QuerySpec; +import org.eclipse.edc.spi.result.Result; +import org.eclipse.edc.spi.result.StoreResult; +import org.eclipse.edc.spi.types.domain.DataAddress; +import org.eclipse.edc.transform.spi.TypeTransformerRegistry; +import org.eclipse.edc.validator.spi.JsonObjectValidatorRegistry; +import org.eclipse.edc.validator.spi.ValidationResult; +import org.eclipse.edc.web.jersey.testfixtures.RestControllerTestBase; +import org.eclipse.tractusx.edc.edr.spi.service.EdrService; +import org.eclipse.tractusx.edc.spi.tokenrefresh.common.TokenRefreshHandler; +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static io.restassured.RestAssured.given; +import static io.restassured.http.ContentType.JSON; +import static jakarta.json.Json.createObjectBuilder; +import static org.eclipse.edc.edr.spi.types.EndpointDataReferenceEntry.EDR_ENTRY_AGREEMENT_ID; +import static org.eclipse.edc.edr.spi.types.EndpointDataReferenceEntry.EDR_ENTRY_ASSET_ID; +import static org.eclipse.edc.edr.spi.types.EndpointDataReferenceEntry.EDR_ENTRY_CONTRACT_NEGOTIATION_ID; +import static org.eclipse.edc.edr.spi.types.EndpointDataReferenceEntry.EDR_ENTRY_PROVIDER_ID; +import static org.eclipse.edc.edr.spi.types.EndpointDataReferenceEntry.EDR_ENTRY_TRANSFER_PROCESS_ID; +import static org.eclipse.edc.edr.spi.types.EndpointDataReferenceEntry.EDR_ENTRY_TYPE; +import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.CONTEXT; +import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.ID; +import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.TYPE; +import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.VOCAB; +import static org.eclipse.edc.spi.CoreConstants.EDC_NAMESPACE; +import static org.eclipse.edc.spi.CoreConstants.EDC_PREFIX; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.is; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.argThat; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.isA; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.when; + +@ApiTest +public class EdrCacheApiControllerTest extends RestControllerTestBase { + + private static final String TEST_TRANSFER_PROCESS_ID = "test-transfer-process-id"; + private static final String TEST_TRANSFER_NEGOTIATION_ID = "test-cn-id"; + private static final String TEST_AGREEMENT_ID = "test-agreement-id"; + private static final String TEST_PROVIDER_ID = "test-provider-id"; + private static final String TEST_ASSET_ID = "test-asset-id"; + + private final TypeTransformerRegistry transformerRegistry = mock(); + private final JsonObjectValidatorRegistry validator = mock(); + private final EndpointDataReferenceStore edrStore = mock(); + private final EdrService edrService = mock(); + private final TokenRefreshHandler tokenRefreshHandler = mock(); + + @Test + void requestEdrEntries() { + when(edrStore.query(any())) + .thenReturn(StoreResult.success(List.of(createEdrEntry()))); + when(transformerRegistry.transform(isA(EndpointDataReferenceEntry.class), eq(JsonObject.class))) + .thenReturn(Result.success(createEdrEntryJson().build())); + when(transformerRegistry.transform(isA(JsonObject.class), eq(QuerySpec.class))) + .thenReturn(Result.success(QuerySpec.Builder.newInstance().offset(10).build())); + when(validator.validate(any(), any())).thenReturn(ValidationResult.success()); + + baseRequest() + .contentType(JSON) + .body("{}") + .post("/v2/edrs/request") + .then() + .log().ifError() + .statusCode(200) + .contentType(JSON) + .body("size()", is(1)); + + verify(edrStore).query(argThat(s -> s.getOffset() == 10)); + verify(transformerRegistry).transform(isA(EndpointDataReferenceEntry.class), eq(JsonObject.class)); + verify(transformerRegistry).transform(isA(JsonObject.class), eq(QuerySpec.class)); + } + + @Test + void getEdrEntryDataAddress() { + + var dataAddressType = "type"; + var dataAddress = DataAddress.Builder.newInstance().type(dataAddressType).build(); + when(edrStore.resolveByTransferProcess("transferProcessId")) + .thenReturn(StoreResult.success(dataAddress)); + + when(transformerRegistry.transform(isA(DataAddress.class), eq(JsonObject.class))) + .thenReturn(Result.success(createDataAddress(dataAddressType).build())); + + baseRequest() + .contentType(JSON) + .get("/v2/edrs/transferProcessId/dataaddress") + .then() + .log().ifError() + .statusCode(200) + .contentType(JSON) + .body("'%s'".formatted(DataAddress.EDC_DATA_ADDRESS_TYPE_PROPERTY), equalTo(dataAddressType)); + + verify(edrStore).resolveByTransferProcess("transferProcessId"); + verify(transformerRegistry).transform(isA(DataAddress.class), eq(JsonObject.class)); + verifyNoMoreInteractions(transformerRegistry); + } + + @Test + void getEdrEntryDataAddress_whenNotFound() { + + when(edrStore.resolveByTransferProcess("transferProcessId")) + .thenReturn(StoreResult.notFound("notFound")); + + + baseRequest() + .contentType(JSON) + .get("/v2/edrs/transferProcessId/dataaddress") + .then() + .log().ifError() + .statusCode(404) + .contentType(JSON); + + verify(edrStore).resolveByTransferProcess("transferProcessId"); + verifyNoMoreInteractions(transformerRegistry); + } + + @Test + void removeEdrEntry() { + when(edrStore.delete("transferProcessId")) + .thenReturn(StoreResult.success(createEdrEntry())); + + baseRequest() + .contentType(JSON) + .delete("/v2/edrs/transferProcessId") + .then() + .statusCode(204); + verify(edrStore).delete("transferProcessId"); + } + + @Test + void removeEdrEntry_whenNotFound() { + when(edrStore.delete("transferProcessId")) + .thenReturn(StoreResult.notFound("not found")); + + baseRequest() + .contentType(JSON) + .delete("/v2/edrs/transferProcessId") + .then() + .statusCode(404); + + verify(edrStore).delete("transferProcessId"); + } + + @Override + protected Object controller() { + return new EdrCacheApiController(edrStore, transformerRegistry, validator, mock(), edrService, tokenRefreshHandler); + } + + private JsonObjectBuilder createEdrEntryJson() { + return createObjectBuilder() + .add(CONTEXT, createContextBuilder().build()) + .add(TYPE, EDR_ENTRY_TYPE) + .add(ID, TEST_TRANSFER_PROCESS_ID) + .add(EDR_ENTRY_TRANSFER_PROCESS_ID, TEST_TRANSFER_PROCESS_ID) + .add(EDR_ENTRY_PROVIDER_ID, TEST_PROVIDER_ID) + .add(EDR_ENTRY_CONTRACT_NEGOTIATION_ID, TEST_TRANSFER_NEGOTIATION_ID) + .add(EDR_ENTRY_ASSET_ID, TEST_ASSET_ID) + .add(EDR_ENTRY_AGREEMENT_ID, TEST_AGREEMENT_ID); + } + + private JsonObjectBuilder createDataAddress(String type) { + return createObjectBuilder() + .add(CONTEXT, createContextBuilder().build()) + .add(TYPE, DataAddress.EDC_DATA_ADDRESS_TYPE) + .add(DataAddress.EDC_DATA_ADDRESS_TYPE_PROPERTY, type); + } + + private EndpointDataReferenceEntry createEdrEntry() { + return EndpointDataReferenceEntry.Builder.newInstance() + .agreementId(TEST_AGREEMENT_ID) + .assetId(TEST_ASSET_ID) + .providerId(TEST_PROVIDER_ID) + .transferProcessId(TEST_TRANSFER_PROCESS_ID) + .contractNegotiationId(TEST_TRANSFER_NEGOTIATION_ID) + .build(); + + } + + private JsonObjectBuilder createContextBuilder() { + return createObjectBuilder() + .add(VOCAB, EDC_NAMESPACE) + .add(EDC_PREFIX, EDC_NAMESPACE); + } + + + private RequestSpecification baseRequest() { + return given() + .baseUri("http://localhost:" + port) + .when(); + } +} diff --git a/edc-extensions/edr/edr-api-v2/src/test/java/org/eclipse/tractusx/edc/api/edr/v2/EdrCacheApiExtensionTest.java b/edc-extensions/edr/edr-api-v2/src/test/java/org/eclipse/tractusx/edc/api/edr/v2/EdrCacheApiExtensionTest.java new file mode 100644 index 000000000..1fd484120 --- /dev/null +++ b/edc-extensions/edr/edr-api-v2/src/test/java/org/eclipse/tractusx/edc/api/edr/v2/EdrCacheApiExtensionTest.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.eclipse.tractusx.edc.api.edr.v2; + +import org.eclipse.edc.junit.extensions.DependencyInjectionExtension; +import org.eclipse.edc.spi.system.ServiceExtensionContext; +import org.eclipse.edc.transform.spi.TypeTransformerRegistry; +import org.eclipse.edc.validator.spi.JsonObjectValidatorRegistry; +import org.eclipse.edc.web.spi.WebService; +import org.eclipse.tractusx.edc.api.edr.v2.transform.JsonObjectFromEndpointDataReferenceEntryTransformer; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.isA; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@ExtendWith(DependencyInjectionExtension.class) +class EdrCacheApiExtensionTest { + + private final JsonObjectValidatorRegistry validatorRegistry = mock(); + private final WebService webService = mock(); + + private final TypeTransformerRegistry transformerRegistry = mock(); + + + @BeforeEach + void setUp(ServiceExtensionContext context) { + context.registerService(JsonObjectValidatorRegistry.class, validatorRegistry); + context.registerService(WebService.class, webService); + context.registerService(TypeTransformerRegistry.class, transformerRegistry); + when(transformerRegistry.forContext("management-api")).thenReturn(transformerRegistry); + } + + @Test + void initialize_shouldRegisterControllers(EdrCacheApiExtension extension, ServiceExtensionContext context) { + extension.initialize(context); + + verify(webService).registerResource(any(), isA(EdrCacheApiController.class)); + } + + @Test + void initialize_shouldRegisterTransformers(EdrCacheApiExtension extension, ServiceExtensionContext context) { + extension.initialize(context); + verify(transformerRegistry).register(isA(JsonObjectFromEndpointDataReferenceEntryTransformer.class)); + } +} diff --git a/edc-extensions/edr/edr-api-v2/src/test/java/org/eclipse/tractusx/edc/api/edr/v2/EdrCacheApiTest.java b/edc-extensions/edr/edr-api-v2/src/test/java/org/eclipse/tractusx/edc/api/edr/v2/EdrCacheApiTest.java new file mode 100644 index 000000000..62b1b3c1e --- /dev/null +++ b/edc-extensions/edr/edr-api-v2/src/test/java/org/eclipse/tractusx/edc/api/edr/v2/EdrCacheApiTest.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.eclipse.tractusx.edc.api.edr.v2; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import jakarta.json.JsonObject; +import org.eclipse.edc.jsonld.TitaniumJsonLd; +import org.eclipse.edc.jsonld.spi.JsonLd; +import org.eclipse.edc.jsonld.util.JacksonJsonLd; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.eclipse.edc.edr.spi.types.EndpointDataReferenceEntry.EDR_ENTRY_AGREEMENT_ID; +import static org.eclipse.edc.edr.spi.types.EndpointDataReferenceEntry.EDR_ENTRY_ASSET_ID; +import static org.eclipse.edc.edr.spi.types.EndpointDataReferenceEntry.EDR_ENTRY_CONTRACT_NEGOTIATION_ID; +import static org.eclipse.edc.edr.spi.types.EndpointDataReferenceEntry.EDR_ENTRY_CREATED_AT; +import static org.eclipse.edc.edr.spi.types.EndpointDataReferenceEntry.EDR_ENTRY_PROVIDER_ID; +import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.ID; +import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.VALUE; +import static org.eclipse.edc.junit.assertions.AbstractResultAssert.assertThat; +import static org.eclipse.tractusx.edc.api.edr.v2.EdrCacheApi.EndpointDataReferenceEntrySchema.EDR_ENTRY_OUTPUT_EXAMPLE; +import static org.mockito.Mockito.mock; + +public class EdrCacheApiTest { + + private final ObjectMapper objectMapper = JacksonJsonLd.createObjectMapper(); + private final JsonLd jsonLd = new TitaniumJsonLd(mock()); + + @Test + void edrEntryOutputExample() throws JsonProcessingException { + var jsonObject = objectMapper.readValue(EDR_ENTRY_OUTPUT_EXAMPLE, JsonObject.class); + var expanded = jsonLd.expand(jsonObject); + + assertThat(expanded).isSucceeded().satisfies(content -> { + assertThat(content.getString(ID)).isNotBlank(); + assertThat(content.getJsonArray(EDR_ENTRY_AGREEMENT_ID).getJsonObject(0).getString(VALUE)).isNotBlank(); + assertThat(content.getJsonArray(EDR_ENTRY_CONTRACT_NEGOTIATION_ID).getJsonObject(0).getString(VALUE)).isNotBlank(); + assertThat(content.getJsonArray(EDR_ENTRY_PROVIDER_ID).getJsonObject(0).getString(VALUE)).isNotBlank(); + assertThat(content.getJsonArray(EDR_ENTRY_ASSET_ID).getJsonObject(0).getString(VALUE)).isNotBlank(); + assertThat(content.getJsonArray(EDR_ENTRY_CREATED_AT).getJsonObject(0).getJsonNumber(VALUE)).isNotNull(); + }); + } +} diff --git a/edc-extensions/edr/edr-api-v2/src/test/java/org/eclipse/tractusx/edc/api/edr/v2/TestFunctions.java b/edc-extensions/edr/edr-api-v2/src/test/java/org/eclipse/tractusx/edc/api/edr/v2/TestFunctions.java new file mode 100644 index 000000000..9fdaf6f98 --- /dev/null +++ b/edc-extensions/edr/edr-api-v2/src/test/java/org/eclipse/tractusx/edc/api/edr/v2/TestFunctions.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.eclipse.tractusx.edc.api.edr.v2; + +import jakarta.json.Json; +import jakarta.json.JsonObject; +import org.eclipse.edc.connector.api.management.contractnegotiation.model.ContractOfferDescription; +import org.eclipse.edc.policy.model.Policy; +import org.eclipse.edc.spi.types.domain.offer.ContractOffer; +import org.eclipse.tractusx.edc.api.edr.v2.dto.NegotiateEdrRequestDto; +import org.eclipse.tractusx.edc.edr.spi.types.NegotiateEdrRequest; + +import java.util.UUID; + +import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.TYPE; +import static org.eclipse.edc.spi.CoreConstants.EDC_NAMESPACE; + +public class TestFunctions { + + public static ContractOfferDescription createOffer(String offerId, String assetId) { + return ContractOfferDescription.Builder.newInstance() + .offerId(offerId) + .assetId(assetId) + .policy(Policy.Builder.newInstance().build()) + .build(); + } + + public static ContractOfferDescription createOffer(Policy policy) { + return ContractOfferDescription.Builder.newInstance() + .offerId(UUID.randomUUID().toString()) + .assetId(UUID.randomUUID().toString()) + .policy(policy) + .build(); + } + + public static ContractOfferDescription createOffer(String offerId) { + return createOffer(offerId, UUID.randomUUID().toString()); + } + + public static ContractOfferDescription createOffer() { + return createOffer(UUID.randomUUID().toString(), UUID.randomUUID().toString()); + } + + public static JsonObject negotiationRequest() { + return Json.createObjectBuilder() + .add(TYPE, NegotiateEdrRequestDto.EDR_REQUEST_DTO_TYPE) + .add(EDC_NAMESPACE + "connectorId", "test") + .add(EDC_NAMESPACE + "providerId", "test") + .add(EDC_NAMESPACE + "connectorAddress", "test") + .add(EDC_NAMESPACE + "protocol", "dataspace-protocol-http") + .add(EDC_NAMESPACE + "offer", Json.createObjectBuilder() + .add(EDC_NAMESPACE + "offerId", "offerId") + .add(EDC_NAMESPACE + "assetId", "assetId") + .add(EDC_NAMESPACE + "policy", Json.createObjectBuilder().build()) + ) + .build(); + } + + public static NegotiateEdrRequest openRequest() { + return NegotiateEdrRequest.Builder.newInstance() + .connectorAddress("test") + .connectorId("id") + .protocol("test-protocol") + .offer(ContractOffer.Builder.newInstance() + .id("offerId") + .assetId("assetId") + .policy(Policy.Builder.newInstance().build()).build()) + .build(); + } +} diff --git a/edc-extensions/edr/edr-api-v2/src/test/java/org/eclipse/tractusx/edc/api/edr/v2/transform/EndpointDataReferenceToDataAddressTransformerTest.java b/edc-extensions/edr/edr-api-v2/src/test/java/org/eclipse/tractusx/edc/api/edr/v2/transform/EndpointDataReferenceToDataAddressTransformerTest.java new file mode 100644 index 000000000..4bad43e38 --- /dev/null +++ b/edc-extensions/edr/edr-api-v2/src/test/java/org/eclipse/tractusx/edc/api/edr/v2/transform/EndpointDataReferenceToDataAddressTransformerTest.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.eclipse.tractusx.edc.api.edr.v2.transform; + +import org.eclipse.edc.transform.spi.TransformerContext; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.eclipse.edc.spi.types.domain.edr.EndpointDataReference.AUTH_CODE; +import static org.eclipse.edc.spi.types.domain.edr.EndpointDataReference.AUTH_KEY; +import static org.eclipse.edc.spi.types.domain.edr.EndpointDataReference.Builder; +import static org.eclipse.edc.spi.types.domain.edr.EndpointDataReference.EDR_SIMPLE_TYPE; +import static org.eclipse.edc.spi.types.domain.edr.EndpointDataReference.ENDPOINT; +import static org.eclipse.edc.spi.types.domain.edr.EndpointDataReference.ID; +import static org.mockito.Mockito.mock; + +public class EndpointDataReferenceToDataAddressTransformerTest { + + private final TransformerContext context = mock(TransformerContext.class); + private EndpointDataReferenceToDataAddressTransformer transformer; + + @BeforeEach + void setUp() { + transformer = new EndpointDataReferenceToDataAddressTransformer(); + } + + @Test + void transform() { + + var dto = Builder.newInstance() + .id("dataRequestId") + .authCode("authCode") + .authKey("authKey") + .contractId("test-contract-id") + .endpoint("http://endpoint") + .build(); + + var dataAddress = transformer.transform(dto, context); + + assertThat(dataAddress).isNotNull(); + assertThat(dataAddress.getType()).isEqualTo(EDR_SIMPLE_TYPE); + assertThat(dataAddress.getStringProperty(ID)).isEqualTo(dto.getId()); + assertThat(dataAddress.getStringProperty(ENDPOINT)).isEqualTo(dto.getEndpoint()); + assertThat(dataAddress.getStringProperty(AUTH_KEY)).isEqualTo(dto.getAuthKey()); + assertThat(dataAddress.getStringProperty(AUTH_CODE)).isEqualTo(dto.getAuthCode()); + + } +} diff --git a/edc-extensions/edr/edr-api-v2/src/test/java/org/eclipse/tractusx/edc/api/edr/v2/transform/JsonObjectFromEndpointDataReferenceEntryTransformerTest.java b/edc-extensions/edr/edr-api-v2/src/test/java/org/eclipse/tractusx/edc/api/edr/v2/transform/JsonObjectFromEndpointDataReferenceEntryTransformerTest.java new file mode 100644 index 000000000..df15e3971 --- /dev/null +++ b/edc-extensions/edr/edr-api-v2/src/test/java/org/eclipse/tractusx/edc/api/edr/v2/transform/JsonObjectFromEndpointDataReferenceEntryTransformerTest.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.eclipse.tractusx.edc.api.edr.v2.transform; + +import jakarta.json.Json; +import org.eclipse.edc.edr.spi.types.EndpointDataReferenceEntry; +import org.eclipse.edc.transform.spi.TransformerContext; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntry.EDR_ENTRY_AGREEMENT_ID; +import static org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntry.EDR_ENTRY_ASSET_ID; +import static org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntry.EDR_ENTRY_CONTRACT_NEGOTIATION_ID; +import static org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntry.EDR_ENTRY_PROVIDER_ID; +import static org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntry.EDR_ENTRY_TRANSFER_PROCESS_ID; +import static org.mockito.Mockito.mock; + +class JsonObjectFromEndpointDataReferenceEntryTransformerTest { + + private final TransformerContext context = mock(TransformerContext.class); + private JsonObjectFromEndpointDataReferenceEntryTransformer transformer; + + @BeforeEach + void setUp() { + transformer = new JsonObjectFromEndpointDataReferenceEntryTransformer(Json.createBuilderFactory(Map.of())); + } + + @Test + void transform() { + + var dto = EndpointDataReferenceEntry.Builder.newInstance() + .assetId("id") + .transferProcessId("tpId") + .agreementId("aId") + .providerId("providerId") + .contractNegotiationId("contractNegotiationId") + .build(); + + var jsonObject = transformer.transform(dto, context); + + assertThat(jsonObject).isNotNull(); + assertThat(jsonObject.getJsonString(EDR_ENTRY_AGREEMENT_ID).getString()).isNotNull().isEqualTo(dto.getAgreementId()); + assertThat(jsonObject.getJsonString(EDR_ENTRY_CONTRACT_NEGOTIATION_ID).getString()).isNotNull().isEqualTo(dto.getContractNegotiationId()); + assertThat(jsonObject.getJsonString(EDR_ENTRY_ASSET_ID).getString()).isNotNull().isEqualTo(dto.getAssetId()); + assertThat(jsonObject.getJsonString(EDR_ENTRY_TRANSFER_PROCESS_ID).getString()).isNotNull().isEqualTo(dto.getTransferProcessId()); + assertThat(jsonObject.getJsonString(EDR_ENTRY_PROVIDER_ID).getString()).isNotNull().isEqualTo(dto.getProviderId()); + + } +} diff --git a/edc-extensions/edr/edr-api-v2/src/test/java/org/eclipse/tractusx/edc/api/edr/v2/transform/JsonObjectToNegotiateEdrRequestDtoTransformerTest.java b/edc-extensions/edr/edr-api-v2/src/test/java/org/eclipse/tractusx/edc/api/edr/v2/transform/JsonObjectToNegotiateEdrRequestDtoTransformerTest.java new file mode 100644 index 000000000..6409d37f4 --- /dev/null +++ b/edc-extensions/edr/edr-api-v2/src/test/java/org/eclipse/tractusx/edc/api/edr/v2/transform/JsonObjectToNegotiateEdrRequestDtoTransformerTest.java @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.eclipse.tractusx.edc.api.edr.v2.transform; + +import jakarta.json.Json; +import jakarta.json.JsonArrayBuilder; +import jakarta.json.JsonObject; +import jakarta.json.JsonValue; +import org.eclipse.edc.connector.api.management.contractnegotiation.model.ContractOfferDescription; +import org.eclipse.edc.jsonld.TitaniumJsonLd; +import org.eclipse.edc.jsonld.spi.JsonLd; +import org.eclipse.edc.spi.monitor.Monitor; +import org.eclipse.edc.spi.types.domain.callback.CallbackAddress; +import org.eclipse.edc.transform.spi.ProblemBuilder; +import org.eclipse.edc.transform.spi.TransformerContext; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.util.Set; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.eclipse.edc.connector.api.management.contractnegotiation.model.ContractOfferDescription.ASSET_ID; +import static org.eclipse.edc.connector.api.management.contractnegotiation.model.ContractOfferDescription.OFFER_ID; +import static org.eclipse.edc.connector.api.management.contractnegotiation.model.ContractOfferDescription.POLICY; +import static org.eclipse.edc.connector.contract.spi.types.negotiation.ContractRequest.CALLBACK_ADDRESSES; +import static org.eclipse.edc.connector.contract.spi.types.negotiation.ContractRequest.CONTRACT_REQUEST_TYPE; +import static org.eclipse.edc.connector.contract.spi.types.negotiation.ContractRequest.OFFER; +import static org.eclipse.edc.connector.contract.spi.types.negotiation.ContractRequest.PROTOCOL; +import static org.eclipse.edc.connector.contract.spi.types.negotiation.ContractRequest.PROVIDER_ID; +import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.TYPE; +import static org.eclipse.edc.jsonld.spi.PropertyAndTypeNames.ODRL_OBLIGATION_ATTRIBUTE; +import static org.eclipse.edc.jsonld.spi.PropertyAndTypeNames.ODRL_PERMISSION_ATTRIBUTE; +import static org.eclipse.edc.jsonld.spi.PropertyAndTypeNames.ODRL_POLICY_TYPE_SET; +import static org.eclipse.edc.jsonld.spi.PropertyAndTypeNames.ODRL_PROHIBITION_ATTRIBUTE; +import static org.eclipse.edc.spi.CoreConstants.EDC_NAMESPACE; +import static org.eclipse.edc.spi.types.domain.callback.CallbackAddress.EVENTS; +import static org.eclipse.edc.spi.types.domain.callback.CallbackAddress.IS_TRANSACTIONAL; +import static org.eclipse.edc.spi.types.domain.callback.CallbackAddress.URI; +import static org.eclipse.tractusx.edc.api.edr.v2.dto.NegotiateEdrRequestDto.EDR_REQUEST_DTO_COUNTERPARTY_ADDRESS; +import static org.eclipse.tractusx.edc.api.edr.v2.dto.NegotiateEdrRequestDto.EDR_REQUEST_DTO_COUNTERPARTY_ID; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +class JsonObjectToNegotiateEdrRequestDtoTransformerTest { + + private final JsonLd jsonLd = new TitaniumJsonLd(mock(Monitor.class)); + private final TransformerContext context = mock(TransformerContext.class); + private JsonObjectToNegotiateEdrRequestDtoTransformer transformer; + + @BeforeEach + void setUp() { + transformer = new JsonObjectToNegotiateEdrRequestDtoTransformer(); + } + + @Test + void transform() { + var jsonObject = Json.createObjectBuilder() + .add(TYPE, CONTRACT_REQUEST_TYPE) + .add(EDR_REQUEST_DTO_COUNTERPARTY_ADDRESS, "test-address") + .add(EDR_REQUEST_DTO_COUNTERPARTY_ID, "test-conn-id") + .add(PROTOCOL, "test-protocol") + .add(PROVIDER_ID, "test-provider-id") + .add(CALLBACK_ADDRESSES, createCallbackAddress()) + .add(OFFER, Json.createObjectBuilder() + .add(OFFER_ID, "test-offer-id") + .add(ASSET_ID, "test-asset") + .add(POLICY, createPolicy()) + .build()) + .build(); + + when(context.transform(any(JsonValue.class), eq(ContractOfferDescription.class))).thenReturn(ContractOfferDescription.Builder.newInstance().build()); + + when(context.transform(any(JsonObject.class), eq(CallbackAddress.class))).thenReturn(CallbackAddress.Builder.newInstance() + .uri("http://test.local") + .events(Set.of("foo", "bar")) + .transactional(true) + .build()); + when(context.transform(any(CallbackAddress.class), eq(CallbackAddress.class))).thenReturn(CallbackAddress.Builder.newInstance() + .uri("http://test.local") + .events(Set.of("foo", "bar")) + .transactional(true) + .build()); + var dto = transformer.transform(jsonLd.expand(jsonObject).getContent(), context); + + assertThat(dto).isNotNull(); + assertThat(dto.getCallbackAddresses()).isNotEmpty(); + assertThat(dto.getProtocol()).isEqualTo("test-protocol"); + assertThat(dto.getCounterPartyAddress()).isEqualTo("test-address"); + assertThat(dto.getCounterPartyId()).isEqualTo("test-conn-id"); + assertThat(dto.getProviderId()).isEqualTo("test-provider-id"); + assertThat(dto.getOffer()).isNotNull(); + + } + + @Test + void transform_reportErrors() { + + when(context.problem()).thenReturn(new ProblemBuilder(context)); + + var jsonObject = Json.createObjectBuilder() + .add(TYPE, CONTRACT_REQUEST_TYPE) + .add(EDC_NAMESPACE + "notFound", "test-address") + .build(); + + var dto = transformer.transform(jsonLd.expand(jsonObject).getContent(), context); + + assertThat(dto).isNotNull(); + verify(context, times(1)).reportProblem(anyString()); + } + + private JsonArrayBuilder createCallbackAddress() { + var builder = Json.createArrayBuilder(); + return builder.add(Json.createObjectBuilder() + .add(IS_TRANSACTIONAL, true) + .add(URI, "http://test.local/") + .add(EVENTS, Json.createArrayBuilder().build())); + } + + private JsonObject createPolicy() { + var permissionJson = getJsonObject("permission"); + var prohibitionJson = getJsonObject("prohibition"); + var dutyJson = getJsonObject("duty"); + return Json.createObjectBuilder() + .add(TYPE, ODRL_POLICY_TYPE_SET) + .add(ODRL_PERMISSION_ATTRIBUTE, permissionJson) + .add(ODRL_PROHIBITION_ATTRIBUTE, prohibitionJson) + .add(ODRL_OBLIGATION_ATTRIBUTE, dutyJson) + .build(); + } + + private JsonObject getJsonObject(String type) { + return Json.createObjectBuilder() + .add(TYPE, type) + .build(); + } +} diff --git a/edc-extensions/edr/edr-api-v2/src/test/java/org/eclipse/tractusx/edc/api/edr/v2/transform/NegotiateEdrRequestDtoToNegotiateEdrRequestTransformerTest.java b/edc-extensions/edr/edr-api-v2/src/test/java/org/eclipse/tractusx/edc/api/edr/v2/transform/NegotiateEdrRequestDtoToNegotiateEdrRequestTransformerTest.java new file mode 100644 index 000000000..24a31450c --- /dev/null +++ b/edc-extensions/edr/edr-api-v2/src/test/java/org/eclipse/tractusx/edc/api/edr/v2/transform/NegotiateEdrRequestDtoToNegotiateEdrRequestTransformerTest.java @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.eclipse.tractusx.edc.api.edr.v2.transform; + +import org.eclipse.edc.spi.types.domain.callback.CallbackAddress; +import org.eclipse.edc.transform.spi.TransformerContext; +import org.eclipse.tractusx.edc.api.edr.v2.dto.NegotiateEdrRequestDto; +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.eclipse.tractusx.edc.api.edr.v2.TestFunctions.createOffer; +import static org.mockito.Mockito.mock; + +public class NegotiateEdrRequestDtoToNegotiateEdrRequestTransformerTest { + + private final NegotiateEdrRequestDtoToNegotiatedEdrRequestTransformer transformer = new NegotiateEdrRequestDtoToNegotiatedEdrRequestTransformer(); + + private final TransformerContext context = mock(TransformerContext.class); + + @Test + void inputOutputType() { + assertThat(transformer.getInputType()).isNotNull(); + assertThat(transformer.getOutputType()).isNotNull(); + } + + @Test + void verify_transform() { + var callback = CallbackAddress.Builder.newInstance() + .uri("local://test") + .build(); + var dto = NegotiateEdrRequestDto.Builder.newInstance() + .counterPartyId("connectorId") + .connectorAddress("address") + .protocol("protocol") + .providerId("test-provider") + .offer(createOffer("offerId", "assetId")) + .callbackAddresses(List.of(callback)) + .build(); + + var request = transformer.transform(dto, context); + + assertThat(request).isNotNull(); + assertThat(request.getConnectorId()).isEqualTo("connectorId"); + assertThat(request.getConnectorAddress()).isEqualTo("address"); + assertThat(request.getProtocol()).isEqualTo("protocol"); + assertThat(request.getOffer().getId()).isEqualTo("offerId"); + assertThat(request.getOffer().getPolicy()).isNotNull(); + assertThat(request.getCallbackAddresses()).hasSize(1); + } + + @Test + void verify_transfor_withNoProviderId() { + var dto = NegotiateEdrRequestDto.Builder.newInstance() + .counterPartyId("connectorId") + .connectorAddress("address") + .protocol("protocol") + // do not set provider ID + .offer(createOffer("offerId", "assetId")) + .build(); + + var request = transformer.transform(dto, context); + + assertThat(request).isNotNull(); + } + + @Test + void verify_transform_withNoConsumerId() { + var dto = NegotiateEdrRequestDto.Builder.newInstance() + .counterPartyId("connectorId") + .connectorAddress("address") + .protocol("protocol") + // do not set consumer ID + .providerId("urn:connector:test-provider") + .offer(createOffer("offerId", "assetId")) + .build(); + + var request = transformer.transform(dto, context); + assertThat(request).isNotNull(); + } +} diff --git a/edc-extensions/edr/edr-api-v2/src/test/java/org/eclipse/tractusx/edc/api/edr/v2/validation/NegotiateEdrRequestDtoValidatorTest.java b/edc-extensions/edr/edr-api-v2/src/test/java/org/eclipse/tractusx/edc/api/edr/v2/validation/NegotiateEdrRequestDtoValidatorTest.java new file mode 100644 index 000000000..6dfc87b2b --- /dev/null +++ b/edc-extensions/edr/edr-api-v2/src/test/java/org/eclipse/tractusx/edc/api/edr/v2/validation/NegotiateEdrRequestDtoValidatorTest.java @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.eclipse.tractusx.edc.api.edr.v2.validation; + +import jakarta.json.Json; +import jakarta.json.JsonArrayBuilder; +import jakarta.json.JsonObject; +import org.eclipse.edc.validator.spi.ValidationFailure; +import org.eclipse.edc.validator.spi.Validator; +import org.eclipse.edc.validator.spi.Violation; +import org.junit.jupiter.api.Test; + +import static jakarta.json.Json.createArrayBuilder; +import static jakarta.json.Json.createObjectBuilder; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.InstanceOfAssertFactories.list; +import static org.eclipse.edc.connector.api.management.contractnegotiation.model.ContractOfferDescription.ASSET_ID; +import static org.eclipse.edc.connector.api.management.contractnegotiation.model.ContractOfferDescription.OFFER_ID; +import static org.eclipse.edc.connector.api.management.contractnegotiation.model.ContractOfferDescription.POLICY; +import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.VALUE; +import static org.eclipse.edc.junit.assertions.AbstractResultAssert.assertThat; +import static org.eclipse.tractusx.edc.api.edr.v2.dto.NegotiateEdrRequestDto.EDR_REQUEST_DTO_COUNTERPARTY_ADDRESS; +import static org.eclipse.tractusx.edc.api.edr.v2.dto.NegotiateEdrRequestDto.EDR_REQUEST_DTO_OFFER; +import static org.eclipse.tractusx.edc.api.edr.v2.dto.NegotiateEdrRequestDto.EDR_REQUEST_DTO_PROTOCOL; +import static org.eclipse.tractusx.edc.api.edr.v2.dto.NegotiateEdrRequestDto.EDR_REQUEST_DTO_PROVIDER_ID; + +public class NegotiateEdrRequestDtoValidatorTest { + + private final Validator validator = NegotiateEdrRequestDtoValidator.instance(); + + @Test + void shouldSuccess_whenObjectIsValid() { + var input = Json.createObjectBuilder() + .add(EDR_REQUEST_DTO_COUNTERPARTY_ADDRESS, value("http://connector-address")) + .add(EDR_REQUEST_DTO_PROTOCOL, value("protocol")) + .add(EDR_REQUEST_DTO_PROVIDER_ID, value("connector-id")) + .add(EDR_REQUEST_DTO_OFFER, createArrayBuilder().add(createObjectBuilder() + .add(OFFER_ID, value("offerId")) + .add(ASSET_ID, value("offerId")) + .add(POLICY, createArrayBuilder().add(createObjectBuilder())) + )) + .build(); + + var result = validator.validate(input); + + assertThat(result).isSucceeded(); + } + + @Test + void shouldFail_whenMandatoryPropertiesAreMissing() { + var input = Json.createObjectBuilder().build(); + + var result = validator.validate(input); + + assertThat(result).isFailed().extracting(ValidationFailure::getViolations).asInstanceOf(list(Violation.class)) + .isNotEmpty() + .anySatisfy(violation -> assertThat(violation.path()).isEqualTo(EDR_REQUEST_DTO_COUNTERPARTY_ADDRESS)) + .anySatisfy(violation -> assertThat(violation.path()).isEqualTo(EDR_REQUEST_DTO_PROTOCOL)) + .anySatisfy(violation -> assertThat(violation.path()).isEqualTo(EDR_REQUEST_DTO_OFFER)); + } + + @Test + void shouldFail_whenOfferMandatoryPropertiesAreMissing() { + var input = Json.createObjectBuilder() + .add(EDR_REQUEST_DTO_COUNTERPARTY_ADDRESS, value("http://connector-address")) + .add(EDR_REQUEST_DTO_PROTOCOL, value("protocol")) + .add(EDR_REQUEST_DTO_PROVIDER_ID, value("connector-id")) + .add(EDR_REQUEST_DTO_OFFER, createArrayBuilder().add(createObjectBuilder())) + .build(); + + var result = validator.validate(input); + + assertThat(result).isFailed().extracting(ValidationFailure::getViolations).asInstanceOf(list(Violation.class)) + .isNotEmpty() + .anySatisfy(violation -> assertThat(violation.path()).isEqualTo(EDR_REQUEST_DTO_OFFER + "/" + OFFER_ID)) + .anySatisfy(violation -> assertThat(violation.path()).isEqualTo(EDR_REQUEST_DTO_OFFER + "/" + ASSET_ID)) + .anySatisfy(violation -> assertThat(violation.path()).isEqualTo(EDR_REQUEST_DTO_OFFER + "/" + POLICY)); + } + + private JsonArrayBuilder value(String value) { + return createArrayBuilder().add(createObjectBuilder().add(VALUE, value)); + } +} diff --git a/edc-extensions/tokenrefresh-handler/build.gradle.kts b/edc-extensions/tokenrefresh-handler/build.gradle.kts index c2612c77d..65e3ba221 100644 --- a/edc-extensions/tokenrefresh-handler/build.gradle.kts +++ b/edc-extensions/tokenrefresh-handler/build.gradle.kts @@ -23,6 +23,7 @@ plugins { } dependencies { + implementation(project(":spi:core-spi")) implementation(project(":spi:tokenrefresh-spi")) implementation(libs.edc.spi.core) implementation(libs.edc.spi.edrstore) diff --git a/edc-extensions/tokenrefresh-handler/src/main/java/org/eclipse/tractusx/edc/common/tokenrefresh/TokenRefreshHandlerExtension.java b/edc-extensions/tokenrefresh-handler/src/main/java/org/eclipse/tractusx/edc/common/tokenrefresh/TokenRefreshHandlerExtension.java index 52d57b88b..7fb54d155 100644 --- a/edc-extensions/tokenrefresh-handler/src/main/java/org/eclipse/tractusx/edc/common/tokenrefresh/TokenRefreshHandlerExtension.java +++ b/edc-extensions/tokenrefresh-handler/src/main/java/org/eclipse/tractusx/edc/common/tokenrefresh/TokenRefreshHandlerExtension.java @@ -19,7 +19,7 @@ package org.eclipse.tractusx.edc.common.tokenrefresh; -import org.eclipse.edc.edr.spi.store.EndpointDataReferenceStore; +import org.eclipse.edc.edr.spi.store.EndpointDataReferenceCache; import org.eclipse.edc.identitytrust.SecureTokenService; import org.eclipse.edc.runtime.metamodel.annotation.Extension; import org.eclipse.edc.runtime.metamodel.annotation.Inject; @@ -39,7 +39,7 @@ public class TokenRefreshHandlerExtension implements ServiceExtension { // this setting is defined by the IdentityAndTrustExtension private static final String PARTICIPANT_DID_PROPERTY = "edc.iam.issuer.id"; @Inject - private EndpointDataReferenceStore edrStore; + private EndpointDataReferenceCache edrStore; @Inject private EdcHttpClient httpClient; @Inject diff --git a/edc-extensions/tokenrefresh-handler/src/main/java/org/eclipse/tractusx/edc/common/tokenrefresh/TokenRefreshHandlerImpl.java b/edc-extensions/tokenrefresh-handler/src/main/java/org/eclipse/tractusx/edc/common/tokenrefresh/TokenRefreshHandlerImpl.java index b64904c30..126f5377b 100644 --- a/edc-extensions/tokenrefresh-handler/src/main/java/org/eclipse/tractusx/edc/common/tokenrefresh/TokenRefreshHandlerImpl.java +++ b/edc-extensions/tokenrefresh-handler/src/main/java/org/eclipse/tractusx/edc/common/tokenrefresh/TokenRefreshHandlerImpl.java @@ -24,11 +24,15 @@ import okhttp3.HttpUrl; import okhttp3.Request; import okhttp3.RequestBody; -import org.eclipse.edc.edr.spi.store.EndpointDataReferenceStore; +import org.eclipse.edc.edr.spi.store.EndpointDataReferenceCache; import org.eclipse.edc.identitytrust.SecureTokenService; import org.eclipse.edc.spi.http.EdcHttpClient; import org.eclipse.edc.spi.monitor.Monitor; import org.eclipse.edc.spi.result.Result; +import org.eclipse.edc.spi.result.ServiceResult; +import org.eclipse.edc.spi.result.StoreResult; +import org.eclipse.edc.spi.types.domain.DataAddress; +import org.eclipse.edc.spi.types.domain.edr.EndpointDataReference; import org.eclipse.edc.util.string.StringUtils; import org.eclipse.tractusx.edc.spi.tokenrefresh.common.TokenRefreshHandler; import org.eclipse.tractusx.edc.spi.tokenrefresh.dataplane.model.TokenResponse; @@ -41,13 +45,17 @@ import static org.eclipse.edc.jwt.spi.JwtRegisteredClaimNames.ISSUER; import static org.eclipse.edc.jwt.spi.JwtRegisteredClaimNames.JWT_ID; import static org.eclipse.edc.jwt.spi.JwtRegisteredClaimNames.SUBJECT; +import static org.eclipse.edc.spi.CoreConstants.EDC_NAMESPACE; +import static org.eclipse.edc.spi.result.Result.success; import static org.eclipse.edc.util.string.StringUtils.isNullOrBlank; +import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.TX_AUTH_NS; public class TokenRefreshHandlerImpl implements TokenRefreshHandler { - public static final String PROPERTY_AUTHORIZATION = "authorization"; - public static final String PROPERTY_REFRESH_TOKEN = "refreshToken"; - public static final String PROPERTY_REFRESH_ENDPOINT = "refreshEndpoint"; - private final EndpointDataReferenceStore edrStore; + public static final String PROPERTY_AUTHORIZATION = EDC_NAMESPACE + "authorization"; + public static final String PROPERTY_REFRESH_TOKEN = TX_AUTH_NS + "refreshToken"; + public static final String PROPERTY_REFRESH_ENDPOINT = TX_AUTH_NS + "refreshEndpoint"; + public static final String PROPERTY_EXPIRES_IN = TX_AUTH_NS + "expiresIn"; + private final EndpointDataReferenceCache edrCache; private final EdcHttpClient httpClient; private final String ownDid; private final Monitor monitor; @@ -57,19 +65,19 @@ public class TokenRefreshHandlerImpl implements TokenRefreshHandler { /** * Creates a new TokenRefreshHandler * - * @param edrStore a persistent storage where {@link org.eclipse.edc.spi.types.domain.edr.EndpointDataReference} objects are stored. + * @param edrCache a persistent storage where {@link EndpointDataReference} objects are stored. * @param httpClient needed to make the actual refresh call against the refresh endpoint * @param ownDid the DID of this connector * @param secureTokenService Service to generate the authentication token * @param objectMapper ObjectMapper to interpret JSON responses */ - public TokenRefreshHandlerImpl(EndpointDataReferenceStore edrStore, + public TokenRefreshHandlerImpl(EndpointDataReferenceCache edrCache, EdcHttpClient httpClient, String ownDid, Monitor monitor, SecureTokenService secureTokenService, ObjectMapper objectMapper) { - this.edrStore = edrStore; + this.edrCache = edrCache; this.httpClient = httpClient; this.ownDid = ownDid; this.monitor = monitor; @@ -78,27 +86,32 @@ public TokenRefreshHandlerImpl(EndpointDataReferenceStore edrStore, } @Override - public Result refreshToken(String tokenId) { - var edrResult = edrStore.resolveByTransferProcess(tokenId); + public ServiceResult refreshToken(String tokenId) { + var edrResult = edrCache.get(tokenId); if (edrResult.failed()) { - return Result.failure(edrResult.getFailureDetail()); + return ServiceResult.notFound(edrResult.getFailureDetail()); } var edr = edrResult.getContent(); + return refreshToken(tokenId, edr); + } + + @Override + public ServiceResult refreshToken(String tokenId, DataAddress edr) { var accessToken = edr.getStringProperty(PROPERTY_AUTHORIZATION); var refreshToken = edr.getProperties().get(PROPERTY_REFRESH_TOKEN); var refreshEndpoint = edr.getProperties().get(PROPERTY_REFRESH_ENDPOINT); if (isNullOrBlank(accessToken)) { - return Result.failure("Cannot perform token refresh: required property 'authorization' not found on EDR."); + return ServiceResult.badRequest("Cannot perform token refresh: required property 'authorization' not found on EDR."); } if (isNullOrBlank(StringUtils.toString(refreshToken))) { - return Result.failure("Cannot perform token refresh: required property 'refreshToken' not found on EDR."); + return ServiceResult.badRequest("Cannot perform token refresh: required property 'refreshToken' not found on EDR."); } if (isNullOrBlank(StringUtils.toString(refreshEndpoint))) { - return Result.failure("Cannot perform token refresh: required property 'refreshEndpoint' not found on EDR."); + return ServiceResult.badRequest("Cannot perform token refresh: required property 'refreshEndpoint' not found on EDR."); } - return getStringClaim(accessToken, ISSUER) + var result = getStringClaim(accessToken, ISSUER) .map(audience -> Map.of( JWT_ID, tokenId, ISSUER, ownDid, @@ -106,11 +119,29 @@ public Result refreshToken(String tokenId) { AUDIENCE, audience )) .compose(claims -> secureTokenService.createToken(claims, accessToken)) - .compose(authToken -> createTokenRefreshRequest(refreshEndpoint.toString(), refreshToken.toString(), "Bearer %s".formatted(authToken.getToken()))) - .compose(this::executeRequest); + .compose(authToken -> createTokenRefreshRequest(refreshEndpoint.toString(), refreshToken.toString(), "Bearer %s".formatted(authToken.getToken()))); + + if (result.failed()) { + return ServiceResult.badRequest("Could not execute token refresh: " + result.getFailureDetail()); + } + + return executeRequest(result.getContent()) + .compose(tr -> update(tokenId, edr, tr)); + } + + private ServiceResult update(String id, DataAddress oldEdr, TokenResponse tokenResponse) { + //todo: create new DataAddress out of the oldEdr, update refresh token, store and return + var newEdr = DataAddress.Builder.newInstance() + .type(oldEdr.getType()) + .properties(oldEdr.getProperties()) + .property(PROPERTY_AUTHORIZATION, tokenResponse.accessToken()) + .property(PROPERTY_REFRESH_TOKEN, tokenResponse.refreshToken()) + .property(PROPERTY_EXPIRES_IN, String.valueOf(tokenResponse.expiresInSeconds())) + .build(); + return ServiceResult.from(edrCache.put(id, newEdr)).map(u -> newEdr); } - private Result executeRequest(Request tokenRefreshRequest) { + private ServiceResult executeRequest(Request tokenRefreshRequest) { try (var response = httpClient.execute(tokenRefreshRequest)) { if (response.isSuccessful()) { if (response.body() != null) { @@ -118,22 +149,27 @@ private Result executeRequest(Request tokenRefreshRequest) { var jsonBody = response.body().string(); if (!StringUtils.isNullOrEmpty(jsonBody)) { var tokenResponse = objectMapper.readValue(jsonBody, TokenResponse.class); - return Result.success(tokenResponse); + return ServiceResult.success(tokenResponse); } } - return Result.failure("Token refresh successful, but body was empty."); + return ServiceResult.badRequest("Token refresh successful, but body was empty."); } - return Result.failure("Token refresh not successful: %d, message: %s".formatted(response.code(), response.message())); + return switch (response.code()) { + case 401 -> ServiceResult.unauthorized(response.message()); + case 409 -> ServiceResult.conflict(response.message()); + case 404 -> ServiceResult.notFound(response.message()); + default -> ServiceResult.badRequest(response.message()); + }; } catch (IOException e) { monitor.warning("Error executing token refresh request", e); - return Result.failure("Error executing token refresh request: %s".formatted(e)); + return ServiceResult.from(StoreResult.generalError("Error executing token refresh request: %s".formatted(e))); } } private Result createTokenRefreshRequest(String refreshEndpoint, String refreshToken, String bearerToken) { // see https://github.com/eclipse-tractusx/tractusx-profiles/blob/main/tx/refresh/refresh.token.grant.profile.md#3-the-refresh-request if (!refreshEndpoint.endsWith("/token")) { - refreshToken += "/token"; + refreshEndpoint += "/token"; } var url = HttpUrl.parse(refreshEndpoint) .newBuilder() @@ -141,7 +177,7 @@ private Result createTokenRefreshRequest(String refreshEndpoint, String .addQueryParameter("refresh_token", refreshToken) .build(); - return Result.success(new Request.Builder() + return success(new Request.Builder() .addHeader("Authorization", bearerToken) .url(url) .post(RequestBody.create(new byte[0])) @@ -150,7 +186,7 @@ private Result createTokenRefreshRequest(String refreshEndpoint, String private Result getStringClaim(String accessToken, String claimName) { try { - return Result.success(SignedJWT.parse(accessToken).getJWTClaimsSet().getStringClaim(claimName)); + return success(SignedJWT.parse(accessToken).getJWTClaimsSet().getStringClaim(claimName)); } catch (ParseException e) { monitor.warning("Failed to get string claim '%s'".formatted(claimName), e); return Result.failure("Failed to parse string claim '%s': %s".formatted(claimName, e)); diff --git a/edc-extensions/tokenrefresh-handler/src/test/java/org/eclipse/tractusx/edc/common/tokenrefresh/TokenRefreshHandlerImplTest.java b/edc-extensions/tokenrefresh-handler/src/test/java/org/eclipse/tractusx/edc/common/tokenrefresh/TokenRefreshHandlerImplTest.java index 362e81fbc..e8e340b8d 100644 --- a/edc-extensions/tokenrefresh-handler/src/test/java/org/eclipse/tractusx/edc/common/tokenrefresh/TokenRefreshHandlerImplTest.java +++ b/edc-extensions/tokenrefresh-handler/src/test/java/org/eclipse/tractusx/edc/common/tokenrefresh/TokenRefreshHandlerImplTest.java @@ -34,7 +34,8 @@ import okhttp3.Request; import okhttp3.Response; import okhttp3.ResponseBody; -import org.eclipse.edc.edr.spi.store.EndpointDataReferenceStore; +import org.assertj.core.api.Assertions; +import org.eclipse.edc.edr.spi.store.EndpointDataReferenceCache; import org.eclipse.edc.identitytrust.SecureTokenService; import org.eclipse.edc.spi.http.EdcHttpClient; import org.eclipse.edc.spi.iam.TokenRepresentation; @@ -52,11 +53,13 @@ import org.junit.jupiter.params.provider.ArgumentsSource; import java.io.IOException; -import java.security.PrivateKey; import java.util.stream.Stream; -import static org.assertj.core.api.Assertions.assertThat; import static org.eclipse.edc.junit.assertions.AbstractResultAssert.assertThat; +import static org.eclipse.tractusx.edc.common.tokenrefresh.TokenRefreshHandlerImpl.PROPERTY_AUTHORIZATION; +import static org.eclipse.tractusx.edc.common.tokenrefresh.TokenRefreshHandlerImpl.PROPERTY_EXPIRES_IN; +import static org.eclipse.tractusx.edc.common.tokenrefresh.TokenRefreshHandlerImpl.PROPERTY_REFRESH_ENDPOINT; +import static org.eclipse.tractusx.edc.common.tokenrefresh.TokenRefreshHandlerImpl.PROPERTY_REFRESH_TOKEN; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyMap; import static org.mockito.ArgumentMatchers.anyString; @@ -70,13 +73,11 @@ class TokenRefreshHandlerImplTest { public static final String REFRESH_ENDPOINT = "http://fizz.buzz/quazz"; private static final String CONSUMER_DID = "did:web:bob"; - private static final String PUBLIC_KEY_ID = CONSUMER_DID + "#key-1"; private static final String PROVIDER_DID = "did:web:alice"; - private final EndpointDataReferenceStore edrStore = mock(); + private final EndpointDataReferenceCache edrCache = mock(); private final EdcHttpClient mockedHttpClient = mock(); private final SecureTokenService mockedTokenService = mock(); private TokenRefreshHandlerImpl tokenRefreshHandler; - private PrivateKey consumerKey; private ObjectMapper objectMapper; private static String createJwt() { @@ -91,16 +92,16 @@ private static String createJwt() { } @BeforeEach - void setup() throws JOSEException { - consumerKey = new ECKeyGenerator(Curve.P_256).generate().toPrivateKey(); + void setup() { objectMapper = new ObjectMapper(); - tokenRefreshHandler = new TokenRefreshHandlerImpl(edrStore, mockedHttpClient, CONSUMER_DID, mock(), + tokenRefreshHandler = new TokenRefreshHandlerImpl(edrCache, mockedHttpClient, CONSUMER_DID, mock(), mockedTokenService, objectMapper); } @Test void refresh_validateCorrectRequest() throws IOException { - when(edrStore.resolveByTransferProcess(anyString())).thenReturn(StoreResult.success(createEdr().build())); + when(edrCache.get(anyString())).thenReturn(StoreResult.success(createEdr().build())); + when(edrCache.put(any(), any())).thenReturn(StoreResult.success()); when(mockedTokenService.createToken(anyMap(), anyString())).thenReturn(Result.success(TokenRepresentation.Builder.newInstance().token("foo-auth-token").build())); var tokenResponse = new TokenResponse("new-access-token", "new-refresh-token", 60 * 5L, "bearer"); var successResponse = createResponse(tokenResponse, 200, ""); @@ -108,22 +109,22 @@ void refresh_validateCorrectRequest() throws IOException { var res = tokenRefreshHandler.refreshToken("token-id"); assertThat(res).isSucceeded() .satisfies(tr -> { - assertThat(tr.accessToken()).isEqualTo("new-access-token"); - assertThat(tr.refreshToken()).isEqualTo("new-refresh-token"); - assertThat(tr.expiresInSeconds()).isEqualTo(300L); - assertThat(tr.tokenType()).isEqualTo("bearer"); + Assertions.assertThat(tr.getProperties()).containsEntry(PROPERTY_AUTHORIZATION, "new-access-token"); + Assertions.assertThat(tr.getProperties()).containsEntry(PROPERTY_EXPIRES_IN, "300"); + Assertions.assertThat(tr.getProperties()).containsEntry(PROPERTY_REFRESH_TOKEN, "new-refresh-token"); + Assertions.assertThat(tr.getProperties()).containsEntry(PROPERTY_REFRESH_ENDPOINT, REFRESH_ENDPOINT); }); } @Test void refresh_edrNotFound() { - when(edrStore.resolveByTransferProcess(anyString())).thenReturn(StoreResult.notFound("foo")); + when(edrCache.get(anyString())).thenReturn(StoreResult.notFound("foo")); assertThat(tokenRefreshHandler.refreshToken("token-id")).isFailed() .detail().isEqualTo("foo"); - verify(edrStore).resolveByTransferProcess(eq("token-id")); - verifyNoMoreInteractions(edrStore); + verify(edrCache).get(eq("token-id")); + verifyNoMoreInteractions(edrCache); verifyNoInteractions(mockedHttpClient, mockedTokenService); } @@ -135,7 +136,7 @@ void refresh_edrLacksRequiredProperties(String authorization, String refreshToke .property("refreshToken", refreshToken) .property("refreshEndpoint", refreshEndpoint) .build(); - when(edrStore.resolveByTransferProcess(anyString())).thenReturn(StoreResult.success(invalidEdr)); + when(edrCache.get(anyString())).thenReturn(StoreResult.success(invalidEdr)); assertThat(tokenRefreshHandler.refreshToken("token-id")).isFailed() .detail() @@ -144,7 +145,7 @@ void refresh_edrLacksRequiredProperties(String authorization, String refreshToke @Test void refresh_endpointReturnsFailure() throws IOException { - when(edrStore.resolveByTransferProcess(anyString())).thenReturn(StoreResult.success(createEdr().build())); + when(edrCache.get(anyString())).thenReturn(StoreResult.success(createEdr().build())); when(mockedTokenService.createToken(anyMap(), anyString())).thenReturn(Result.success(TokenRepresentation.Builder.newInstance().token("foo-auth-token").build())); var response401 = createResponse(null, 401, "Not authorized"); @@ -152,12 +153,12 @@ void refresh_endpointReturnsFailure() throws IOException { var res = tokenRefreshHandler.refreshToken("token-id"); assertThat(res).isFailed() - .detail().isEqualTo("Token refresh not successful: 401, message: Not authorized"); + .detail().isEqualTo("Not authorized"); } @Test void refresh_endpointReturnsEmptyBody() throws IOException { - when(edrStore.resolveByTransferProcess(anyString())).thenReturn(StoreResult.success(createEdr().build())); + when(edrCache.get(anyString())).thenReturn(StoreResult.success(createEdr().build())); when(mockedTokenService.createToken(anyMap(), anyString())).thenReturn(Result.success(TokenRepresentation.Builder.newInstance().token("foo-auth-token").build())); var successResponse = createResponse(null, 200, ""); when(mockedHttpClient.execute(any())).thenReturn(successResponse); @@ -168,7 +169,7 @@ void refresh_endpointReturnsEmptyBody() throws IOException { @Test void refresh_ioException() throws IOException { - when(edrStore.resolveByTransferProcess(anyString())).thenReturn(StoreResult.success(createEdr().build())); + when(edrCache.get(anyString())).thenReturn(StoreResult.success(createEdr().build())); when(mockedTokenService.createToken(anyMap(), anyString())).thenReturn(Result.success(TokenRepresentation.Builder.newInstance().token("foo-auth-token").build())); when(mockedHttpClient.execute(any())).thenThrow(new IOException("test exception")); @@ -178,17 +179,17 @@ void refresh_ioException() throws IOException { @Test void refresh_accessTokenIsNotJwt() { - when(edrStore.resolveByTransferProcess(anyString())).thenReturn(StoreResult.success(createEdr().property("authorization", "not-jwt").build())); + when(edrCache.get(anyString())).thenReturn(StoreResult.success(createEdr().property(PROPERTY_AUTHORIZATION, "not-jwt").build())); assertThat(tokenRefreshHandler.refreshToken("token-id")).isFailed() - .detail().startsWith("Failed to parse string claim 'iss'"); + .detail().startsWith("Could not execute token refresh: Failed to parse string claim 'iss'"); } @Test void refresh_tokenGenerationFailed() { - when(edrStore.resolveByTransferProcess(anyString())).thenReturn(StoreResult.success(createEdr().build())); + when(edrCache.get(anyString())).thenReturn(StoreResult.success(createEdr().build())); when(mockedTokenService.createToken(anyMap(), anyString())).thenReturn(Result.failure("foobar")); assertThat(tokenRefreshHandler.refreshToken("token-id")).isFailed() - .detail().isEqualTo("foobar"); + .detail().isEqualTo("Could not execute token refresh: foobar"); } @NotNull @@ -206,9 +207,9 @@ private Response createResponse(Object responseBodyObject, int statusCode, Strin private DataAddress.Builder createEdr() { return DataAddress.Builder.newInstance() .type("HttpData") - .property("authorization", createJwt()) - .property("refreshToken", "foo-refresh-token") - .property("refreshEndpoint", REFRESH_ENDPOINT); + .property(PROPERTY_AUTHORIZATION, createJwt()) + .property(PROPERTY_REFRESH_TOKEN, "foo-refresh-token") + .property(PROPERTY_REFRESH_ENDPOINT, REFRESH_ENDPOINT); } private static class InvalidEdrProvider implements ArgumentsProvider { diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/tx/ParticipantEdrApi.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/tx/ParticipantEdrApi.java index 2a06eb038..ce717fc23 100644 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/tx/ParticipantEdrApi.java +++ b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/tx/ParticipantEdrApi.java @@ -21,6 +21,7 @@ import io.restassured.response.ValidatableResponse; import io.restassured.specification.RequestSpecification; +import jakarta.json.Json; import jakarta.json.JsonArray; import jakarta.json.JsonObject; import org.eclipse.edc.spi.types.domain.edr.EndpointDataReference; @@ -33,9 +34,13 @@ import static io.restassured.http.ContentType.JSON; import static jakarta.json.Json.createObjectBuilder; import static org.assertj.core.api.Assertions.assertThat; +import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.CONTEXT; import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.ID; +import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.TYPE; +import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.VOCAB; import static org.eclipse.edc.jsonld.spi.PropertyAndTypeNames.ODRL_ASSIGNER_ATTRIBUTE; import static org.eclipse.edc.jsonld.spi.PropertyAndTypeNames.ODRL_TARGET_ATTRIBUTE; +import static org.eclipse.edc.spi.CoreConstants.EDC_NAMESPACE; import static org.eclipse.tractusx.edc.helpers.CatalogHelperFunctions.getDatasetContractId; import static org.eclipse.tractusx.edc.helpers.CatalogHelperFunctions.getDatasetFirstPolicy; import static org.eclipse.tractusx.edc.helpers.EdrNegotiationHelperFunctions.createEdrNegotiationRequest; @@ -102,6 +107,32 @@ public ValidatableResponse getEdrRequest(String transferProcessId) { .then(); } + /** + * Get the cached EDR for a transfer process as {@link ValidatableResponse} + * + * @param transferProcessId The transfer process id + * @return The {@link ValidatableResponse} + */ + public ValidatableResponse getEdrRequestV2(String transferProcessId, boolean autoRefresh) { + return baseEdrRequest() + .when() + .get("/v2/edrs/{id}/dataaddress?auto_refresh={auto_refresh}", transferProcessId, autoRefresh) + .then() + .log().ifError(); + + } + + /** + * Triggers the explicit renewal of an EDR identified by {@code transferProcessId} + */ + public ValidatableResponse refreshEdr(String transferProcessId) { + return baseEdrRequest() + .when() + .post("/v2/edrs/{id}/refresh", transferProcessId) + .then() + .log().ifError(); + } + /** * Start an EDR negotiation using the EDRs API. * @@ -186,6 +217,22 @@ public JsonArray getEdrEntriesByAssetId(String assetId) { .as(JsonArray.class); } + /** + * Creates a query spec as JSON object that can be passed into the new EDR-V2 API (/request). Not yet used + */ + private String createQuery(String leftOp, String op, String rightOp) { + return Json.createObjectBuilder() + .add(CONTEXT, Json.createObjectBuilder().add(VOCAB, EDC_NAMESPACE).build()) + .add(TYPE, "QuerySpec") + .add("filterExpression", Json.createObjectBuilder() + .add("operandLeft", leftOp) + .add("operator", op) + .add("operandRight", rightOp) + .build()) + .build() + .toString(); + } + private RequestSpecification baseEdrRequest() { return participant.getManagementEndpoint().baseRequest().contentType(JSON); } diff --git a/edc-tests/edc-controlplane/edr-tests/build.gradle.kts b/edc-tests/edc-controlplane/edr-tests/build.gradle.kts new file mode 100644 index 000000000..1f8de78d9 --- /dev/null +++ b/edc-tests/edc-controlplane/edr-tests/build.gradle.kts @@ -0,0 +1,51 @@ +/******************************************************************************** + * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +plugins { + `java-library` + `java-test-fixtures` +} + +dependencies { + testImplementation(project(":spi:edr-spi")) + testImplementation(project(":edc-extensions:edr:edr-api")) + testImplementation(project(":spi:core-spi")) + testImplementation(project(":spi:tokenrefresh-spi")) + + testImplementation(testFixtures(libs.edc.api.management.test.fixtures)) + testImplementation(libs.edc.spi.edrstore) + testImplementation(libs.edc.identity.trust.sts.embedded) + testImplementation(libs.netty.mockserver) + testImplementation(libs.edc.core.token) + testImplementation(libs.edc.junit) + testImplementation(libs.restAssured) + + testCompileOnly(project(":edc-tests:runtime:runtime-memory")) + + testFixturesImplementation(libs.junit.jupiter.api) + testFixturesImplementation(libs.edc.spi.core) + testFixturesImplementation(libs.edc.junit) + testFixturesImplementation(libs.edc.spi.policy) + testFixturesImplementation(libs.edc.spi.contract) +} + +// do not publish +edcBuild { + publish.set(false) +} diff --git a/edc-tests/edc-controlplane/edr-tests/src/test/java/org/eclipse/tractusx/edc/tests/CatalogHelperFunctions.java b/edc-tests/edc-controlplane/edr-tests/src/test/java/org/eclipse/tractusx/edc/tests/CatalogHelperFunctions.java new file mode 100644 index 000000000..45563f1a0 --- /dev/null +++ b/edc-tests/edc-controlplane/edr-tests/src/test/java/org/eclipse/tractusx/edc/tests/CatalogHelperFunctions.java @@ -0,0 +1,76 @@ +/******************************************************************************** + * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +package org.eclipse.tractusx.edc.tests; + +import jakarta.json.Json; +import jakarta.json.JsonArray; +import jakarta.json.JsonObject; +import jakarta.json.JsonValue; +import org.eclipse.edc.connector.contract.spi.ContractId; + +import static org.eclipse.edc.catalog.spi.CatalogRequest.CATALOG_REQUEST_QUERY_SPEC; +import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.ID; +import static org.eclipse.edc.jsonld.spi.PropertyAndTypeNames.ODRL_POLICY_ATTRIBUTE; +import static org.eclipse.edc.spi.CoreConstants.EDC_NAMESPACE; + +public class CatalogHelperFunctions { + + + public static JsonObject createCatalogRequest(JsonObject query, String dspEndpoint) { + var jsonBuilder = Json.createObjectBuilder(); + jsonBuilder.add("@type", "CatalogRequest"); + jsonBuilder.add(EDC_NAMESPACE + "counterPartyAddress", dspEndpoint); + jsonBuilder.add(EDC_NAMESPACE + "protocol", "dataspace-protocol-http"); + + if (query != null) { + jsonBuilder.add(CATALOG_REQUEST_QUERY_SPEC, query); + } + return jsonBuilder.build(); + } + + public static ContractId getDatasetContractId(JsonObject dataset) { + var id = dataset.getJsonArray(ODRL_POLICY_ATTRIBUTE).get(0).asJsonObject().getString(ID); + return ContractId.parseId(id).orElseThrow(f -> new RuntimeException(f.getFailureDetail())); + } + + public static String getDatasetAssetId(JsonObject dataset) { + return getDatasetContractId(dataset).assetIdPart(); + } + + public static String getDatasetAssetId(JsonValue dataset) { + return getDatasetContractId(dataset.asJsonObject()).assetIdPart(); + } + + public static JsonArray getDatasetPolicies(JsonObject dataset) { + return dataset.getJsonArray(ODRL_POLICY_ATTRIBUTE); + } + + public static JsonObject getDatasetFirstPolicy(JsonObject dataset) { + return dataset.getJsonArray(ODRL_POLICY_ATTRIBUTE).stream().findFirst().get().asJsonObject(); + } + + public static JsonObject getDatasetFirstPolicy(JsonValue dataset) { + return getDatasetFirstPolicy(dataset.asJsonObject()); + } + + public static JsonArray getDatasetPolicies(JsonValue dataset) { + return getDatasetPolicies(dataset.asJsonObject()); + } +} diff --git a/edc-tests/edc-controlplane/edr-tests/src/test/java/org/eclipse/tractusx/edc/tests/EdrNegotiationHelperFunctions.java b/edc-tests/edc-controlplane/edr-tests/src/test/java/org/eclipse/tractusx/edc/tests/EdrNegotiationHelperFunctions.java new file mode 100644 index 000000000..642584ae9 --- /dev/null +++ b/edc-tests/edc-controlplane/edr-tests/src/test/java/org/eclipse/tractusx/edc/tests/EdrNegotiationHelperFunctions.java @@ -0,0 +1,68 @@ +/******************************************************************************** + * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +package org.eclipse.tractusx.edc.tests; + +import jakarta.json.Json; +import jakarta.json.JsonArray; +import jakarta.json.JsonArrayBuilder; +import jakarta.json.JsonObject; +import org.eclipse.edc.jsonld.TitaniumJsonLd; +import org.eclipse.edc.jsonld.spi.JsonLd; +import org.eclipse.edc.spi.monitor.Monitor; +import org.eclipse.tractusx.edc.api.edr.dto.NegotiateEdrRequestDto; + +import java.util.Set; + +import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.TYPE; +import static org.eclipse.edc.spi.CoreConstants.EDC_NAMESPACE; +import static org.mockito.Mockito.mock; + +public class EdrNegotiationHelperFunctions { + + private static final JsonLd JSON_LD = new TitaniumJsonLd(mock(Monitor.class)); + + public static JsonObject createEdrNegotiationRequest(String connectorAddress, String providerId, String offerId, String assetId, JsonObject policy, JsonArray callbacks) { + return Json.createObjectBuilder() + .add(TYPE, NegotiateEdrRequestDto.EDR_REQUEST_DTO_TYPE) + .add(EDC_NAMESPACE + "counterPartyId", providerId) + .add(EDC_NAMESPACE + "providerId", providerId) + .add(EDC_NAMESPACE + "counterPartyAddress", connectorAddress) + .add(EDC_NAMESPACE + "protocol", "dataspace-protocol-http") + .add(EDC_NAMESPACE + "offer", Json.createObjectBuilder() + .add(EDC_NAMESPACE + "offerId", offerId) + .add(EDC_NAMESPACE + "assetId", assetId) + .add(EDC_NAMESPACE + "policy", JSON_LD.compact(policy).getContent()) + ) + .add(EDC_NAMESPACE + "callbackAddresses", callbacks) + .build(); + } + + public static JsonObject createCallback(String url, boolean transactional, Set events) { + return Json.createObjectBuilder() + .add(TYPE, EDC_NAMESPACE + "CallbackAddress") + .add(EDC_NAMESPACE + "transactional", transactional) + .add(EDC_NAMESPACE + "uri", url) + .add(EDC_NAMESPACE + "events", events + .stream() + .collect(Json::createArrayBuilder, JsonArrayBuilder::add, JsonArrayBuilder::add) + .build()) + .build(); + } +} diff --git a/edc-tests/edc-controlplane/edr-tests/src/test/java/org/eclipse/tractusx/edc/tests/Functions.java b/edc-tests/edc-controlplane/edr-tests/src/test/java/org/eclipse/tractusx/edc/tests/Functions.java new file mode 100644 index 000000000..1e20076d2 --- /dev/null +++ b/edc-tests/edc-controlplane/edr-tests/src/test/java/org/eclipse/tractusx/edc/tests/Functions.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.eclipse.tractusx.edc.tests; + +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.bouncycastle.openssl.jcajce.JcaPEMWriter; +import org.eclipse.edc.spi.EdcException; + +import java.io.IOException; +import java.io.StringWriter; +import java.security.InvalidAlgorithmParameterException; +import java.security.Key; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.NoSuchAlgorithmException; +import java.security.spec.ECGenParameterSpec; + +public class Functions { + + /** + * Returns the Pem representation of a {@link Key} + * + * @param key The input key + * @return The pem encoded key + */ + public static String toPemEncoded(Key key) { + var writer = new StringWriter(); + try (var jcaPEMWriter = new JcaPEMWriter(writer)) { + jcaPEMWriter.writeObject(key); + } catch (IOException e) { + throw new EdcException("Unable to convert private in PEM format ", e); + } + return writer.toString(); + } + + + public static KeyPair generateKeyPair() { + try { + KeyPairGenerator gen = KeyPairGenerator.getInstance("EC", new BouncyCastleProvider()); + gen.initialize(new ECGenParameterSpec("secp256r1")); + return gen.generateKeyPair(); + } catch (NoSuchAlgorithmException | InvalidAlgorithmParameterException e) { + throw new RuntimeException(e); + } + } +} diff --git a/edc-tests/edc-controlplane/edr-tests/src/test/java/org/eclipse/tractusx/edc/tests/MockBpnIdentityService.java b/edc-tests/edc-controlplane/edr-tests/src/test/java/org/eclipse/tractusx/edc/tests/MockBpnIdentityService.java new file mode 100644 index 000000000..c95d7297a --- /dev/null +++ b/edc-tests/edc-controlplane/edr-tests/src/test/java/org/eclipse/tractusx/edc/tests/MockBpnIdentityService.java @@ -0,0 +1,70 @@ +/******************************************************************************** + * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +package org.eclipse.tractusx.edc.tests; + +import org.eclipse.edc.spi.iam.ClaimToken; +import org.eclipse.edc.spi.iam.IdentityService; +import org.eclipse.edc.spi.iam.TokenParameters; +import org.eclipse.edc.spi.iam.TokenRepresentation; +import org.eclipse.edc.spi.iam.VerificationContext; +import org.eclipse.edc.spi.result.Result; +import org.eclipse.edc.spi.types.TypeManager; + +import java.util.Map; + +import static java.lang.String.format; + +/** + * An {@link IdentityService} that will inject the BPN claim in every token. + * Please only use in testing scenarios! + */ +public class MockBpnIdentityService implements IdentityService { + + private static final String BUSINESS_PARTNER_NUMBER_CLAIM = "BusinessPartnerNumber"; + private final String businessPartnerNumber; + private final TypeManager typeManager = new TypeManager(); + + public MockBpnIdentityService(String businessPartnerNumber) { + this.businessPartnerNumber = businessPartnerNumber; + } + + @Override + public Result obtainClientCredentials(TokenParameters parameters) { + var token = Map.of(BUSINESS_PARTNER_NUMBER_CLAIM, businessPartnerNumber); + + var tokenRepresentation = TokenRepresentation.Builder.newInstance() + .token(typeManager.writeValueAsString(token)) + .build(); + return Result.success(tokenRepresentation); + } + + @Override + public Result verifyJwtToken(TokenRepresentation tokenRepresentation, VerificationContext verificationContext) { + + var token = typeManager.readValue(tokenRepresentation.getToken(), Map.class); + if (token.containsKey(BUSINESS_PARTNER_NUMBER_CLAIM)) { + return Result.success(ClaimToken.Builder.newInstance() + .claim(BUSINESS_PARTNER_NUMBER_CLAIM, token.get(BUSINESS_PARTNER_NUMBER_CLAIM)) + .build()); + } + return Result.failure(format("Expected %s claim, but token did not contain them", BUSINESS_PARTNER_NUMBER_CLAIM)); + } + +} diff --git a/edc-tests/edc-controlplane/edr-tests/src/test/java/org/eclipse/tractusx/edc/tests/ParticipantEdrApi.java b/edc-tests/edc-controlplane/edr-tests/src/test/java/org/eclipse/tractusx/edc/tests/ParticipantEdrApi.java new file mode 100644 index 000000000..8b9ce4212 --- /dev/null +++ b/edc-tests/edc-controlplane/edr-tests/src/test/java/org/eclipse/tractusx/edc/tests/ParticipantEdrApi.java @@ -0,0 +1,206 @@ +/******************************************************************************** + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +package org.eclipse.tractusx.edc.tests; + +import io.restassured.response.ValidatableResponse; +import io.restassured.specification.RequestSpecification; +import jakarta.json.Json; +import jakarta.json.JsonArray; +import jakarta.json.JsonObject; + +import static io.restassured.http.ContentType.JSON; +import static jakarta.json.Json.createObjectBuilder; +import static org.assertj.core.api.Assertions.assertThat; +import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.CONTEXT; +import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.ID; +import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.TYPE; +import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.VOCAB; +import static org.eclipse.edc.jsonld.spi.PropertyAndTypeNames.ODRL_ASSIGNER_ATTRIBUTE; +import static org.eclipse.edc.jsonld.spi.PropertyAndTypeNames.ODRL_TARGET_ATTRIBUTE; +import static org.eclipse.edc.spi.CoreConstants.EDC_NAMESPACE; +import static org.eclipse.tractusx.edc.tests.CatalogHelperFunctions.getDatasetContractId; +import static org.eclipse.tractusx.edc.tests.CatalogHelperFunctions.getDatasetFirstPolicy; +import static org.eclipse.tractusx.edc.tests.EdrNegotiationHelperFunctions.createEdrNegotiationRequest; + +/** + * E2E test helper for the EDR APIs + */ +public class ParticipantEdrApi { + + private final TxParticipant participant; + + public ParticipantEdrApi(TxParticipant participant) { + this.participant = participant; + } + + /** + * Get the cached EDR for a transfer process + * + * @param transferProcessId The transfer process id + * @return The EDR + */ + public JsonObject getEdr(String transferProcessId) { + return getEdrRequest(transferProcessId) + .statusCode(200) + .extract() + .body() + .as(JsonObject.class); + } + + /** + * Get the cached EDR for a transfer process as {@link ValidatableResponse} + * + * @param transferProcessId The transfer process id + * @return The {@link ValidatableResponse} + */ + public ValidatableResponse getEdrRequest(String transferProcessId) { + return getEdrRequestV2(transferProcessId, false); + } + + /** + * Get the cached EDR for a transfer process as {@link ValidatableResponse} + * + * @param transferProcessId The transfer process id + * @return The {@link ValidatableResponse} + */ + public ValidatableResponse getEdrRequestV2(String transferProcessId, boolean autoRefresh) { + return baseEdrRequest() + .when() + .get("/v2/edrs/{id}/dataaddress?auto_refresh={auto_refresh}", transferProcessId, autoRefresh) + .then() + .log().ifError(); + + } + + /** + * Triggers the explicit renewal of an EDR identified by {@code transferProcessId} + */ + public ValidatableResponse refreshEdr(String transferProcessId) { + return baseEdrRequest() + .when() + .post("/v2/edrs/{id}/refresh", transferProcessId) + .then() + .log().ifError(); + } + + /** + * Start an EDR negotiation using the EDRs API. + * + * @param other The provider + * @param assetId The asset ID + * @param callbacks The callbacks + * @return The contract negotiation id + */ + public String negotiateEdr(TxParticipant other, String assetId, JsonArray callbacks) { + var dataset = participant.getDatasetForAsset(other, assetId); + assertThat(dataset).withFailMessage("Catalog received from " + other.getName() + " was empty!").isNotEmpty(); + + var policy = createObjectBuilder(getDatasetFirstPolicy(dataset)) + .add(ODRL_TARGET_ATTRIBUTE, createObjectBuilder().add(ID, dataset.get(ID))) + .add(ODRL_ASSIGNER_ATTRIBUTE, createObjectBuilder().add(ID, other.getBpn())) + .build(); + var contractId = getDatasetContractId(dataset); + + var requestBody = createEdrNegotiationRequest(other.getProtocolEndpoint().getUrl().toString(), other.getBpn(), contractId.toString(), contractId.assetIdPart(), policy, callbacks); + + + var response = baseEdrRequest() + .when() + .body(requestBody) + .post("/edrs") + .then(); + + var body = response.extract().body().asString(); + assertThat(response.extract().statusCode()).withFailMessage(body).isBetween(200, 299); + + return response.extract().jsonPath().getString(ID); + } + + /** + * Get the cached EDRs for a contract negotiation + * + * @param contractNegotiationId The contract negotiation id + * @return The EDRs + */ + public JsonArray getEdrEntriesByContractNegotiationId(String contractNegotiationId) { + return baseEdrRequest() + .when() + .get("/edrs?contractNegotiationId={contractNegotiationId}", contractNegotiationId) + .then() + .statusCode(200) + .extract() + .body() + .as(JsonArray.class); + } + + /** + * Get the cached EDRs for a contract agreement + * + * @param agreementId The contract agreement id + * @return The EDRs + */ + public JsonArray getEdrEntriesByAgreementId(String agreementId) { + return baseEdrRequest() + .when() + .get("/edrs?agreementId={agreementId}", agreementId) + .then() + .statusCode(200) + .extract() + .body() + .as(JsonArray.class); + } + + /** + * Get the cached EDRs for an asset + * + * @param assetId The asset id + * @return The EDRs + */ + public JsonArray getEdrEntriesByAssetId(String assetId) { + return baseEdrRequest() + .when() + .get("/edrs?assetId={assetId}", assetId) + .then() + .statusCode(200) + .extract() + .body() + .as(JsonArray.class); + } + + /** + * Creates a query spec as JSON object that can be passed into the new EDR-V2 API (/request). Not yet used + */ + private String createQuery(String leftOp, String op, String rightOp) { + return Json.createObjectBuilder() + .add(CONTEXT, Json.createObjectBuilder().add(VOCAB, EDC_NAMESPACE).build()) + .add(TYPE, "QuerySpec") + .add("filterExpression", Json.createObjectBuilder() + .add("operandLeft", leftOp) + .add("operator", op) + .add("operandRight", rightOp) + .build()) + .build() + .toString(); + } + + private RequestSpecification baseEdrRequest() { + return participant.getManagementEndpoint().baseRequest().contentType(JSON); + } +} diff --git a/edc-tests/edc-controlplane/edr-tests/src/test/java/org/eclipse/tractusx/edc/tests/ParticipantRuntime.java b/edc-tests/edc-controlplane/edr-tests/src/test/java/org/eclipse/tractusx/edc/tests/ParticipantRuntime.java new file mode 100644 index 000000000..7c4a56628 --- /dev/null +++ b/edc-tests/edc-controlplane/edr-tests/src/test/java/org/eclipse/tractusx/edc/tests/ParticipantRuntime.java @@ -0,0 +1,108 @@ +/******************************************************************************** + * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +package org.eclipse.tractusx.edc.tests; + +import com.nimbusds.jose.JOSEException; +import com.nimbusds.jose.jwk.Curve; +import com.nimbusds.jose.jwk.gen.ECKeyGenerator; +import org.eclipse.edc.iam.identitytrust.sts.embedded.EmbeddedSecureTokenService; +import org.eclipse.edc.identitytrust.SecureTokenService; +import org.eclipse.edc.junit.extensions.EdcRuntimeExtension; +import org.eclipse.edc.spi.iam.AudienceResolver; +import org.eclipse.edc.spi.iam.IdentityService; +import org.eclipse.edc.spi.security.Vault; +import org.eclipse.edc.spi.system.ServiceExtension; +import org.eclipse.edc.spi.system.ServiceExtensionContext; +import org.eclipse.edc.spi.system.injection.InjectionContainer; +import org.eclipse.edc.spi.types.domain.message.RemoteMessage; +import org.eclipse.edc.token.JwtGenerationService; +import org.junit.jupiter.api.extension.AfterAllCallback; +import org.junit.jupiter.api.extension.BeforeAllCallback; +import org.junit.jupiter.api.extension.ExtensionContext; + +import java.time.Clock; +import java.time.Duration; +import java.util.List; +import java.util.Map; + +import static org.eclipse.tractusx.edc.tests.Functions.generateKeyPair; +import static org.eclipse.tractusx.edc.tests.Functions.toPemEncoded; + + +public class ParticipantRuntime extends EdcRuntimeExtension implements BeforeAllCallback, AfterAllCallback { + + + private final Map properties; + + public ParticipantRuntime(String moduleName, String runtimeName, String bpn, Map properties) { + super(moduleName, runtimeName, properties); + this.properties = properties; + this.registerServiceMock(IdentityService.class, new MockBpnIdentityService(bpn)); + this.registerServiceMock(AudienceResolver.class, RemoteMessage::getCounterPartyAddress); + var kid = properties.get("edc.iam.issuer.id") + "#key-1"; + try { + var runtimeKeyPair = new ECKeyGenerator(Curve.P_256).keyID(kid).generate(); + var privateKey = runtimeKeyPair.toPrivateKey(); + + registerServiceMock(SecureTokenService.class, new EmbeddedSecureTokenService(new JwtGenerationService(), () -> privateKey, () -> kid, Clock.systemUTC(), Duration.ofMinutes(10).toMillis())); + } catch (JOSEException e) { + throw new RuntimeException(e); + } + } + + @Override + public void beforeTestExecution(ExtensionContext extensionContext) { + //do nothing - we only want to start the runtime once + } + + @Override + public void afterTestExecution(ExtensionContext context) { + } + + @Override + public void beforeAll(ExtensionContext context) throws Exception { + //only run this once + super.beforeTestExecution(context); + } + + @Override + public void afterAll(ExtensionContext context) throws Exception { + super.afterTestExecution(context); + } + + @Override + protected void bootExtensions(ServiceExtensionContext context, List> serviceExtensions) { + super.bootExtensions(context, serviceExtensions); + registerConsumerPullKeys(properties); + } + + private void registerConsumerPullKeys(Map properties) { + var privateAlias = properties.get("edc.transfer.proxy.token.signer.privatekey.alias"); + var publicAlias = properties.get("edc.transfer.proxy.token.verifier.publickey.alias"); + + if (privateAlias != null && publicAlias != null) { + var keyPair = generateKeyPair(); + var vault = getContext().getService(Vault.class); + vault.storeSecret(privateAlias, toPemEncoded(keyPair.getPrivate())); + vault.storeSecret(publicAlias, toPemEncoded(keyPair.getPublic())); + } + } + +} diff --git a/edc-tests/edc-controlplane/edr-tests/src/test/java/org/eclipse/tractusx/edc/tests/TxParticipant.java b/edc-tests/edc-controlplane/edr-tests/src/test/java/org/eclipse/tractusx/edc/tests/TxParticipant.java new file mode 100644 index 000000000..7dc118c70 --- /dev/null +++ b/edc-tests/edc-controlplane/edr-tests/src/test/java/org/eclipse/tractusx/edc/tests/TxParticipant.java @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.eclipse.tractusx.edc.tests; + +import com.fasterxml.jackson.annotation.JsonCreator; +import org.eclipse.edc.test.system.utils.Participant; + +import java.net.URI; +import java.time.Duration; +import java.util.HashMap; +import java.util.Map; + +import static java.time.Duration.ofSeconds; +import static org.eclipse.edc.junit.testfixtures.TestUtils.getFreePort; + +public class TxParticipant extends Participant { + public static final String API_KEY = "testkey"; + private static final Duration ASYNC_TIMEOUT = ofSeconds(60); + private static final Duration ASYNC_POLL_INTERVAL = ofSeconds(1); + + private final URI controlPlaneDefault = URI.create("http://localhost:" + getFreePort()); + private final URI controlPlaneControl = URI.create("http://localhost:" + getFreePort() + "/control"); + private final URI backendProviderProxy = URI.create("http://localhost:" + getFreePort() + "/events"); + private final URI dataPlaneProxy = URI.create("http://localhost:" + getFreePort()); + private final URI dataPlanePublic = URI.create("http://localhost:" + getFreePort() + "/public"); + + private ParticipantEdrApi edrs; + + public String getBpn() { + return getId(); + } + + /** + * Returns the base configuration + */ + public Map getConfiguration() { + return new HashMap<>() { + { + put("edc.connector.name", name); + put("edc.participant.id", id); + put("web.http.port", String.valueOf(controlPlaneDefault.getPort())); + put("web.http.path", "/api"); + put("web.http.protocol.port", String.valueOf(protocolEndpoint.getUrl().getPort())); + put("web.http.protocol.path", protocolEndpoint.getUrl().getPath()); + put("web.http.management.port", String.valueOf(managementEndpoint.getUrl().getPort())); + put("web.http.management.path", managementEndpoint.getUrl().getPath()); + put("web.http.control.port", String.valueOf(controlPlaneControl.getPort())); + put("web.http.control.path", controlPlaneControl.getPath()); + put("edc.dsp.callback.address", protocolEndpoint.getUrl().toString()); + put("edc.api.auth.key", "testkey"); + put("web.http.public.path", "/api/public"); + put("web.http.public.port", String.valueOf(dataPlanePublic.getPort())); + put("edc.transfer.proxy.token.signer.privatekey.alias", "private-key"); + put("edc.transfer.proxy.token.verifier.publickey.alias", "public-key"); + put("edc.transfer.send.retry.limit", "1"); + put("edc.transfer.send.retry.base-delay.ms", "100"); + put("tx.dpf.consumer.proxy.port", String.valueOf(dataPlaneProxy.getPort())); + put("edc.dataplane.token.validation.endpoint", controlPlaneControl + "/token"); + put("edc.dataplane.selector.httpplane.url", controlPlaneControl.toString()); + put("edc.dataplane.selector.httpplane.sourcetypes", "HttpData"); + put("edc.dataplane.selector.httpplane.destinationtypes", "HttpProxy"); + put("edc.dataplane.selector.httpplane.properties", "{\"publicApiUrl\":\"http://localhost:" + dataPlanePublic.getPort() + "/api/public\"}"); + put("edc.receiver.http.dynamic.endpoint", "http://localhost:" + controlPlaneDefault.getPort() + "/api/consumer/datareference"); + put("tractusx.businesspartnervalidation.log.agreement.validation", "true"); + put("edc.agent.identity.key", "BusinessPartnerNumber"); + put("edc.data.encryption.keys.alias", "test-alias"); + put("tx.dpf.proxy.gateway.aas.proxied.path", backendProviderProxy.toString()); + put("tx.dpf.proxy.gateway.aas.authorization.type", "none"); + } + }; + } + + public ParticipantEdrApi edrs() { + return edrs; + } + + public static final class Builder extends Participant.Builder { + + private Builder() { + super(new TxParticipant()); + } + + @JsonCreator + public static Builder newInstance() { + return new Builder(); + } + + @Override + public TxParticipant build() { + super.managementEndpoint(new Endpoint(URI.create("http://localhost:" + getFreePort() + "/api/management"), Map.of("x-api-key", API_KEY))); + super.protocolEndpoint(new Endpoint(URI.create("http://localhost:" + getFreePort() + "/protocol"))); + super.timeout(ASYNC_TIMEOUT); + super.build(); + + this.participant.edrs = new ParticipantEdrApi(participant); + return participant; + } + } +} diff --git a/edc-tests/edc-controlplane/edr-tests/src/test/java/org/eclipse/tractusx/edc/tests/edrv2/EdrCacheApiEndToEndTest.java b/edc-tests/edc-controlplane/edr-tests/src/test/java/org/eclipse/tractusx/edc/tests/edrv2/EdrCacheApiEndToEndTest.java new file mode 100644 index 000000000..11a408fe9 --- /dev/null +++ b/edc-tests/edc-controlplane/edr-tests/src/test/java/org/eclipse/tractusx/edc/tests/edrv2/EdrCacheApiEndToEndTest.java @@ -0,0 +1,332 @@ +/* + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.eclipse.tractusx.edc.tests.edrv2; + + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.nimbusds.jose.JOSEException; +import com.nimbusds.jose.JWSAlgorithm; +import com.nimbusds.jose.JWSHeader; +import com.nimbusds.jose.crypto.ECDSASigner; +import com.nimbusds.jose.jwk.Curve; +import com.nimbusds.jose.jwk.ECKey; +import com.nimbusds.jose.jwk.gen.ECKeyGenerator; +import com.nimbusds.jwt.JWTClaimsSet; +import com.nimbusds.jwt.SignedJWT; +import jakarta.json.JsonObject; +import org.eclipse.edc.edr.spi.store.EndpointDataReferenceStore; +import org.eclipse.edc.edr.spi.types.EndpointDataReferenceEntry; +import org.eclipse.edc.junit.annotations.EndToEndTest; +import org.eclipse.edc.spi.types.domain.DataAddress; +import org.eclipse.tractusx.edc.spi.tokenrefresh.dataplane.model.TokenResponse; +import org.eclipse.tractusx.edc.tests.ParticipantRuntime; +import org.eclipse.tractusx.edc.tests.TxParticipant; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; +import org.mockserver.client.MockServerClient; +import org.mockserver.integration.ClientAndServer; +import org.mockserver.verify.VerificationTimes; + +import java.time.Clock; +import java.time.Instant; +import java.time.ZoneId; +import java.util.HashMap; +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.eclipse.edc.junit.testfixtures.TestUtils.getFreePort; +import static org.eclipse.edc.spi.CoreConstants.EDC_NAMESPACE; +import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.TX_AUTH_NS; +import static org.mockserver.integration.ClientAndServer.startClientAndServer; +import static org.mockserver.matchers.Times.exactly; +import static org.mockserver.model.HttpRequest.request; +import static org.mockserver.model.HttpResponse.response; +import static org.mockserver.model.StringBody.exact; + +/** + * This End-To-End test spins up a consumer control plane and verifies that the EDR Cache API + * performs as expected. + * The provider data plane is mocked with a {@link ClientAndServer}. + */ +@EndToEndTest +public class EdrCacheApiEndToEndTest { + protected static final TxParticipant SOKRATES = TxParticipant.Builder.newInstance() + .name("sokrates") + .id("BPN00001") + .build(); + @RegisterExtension + protected static final ParticipantRuntime SOKRATES_RUNTIME = new ParticipantRuntime( + ":edc-tests:runtime:runtime-memory-signaling", + SOKRATES.getName(), + SOKRATES.getId(), + with(SOKRATES.getConfiguration(), Map.of("edc.iam.issuer.id", "did:web:sokrates"))); + private final ObjectMapper mapper = new ObjectMapper(); + private String refreshEndpoint; + private ClientAndServer mockedRefreshApi; + private ECKey providerSigningKey; + + protected static Map with(Map original, Map additional) { + var newMap = new HashMap<>(original); + newMap.putAll(additional); + return newMap; + } + + @BeforeEach + void setup() throws JOSEException { + providerSigningKey = new ECKeyGenerator(Curve.P_256).keyID("did:web:provider#key-1").generate(); + var port = getFreePort(); + refreshEndpoint = "http://localhost:%s/refresh".formatted(port); + mockedRefreshApi = startClientAndServer(port); + } + + @AfterEach + void teardown() { + mockedRefreshApi.stop(); + } + + @DisplayName("Verify HTTP 200 response and body when refreshing succeeds") + @Test + void getEdrWithRefresh_success() { + + try (var client = new MockServerClient("localhost", mockedRefreshApi.getPort())) { + // mock the provider dataplane's refresh endpoint + client.when(request() + .withMethod("POST") + .withPath("/refresh/token") + .withBody(exact("")), + exactly(1)) + .respond(response() + .withStatusCode(200) + .withBody(tokenResponseBody()) + ); + + storeEdr("test-id", true); + var edr = SOKRATES.edrs().getEdrRequestV2("test-id", true) + .statusCode(200) + .extract().body().as(JsonObject.class); + assertThat(edr).isNotNull(); + + // assert the correct endpoint was called + client.verify( + request() + .withQueryStringParameter("grant_type", "refresh_token") + .withMethod("POST") + .withPath("/refresh/token"), + VerificationTimes.exactly(1)); + + } + } + + @DisplayName("Verify the refresh endpoint is not called when token not yet expired") + @Test + void getEdrWithRefresh_notExpired_shouldNotCallEndpoint() { + + try (var client = new MockServerClient("localhost", mockedRefreshApi.getPort())) { + // mock the provider dataplane's refresh endpoint + + storeEdr("test-id", false); + var edr = SOKRATES.edrs().getEdrRequestV2("test-id", true) + .statusCode(200) + .extract().body().as(JsonObject.class); + assertThat(edr).isNotNull(); + + // assert the correct endpoint was called + client.verify( + request() + .withQueryStringParameter("grant_type", "refresh_token") + .withMethod("POST") + .withPath("/refresh/token"), + VerificationTimes.never()); + } + } + + @DisplayName("Verify the refresh endpoint is not called when auto_refresh=false") + @Test + void getEdrWithRefresh_whenNotAutorefresh_shouldNotCallEndpoint() { + + try (var client = new MockServerClient("localhost", mockedRefreshApi.getPort())) { + // mock the provider dataplane's refresh endpoint + + storeEdr("test-id", true); + var edr = SOKRATES.edrs() + .getEdrRequestV2("test-id", false) + .statusCode(200) + .extract().body().as(JsonObject.class); + assertThat(edr).isNotNull(); + + // assert the correct endpoint was called + client.verify( + request() + .withQueryStringParameter("grant_type", "refresh_token") + .withMethod("POST") + .withPath("/refresh/token"), + VerificationTimes.never()); + } + } + + @DisplayName("Verify HTTP 403 response when refreshing the token is not allowed") + @Test + void getEdrWithRefresh_unauthorized() { + + try (var client = new MockServerClient("localhost", mockedRefreshApi.getPort())) { + // mock the provider dataplane's refresh endpoint + client.when(request() + .withMethod("POST") + .withPath("/refresh/token") + .withBody(exact("")), + exactly(1)) + .respond(response() + .withStatusCode(401) + .withBody("unauthorized") + ); + + storeEdr("test-id", true); + SOKRATES.edrs().getEdrRequestV2("test-id", true) + .statusCode(403); + + // assert the correct endpoint was called + client.verify( + request() + .withQueryStringParameter("grant_type", "refresh_token") + .withMethod("POST") + .withPath("/refresh/token"), + VerificationTimes.exactly(1)); + } + } + + @Test + void refreshEdr() { + try (var client = new MockServerClient("localhost", mockedRefreshApi.getPort())) { + // mock the provider dataplane's refresh endpoint + client.when(request() + .withMethod("POST") + .withPath("/refresh/token") + .withBody(exact("")), + exactly(1)) + .respond(response() + .withStatusCode(200) + .withBody(tokenResponseBody()) + ); + + storeEdr("test-id", true); + var edr = SOKRATES.edrs().refreshEdr("test-id") + .statusCode(200) + .extract().body().as(JsonObject.class); + assertThat(edr).isNotNull(); + + // assert the correct endpoint was called + client.verify( + request() + .withQueryStringParameter("grant_type", "refresh_token") + .withMethod("POST") + .withPath("/refresh/token"), + VerificationTimes.exactly(1)); + + } + } + + @Test + void refreshEdr_whenNotFound() { + var edr = SOKRATES.edrs().refreshEdr("does-not-exist") + .statusCode(404); + } + + @Test + void refreshEdr_whenNotAuthorized() { + try (var client = new MockServerClient("localhost", mockedRefreshApi.getPort())) { + // mock the provider dataplane's refresh endpoint + client.when(request() + .withMethod("POST") + .withPath("/refresh/token") + .withBody(exact("")), + exactly(1)) + .respond(response() + .withStatusCode(401) + .withBody("unauthorized") + ); + + storeEdr("test-id", true); + SOKRATES.edrs().refreshEdr("test-id") + .statusCode(403); + + // assert the correct endpoint was called + client.verify( + request() + .withQueryStringParameter("grant_type", "refresh_token") + .withMethod("POST") + .withPath("/refresh/token"), + VerificationTimes.exactly(1)); + } + } + + private String tokenResponseBody() { + var claims = new JWTClaimsSet.Builder().claim("iss", "did:web:provider").build(); + + var accessToken = createJwt(providerSigningKey, claims); + var refreshToken = createJwt(providerSigningKey, new JWTClaimsSet.Builder().build()); + var response = new TokenResponse(accessToken, refreshToken, 300L, "bearer"); + try { + return mapper.writeValueAsString(response); + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + } + + private void storeEdr(String transferProcessId, boolean isExpired) { + var claims = new JWTClaimsSet.Builder().claim("iss", "did:web:provider").build(); + var store = SOKRATES_RUNTIME.getService(EndpointDataReferenceStore.class); + var edr = DataAddress.Builder.newInstance() + .type("test-type") + .property(EDC_NAMESPACE + "authorization", createJwt(providerSigningKey, claims)) + .property(EDC_NAMESPACE + "authType", "bearer") + .property(TX_AUTH_NS + "refreshToken", createJwt(providerSigningKey, new JWTClaimsSet.Builder().build())) + .property(TX_AUTH_NS + "expiresIn", "300") + .property(TX_AUTH_NS + "refreshEndpoint", refreshEndpoint) + .build(); + var entry = EndpointDataReferenceEntry.Builder.newInstance() + .clock(isExpired ? // defaults to an expired token + Clock.fixed(Instant.now().minusSeconds(3600), ZoneId.systemDefault()) : + Clock.systemUTC()) + .agreementId("test-agreement") + .assetId("test-asset") + .transferProcessId(transferProcessId) + .providerId("test-provider") + .contractNegotiationId("test-negotiation") + .build(); + store.save(entry, edr).orElseThrow(f -> new AssertionError(f.getFailureDetail())); + } + + + private String createJwt(ECKey signerKey, JWTClaimsSet claims) { + var header = new JWSHeader.Builder(JWSAlgorithm.ES256).keyID(signerKey.getKeyID()).build(); + var jwt = new SignedJWT(header, claims); + try { + jwt.sign(new ECDSASigner(signerKey)); + return jwt.serialize(); + } catch (JOSEException e) { + throw new RuntimeException(e); + } + } + +} diff --git a/edc-tests/runtime/runtime-memory-signaling/README.md b/edc-tests/runtime/runtime-memory-signaling/README.md new file mode 100644 index 000000000..2f9593a75 --- /dev/null +++ b/edc-tests/runtime/runtime-memory-signaling/README.md @@ -0,0 +1,3 @@ +# In-Memory Runtime for Testing Purposes + +This module provides a very small, purely in-mem runtime to execute tests against. Not intended for anything other than testing! diff --git a/edc-tests/runtime/runtime-memory-signaling/build.gradle.kts b/edc-tests/runtime/runtime-memory-signaling/build.gradle.kts new file mode 100644 index 000000000..816fe647f --- /dev/null +++ b/edc-tests/runtime/runtime-memory-signaling/build.gradle.kts @@ -0,0 +1,45 @@ +/******************************************************************************** + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +plugins { + `java-library` + id("application") +} + + +dependencies { + + // use basic (all in-mem) control plane + implementation(project(":edc-tests:runtime:runtime-memory")) + + // these extensions are used for DataPlane Signaling + Token Refresh + runtimeOnly(project(":edc-extensions:edr:edr-api-v2")) + runtimeOnly(project((":edc-extensions:tokenrefresh-handler"))) + runtimeOnly(libs.edc.edr.store.receiver) + runtimeOnly(libs.edc.core.edrstore) + +} + +application { + mainClass.set("org.eclipse.edc.boot.system.runtime.BaseRuntime") +} + +edcBuild { + publish.set(false) +} diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index fae161a3a..bb21333d1 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -16,6 +16,7 @@ jakarta-json = "2.0.1" jupiter = "5.10.2" mockwebserver = "5.0.0-alpha.12" nimbus = "9.37.3" +netty-mockserver = "5.15.0" okhttp = "4.12.0" postgres = "42.7.2" restAssured = "5.4.0" @@ -66,6 +67,7 @@ edc-core-sql = { module = "org.eclipse.edc:sql-core", version.ref = "edc" } edc-core-validator = { module = "org.eclipse.edc:validator-core", version.ref = "edc" } edc-core-transform = { module = "org.eclipse.edc:transform-core", version.ref = "edc" } edc-core-token = { module = "org.eclipse.edc:token-core", version.ref = "edc" } +edc-core-edrstore = { module = "org.eclipse.edc:edr-store-core", version.ref = "edc" } edc-statemachine = { module = "org.eclipse.edc:state-machine", version.ref = "edc" } edc-junit = { module = "org.eclipse.edc:junit", version.ref = "edc" } edc-api-management-config = { module = "org.eclipse.edc:management-api-configuration", version.ref = "edc" } @@ -154,6 +156,7 @@ edc-dpf-transferclient = { module = "org.eclipse.edc:data-plane-transfer-client" edc-dpf-selector-spi = { module = "org.eclipse.edc:data-plane-selector-spi", version.ref = "edc" } edc-dpf-selector-core = { module = "org.eclipse.edc:data-plane-selector-core", version.ref = "edc" } edc-dpf-transfer = { module = "org.eclipse.edc:transfer-data-plane", version.ref = "edc" } +edc-dpf-transfer-signaling = { module = "org.eclipse.edc:transfer-data-plane-signaling", version.ref = "edc" } edc-dpf-core = { module = "org.eclipse.edc:data-plane-core", version.ref = "edc" } edc-dpf-util = { module = "org.eclipse.edc:data-plane-util", version.ref = "edc" } @@ -173,6 +176,7 @@ edc-micrometer-jetty = { module = "org.eclipse.edc:jetty-micrometer", version.re edc-monitor-jdklogger = { module = "org.eclipse.edc:monitor-jdk-logger", version.ref = "edc" } edc-transfer-dynamicreceiver = { module = "org.eclipse.edc:transfer-pull-http-dynamic-receiver", version.ref = "edc" } edc-transfer-receiver = { module = "org.eclipse.edc:transfer-pull-http-receiver", version.ref = "edc" } +edc-edr-store-receiver = { module = "org.eclipse.edc:edr-store-receiver", version.ref = "edc" } # other deps @@ -194,6 +198,7 @@ junit-jupiter-api = { module = "org.junit.jupiter:junit-jupiter-api", version.re nimbus-jwt = { module = "com.nimbusds:nimbus-jose-jwt", version.ref = "nimbus" } okhttp = { module = "com.squareup.okhttp3:okhttp", version.ref = "okhttp" } okhttp-mockwebserver = { module = "com.squareup.okhttp3:mockwebserver", version.ref = "mockwebserver" } +netty-mockserver = { module = "org.mock-server:mockserver-netty", version.ref = "netty-mockserver" } postgres = { module = "org.postgresql:postgresql", version.ref = "postgres" } restAssured = { module = "io.rest-assured:rest-assured", version.ref = "restAssured" } slf4j-api = { module = "org.slf4j:slf4j-api", version.ref = "slf4j" } diff --git a/settings.gradle.kts b/settings.gradle.kts index 93bdd0340..379f7a43f 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -47,12 +47,13 @@ include(":edc-extensions:transferprocess-sftp-client") include(":edc-extensions:transferprocess-sftp-common") include(":edc-extensions:transferprocess-sftp-provisioner") include(":edc-extensions:edr:edr-api") +include(":edc-extensions:edr:edr-api-v2") include(":edc-extensions:edr:edr-callback") include(":edc-extensions:edr:edr-cache-sql") include(":edc-extensions:cx-policy") include(":edc-extensions:cx-policy-legacy") -include("edc-extensions:ssi:ssi-identity-core") -include("edc-extensions:ssi:ssi-miw-credential-client") +include(":edc-extensions:ssi:ssi-identity-core") +include(":edc-extensions:ssi:ssi-miw-credential-client") include(":edc-extensions:ssi:ssi-identity-extractor") include(":edc-extensions:iatp:tx-iatp") include(":edc-extensions:iatp:tx-iatp-sts-dim") @@ -68,9 +69,11 @@ include(":edc-extensions:dataplane:dataplane-token-refresh:token-refresh-api") // test modules include(":edc-tests:e2e-tests") +include(":edc-tests:edc-controlplane:edr-tests") include(":edc-tests:miw-tests") include(":edc-tests:runtime:extensions") include(":edc-tests:runtime:runtime-memory") +include(":edc-tests:runtime:runtime-memory-signaling") include(":edc-tests:runtime:dataplane-cloud") include(":edc-tests:runtime:runtime-memory-ssi") include(":edc-tests:runtime:runtime-postgresql") diff --git a/spi/core-spi/src/main/java/org/eclipse/tractusx/edc/edr/spi/CoreConstants.java b/spi/core-spi/src/main/java/org/eclipse/tractusx/edc/edr/spi/CoreConstants.java index 87ab2566f..5391a2b34 100644 --- a/spi/core-spi/src/main/java/org/eclipse/tractusx/edc/edr/spi/CoreConstants.java +++ b/spi/core-spi/src/main/java/org/eclipse/tractusx/edc/edr/spi/CoreConstants.java @@ -24,6 +24,7 @@ public final class CoreConstants { public static final String TX_PREFIX = "tx"; public static final String TX_NAMESPACE = "https://w3id.org/tractusx/v0.0.1/ns/"; public static final String TX_CONTEXT = "https://w3id.org/tractusx/edc/v0.0.1"; + public static final String TX_AUTH_NS = "https://w3id.org/tractusx/auth/"; public static final String EDC_CONTEXT = "https://w3id.org/edc/v0.0.1"; public static final String CX_CREDENTIAL_NS = "https://w3id.org/catenax/credentials/"; public static final String CX_POLICY_NS = "https://w3id.org/catenax/policy/"; diff --git a/spi/tokenrefresh-spi/src/main/java/org/eclipse/tractusx/edc/spi/tokenrefresh/common/TokenRefreshHandler.java b/spi/tokenrefresh-spi/src/main/java/org/eclipse/tractusx/edc/spi/tokenrefresh/common/TokenRefreshHandler.java index bbfa871ef..d2c84bfba 100644 --- a/spi/tokenrefresh-spi/src/main/java/org/eclipse/tractusx/edc/spi/tokenrefresh/common/TokenRefreshHandler.java +++ b/spi/tokenrefresh-spi/src/main/java/org/eclipse/tractusx/edc/spi/tokenrefresh/common/TokenRefreshHandler.java @@ -19,13 +19,12 @@ package org.eclipse.tractusx.edc.spi.tokenrefresh.common; -import org.eclipse.edc.spi.result.Result; -import org.eclipse.tractusx.edc.spi.tokenrefresh.dataplane.model.TokenResponse; +import org.eclipse.edc.spi.result.ServiceResult; +import org.eclipse.edc.spi.types.domain.DataAddress; /** * Handles token refreshing against an OAuth2-compliant token refresh endpoint. */ -@FunctionalInterface public interface TokenRefreshHandler { /** * Refreshes a token identified by the token ID and returns the updated token. If tokens are kept in persistent storage or @@ -34,5 +33,15 @@ public interface TokenRefreshHandler { * @param tokenId The ID of the token, e.g. a {@code jti} claim in JWT tokens. * @return An updated access+refresh token pair. */ - Result refreshToken(String tokenId); + ServiceResult refreshToken(String tokenId); + + /** + * Refreshes a token identified by the token ID and returns the updated token. If tokens are kept in persistent storage or + * a HSM, implementors must update that entry. + * + * @param tokenId The ID of the token, e.g. a {@code jti} claim in JWT tokens. + * @param edr The {@link DataAddress} containing the EDR + * @return An updated access+refresh token pair. + */ + ServiceResult refreshToken(String tokenId, DataAddress edr); } From 19c7866ffd346a9ef5949fdc84d38cdf401ea299 Mon Sep 17 00:00:00 2001 From: Paul Latzelsperger <43503240+paullatzelsperger@users.noreply.github.com> Date: Wed, 20 Mar 2024 21:22:24 +0100 Subject: [PATCH 060/100] refactor: code base now uses DPS (#1146) * remove provider dataplane proxy * remove old edr api * re-enable callbacks * introduce fixtures module * introduce fixtures module * introduce controlplane test modules * http pull transfer w/ signaling * split tests * fix negotiate edr test * get http push to work * rename edr-test edr-api-test * added policy tests * cleanup * transfer type in SSI/DIM/IATP tests * iatp test * fix DIM tests * add legacy SSI tests * compile errors * DEPENDENCIES * add SQL migration for DataAddress change * temporarily made DIM and TokenRefresh config optional * fix MIW e2e tests --- .github/workflows/verify.yaml | 8 +- DEPENDENCIES | 8 +- core/core-utils/build.gradle.kts | 1 + .../core/utils/RequiredConfigWarnings.java | 29 ++ .../edc/edr/core/manager/EdrManagerImpl.java | 14 +- .../edr/core/manager/EdrManagerImplTest.java | 19 +- .../edc-controlplane-base/build.gradle.kts | 9 +- .../build.gradle.kts | 2 - .../build.gradle.kts | 2 - .../build.gradle.kts | 1 - .../edc-dataplane-base/build.gradle.kts | 3 - .../build.gradle.kts | 1 - .../edc/data/encryption/ArrayUtil.java | 44 --- .../data/encryption/TxEncryptorExtension.java | 78 ----- .../edc/data/encryption/aes/AesEncryptor.java | 147 -------- .../encryption/TxEncryptorExtensionTest.java | 84 ----- .../data/encryption/aes/AesEncryptorTest.java | 127 ------- .../asset/ConsumerAssetRequestController.java | 1 - .../README.md | 26 -- .../DataPlaneProxyProviderApiExtension.java | 122 ------- .../api/gateway/ProviderGatewayApi.java | 43 --- .../gateway/ProviderGatewayController.java | 253 -------------- .../provider/api/response/ResponseHelper.java | 49 --- .../ProxyProviderDataAddressResolver.java | 72 ---- ...rg.eclipse.edc.spi.system.ServiceExtension | 20 -- ...ataPlaneProxyProviderApiExtensionTest.java | 119 ------- .../ProxyProviderDataAddressResolverTest.java | 87 ----- .../api/response/ResponseHelperTest.java | 37 -- .../README.md | 13 - .../core/ProxyProviderCoreExtension.java | 91 ----- .../GatewayConfigurationLoader.java | 57 --- ...rg.eclipse.edc.spi.system.ServiceExtension | 20 -- .../AuthorizationHandlerRegistryImplTest.java | 37 -- .../GatewayConfigurationLoaderTest.java | 57 --- .../GatewayConfigurationRegistryImplTest.java | 36 -- .../authorization/AuthorizationExtension.java | 39 --- .../authorization/AuthorizationHandler.java | 38 -- .../configuration/GatewayConfiguration.java | 107 ------ .../GatewayConfigurationRegistry.java | 40 --- ...SelectorConfigurationServiceExtension.java | 64 ++-- ...ationServiceExtensionEdcExtensionTest.java | 161 --------- ...ctorConfigurationServiceExtensionTest.java | 193 ++++------- ...DataPlaneTokenRefreshServiceExtension.java | 9 +- .../DataPlaneTokenRefreshServiceImpl.java | 34 +- ...eTokenRefreshServiceImplComponentTest.java | 1 + .../DataPlaneTokenRefreshServiceImplTest.java | 2 +- .../callback/ContractNegotiationCallback.java | 2 +- .../TransferProcessLocalCallback.java | 8 +- .../TransferProcessLocalCallbackTest.java | 21 +- .../dim/DimSecureTokenServiceExtension.java | 16 +- .../sts/dim/DimStsConfigurationExtension.java | 23 +- .../dim/DimSecureServiceExtensionTest.java | 9 +- .../dim/DimStsConfigurationExtensionTest.java | 6 +- ...lter_TransferProcess_InlineDataAddress.sql | 28 ++ .../AdditionalHeadersProvisioner.java | 17 +- ...nalHeadersResourceDefinitionGenerator.java | 4 +- ...eadersResourceDefinitionGeneratorTest.java | 26 +- .../tokenrefresh-handler/build.gradle.kts | 1 + .../TokenRefreshHandlerExtension.java | 7 +- ...oviderResourceDefinitionGeneratorTest.java | 9 +- edc-tests/e2e-tests/build.gradle.kts | 1 - .../edc/helpers/CatalogHelperFunctions.java | 31 -- .../ContractDefinitionHelperFunctions.java | 47 --- .../ContractNegotiationHelperFunctions.java | 47 --- .../EdrNegotiationHelperFunctions.java | 74 ---- .../edc/helpers/PolicyHelperFunctions.java | 2 - .../TransferProcessHelperFunctions.java | 17 - .../edc/lifecycle/tx/ParticipantDataApi.java | 89 +---- .../edc/lifecycle/tx/ParticipantEdrApi.java | 179 +--------- .../edc/lifecycle/tx/TxParticipant.java | 5 +- .../edc/tests/edr/AbstractDeleteEdrTest.java | 102 ------ .../edc/tests/edr/AbstractRenewalEdrTest.java | 183 ---------- .../edc/tests/edr/DeleteEdrInMemoryTest.java | 63 ---- .../tests/edr/DeleteEdrPostgresqlTest.java | 44 --- ...otiateEdrPostgresqlHashicorpVaultTest.java | 48 --- .../tests/edr/NegotiateEdrPostgresqlTest.java | 44 --- .../edc/tests/edr/RenewalEdrInMemoryTest.java | 63 ---- .../tests/edr/RenewalEdrPostgresqlTest.java | 44 --- .../tractusx/edc/tests/edr/TestFunctions.java | 45 --- .../proxy/AbstractDataPlaneProxyTest.java | 328 ------------------ .../proxy/DataPlaneProxyInMemoryTest.java | 62 ---- .../proxy/DataPlaneProxyPostgresqlTest.java | 43 --- .../catalog-tests}/build.gradle.kts | 15 +- .../tests/catalog/AbstractCatalogTest.java | 24 +- .../tests/catalog/CatalogInMemoryTest.java | 2 +- .../tests/catalog/CatalogPostgresqlTest.java | 2 +- .../edr-api-tests}/build.gradle.kts | 13 +- .../edrv2}/AbstractNegotiateEdrTest.java | 49 ++- .../tests/edrv2/EdrCacheApiEndToEndTest.java | 12 +- .../edrv2}/NegotiateEdrInMemoryTest.java | 10 +- .../fixtures/build.gradle.kts | 63 ++++ .../edc/tests/IdentityParticipant.java | 68 ++++ .../edc/tests/MockBpnIdentityService.java | 0 .../edc/tests/ParticipantDataApi.java | 56 +++ .../tractusx/edc/tests/ParticipantEdrApi.java | 24 +- .../edc/tests/TestRuntimeConfiguration.java | 25 +- .../tractusx/edc/tests/TxParticipant.java | 62 +++- .../helpers}/CatalogHelperFunctions.java | 8 +- .../EdrNegotiationHelperFunctions.java | 21 +- .../edc/tests/helpers}/Functions.java | 36 +- .../tests/helpers/PolicyHelperFunctions.java | 205 +++++++++++ .../tests}/helpers/QueryHelperFunctions.java | 2 +- .../edc/tests/helpers/ReceivedEvent.java | 49 ++- .../edc/tests/runtimes/DataWiper.java | 84 +++++ .../tractusx/edc/tests/runtimes/KeyPool.java | 36 ++ .../tests/runtimes}/ParticipantRuntime.java | 39 ++- .../tests/runtimes/PgParticipantRuntime.java | 130 +++++++ .../build.gradle.kts | 29 +- ...AbstractHttpConsumerPullWithProxyTest.java | 41 ++- ...HttpConsumerPullWithProxyInMemoryTest.java | 33 +- ...HttpConsumerPullWithProxyInMemoryTest.java | 69 ++-- .../transfer/iatp/IatpDimParticipant.java | 28 +- .../tests/transfer/iatp/IatpParticipant.java | 141 ++++++++ .../iatp/dispatchers}/DimDispatcher.java | 8 +- .../iatp/dispatchers/KeycloakDispatcher.java | 56 +++ .../iatp/harness/DataspaceIssuer.java | 180 ++++++++++ .../iatp/harness/DidExampleResolver.java | 59 ++++ .../iatp/harness/IatpHelperFunctions.java | 132 +++++++ .../iatp/harness/SecureTokenService.java | 89 +++++ .../iatp/runtime/IatpParticipantRuntime.java | 90 +++++ .../policy-tests}/build.gradle.kts | 23 +- .../policy/AbstractPolicyMonitorTest.java | 14 +- .../policy/PolicyMonitorInMemoryTest.java | 2 +- .../policy/PolicyMonitorPostgresqlTest.java | 2 +- .../ssi-summarycred-tests/build.gradle.kts | 41 +++ .../edc/tests}/KeycloakDispatcher.java | 4 +- .../tractusx/edc/tests}/MiwDispatcher.java | 4 +- .../tractusx/edc/tests/SsiParticipant.java | 67 ++++ .../AbstractContractNegotiateTest.java | 28 +- .../SsiContractNegotiationInMemoryTest.java | 23 +- ...AbstractHttpConsumerPullWithProxyTest.java | 145 ++++++++ ...HttpConsumerPullWithProxyInMemoryTest.java | 34 +- .../src/test/resources/framework-policy.json | 24 ++ .../resources/summary-vc-no-dismantler.json | 37 ++ .../src/test/resources/summary-vc.json | 38 ++ .../transfer-tests}/build.gradle.kts | 23 +- ...AbstractHttpConsumerPullWithProxyTest.java | 127 +++++++ .../AbstractHttpProviderPushTest.java | 16 +- ...HttpConsumerPullWithProxyInMemoryTest.java | 2 +- ...tpConsumerPullWithProxyPostgresqlTest.java | 2 +- .../HttpProviderPushInMemoryTest.java | 2 +- .../HttpProviderPushInPostgresqlTest.java | 2 +- .../TransferProcessHelperFunctions.java} | 38 +- .../edc-dataplane-proxy-e2e/build.gradle.kts | 44 --- .../proxy/e2e/DpfProxyEndToEndTest.java | 209 ----------- .../dataplane/proxy/e2e/EdrCacheSetup.java | 110 ------ .../dataplane/proxy/e2e/KeyStoreSetup.java | 50 --- edc-tests/miw-tests/build.gradle.kts | 2 +- edc-tests/runtime/extensions/build.gradle.kts | 2 - .../ConsumerEdrHandlerController.java | 65 ---- .../lifecycle/ConsumerServicesExtension.java | 38 -- ...rg.eclipse.edc.spi.system.ServiceExtension | 1 - .../runtime-memory-iatp-ih/build.gradle.kts | 1 + .../iatp/runtime-memory-sts/build.gradle.kts | 3 + .../SecureTokenServiceExtension.java | 57 +++ ...rg.eclipse.edc.spi.system.ServiceExtension | 3 +- .../runtime-memory-signaling/build.gradle.kts | 7 - .../runtime-memory-ssi/build.gradle.kts | 2 +- .../runtime/runtime-memory/build.gradle.kts | 4 + .../runtime-postgresql/build.gradle.kts | 1 + gradle/libs.versions.toml | 5 +- samples/multi-tenancy/build.gradle.kts | 6 + settings.gradle.kts | 16 +- 163 files changed, 2693 insertions(+), 4764 deletions(-) create mode 100644 core/core-utils/src/main/java/org/eclipse/tractusx/edc/core/utils/RequiredConfigWarnings.java delete mode 100644 edc-extensions/data-encryption/src/main/java/org/eclipse/tractusx/edc/data/encryption/ArrayUtil.java delete mode 100644 edc-extensions/data-encryption/src/main/java/org/eclipse/tractusx/edc/data/encryption/TxEncryptorExtension.java delete mode 100644 edc-extensions/data-encryption/src/main/java/org/eclipse/tractusx/edc/data/encryption/aes/AesEncryptor.java delete mode 100644 edc-extensions/data-encryption/src/test/java/org/eclipse/tractusx/edc/data/encryption/TxEncryptorExtensionTest.java delete mode 100644 edc-extensions/data-encryption/src/test/java/org/eclipse/tractusx/edc/data/encryption/aes/AesEncryptorTest.java delete mode 100644 edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-api/README.md delete mode 100644 edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/api/DataPlaneProxyProviderApiExtension.java delete mode 100644 edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/api/gateway/ProviderGatewayApi.java delete mode 100644 edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/api/gateway/ProviderGatewayController.java delete mode 100644 edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/api/response/ResponseHelper.java delete mode 100644 edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/api/validation/ProxyProviderDataAddressResolver.java delete mode 100644 edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-api/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension delete mode 100644 edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-api/src/test/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/api/response/DataPlaneProxyProviderApiExtensionTest.java delete mode 100644 edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-api/src/test/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/api/response/ProxyProviderDataAddressResolverTest.java delete mode 100644 edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-api/src/test/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/api/response/ResponseHelperTest.java delete mode 100644 edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-core/README.md delete mode 100644 edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-core/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/core/ProxyProviderCoreExtension.java delete mode 100644 edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-core/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/core/gateway/configuration/GatewayConfigurationLoader.java delete mode 100644 edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-core/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension delete mode 100644 edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-core/src/test/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/core/gateway/auth/AuthorizationHandlerRegistryImplTest.java delete mode 100644 edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-core/src/test/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/core/gateway/configuration/GatewayConfigurationLoaderTest.java delete mode 100644 edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-core/src/test/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/core/gateway/configuration/GatewayConfigurationRegistryImplTest.java delete mode 100644 edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-spi/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/spi/provider/gateway/authorization/AuthorizationExtension.java delete mode 100644 edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-spi/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/spi/provider/gateway/authorization/AuthorizationHandler.java delete mode 100644 edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-spi/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/spi/provider/gateway/configuration/GatewayConfiguration.java delete mode 100644 edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-spi/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/spi/provider/gateway/configuration/GatewayConfigurationRegistry.java delete mode 100644 edc-extensions/dataplane/dataplane-selector-configuration/src/test/java/org/eclipse/tractusx/edc/dataplane/selector/configuration/DataPlaneSelectorConfigurationServiceExtensionEdcExtensionTest.java create mode 100644 edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/transferprocess/V0_0_15__Alter_TransferProcess_InlineDataAddress.sql delete mode 100644 edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/helpers/ContractDefinitionHelperFunctions.java delete mode 100644 edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/helpers/ContractNegotiationHelperFunctions.java delete mode 100644 edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/helpers/EdrNegotiationHelperFunctions.java delete mode 100644 edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/edr/AbstractDeleteEdrTest.java delete mode 100644 edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/edr/AbstractRenewalEdrTest.java delete mode 100644 edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/edr/DeleteEdrInMemoryTest.java delete mode 100644 edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/edr/DeleteEdrPostgresqlTest.java delete mode 100644 edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/edr/NegotiateEdrPostgresqlHashicorpVaultTest.java delete mode 100644 edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/edr/NegotiateEdrPostgresqlTest.java delete mode 100644 edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/edr/RenewalEdrInMemoryTest.java delete mode 100644 edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/edr/RenewalEdrPostgresqlTest.java delete mode 100644 edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/edr/TestFunctions.java delete mode 100644 edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/proxy/AbstractDataPlaneProxyTest.java delete mode 100644 edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/proxy/DataPlaneProxyInMemoryTest.java delete mode 100644 edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/proxy/DataPlaneProxyPostgresqlTest.java rename {edc-extensions/data-encryption => edc-tests/edc-controlplane/catalog-tests}/build.gradle.kts (74%) rename edc-tests/{e2e-tests => edc-controlplane/catalog-tests}/src/test/java/org/eclipse/tractusx/edc/tests/catalog/AbstractCatalogTest.java (88%) rename edc-tests/{e2e-tests => edc-controlplane/catalog-tests}/src/test/java/org/eclipse/tractusx/edc/tests/catalog/CatalogInMemoryTest.java (96%) rename edc-tests/{e2e-tests => edc-controlplane/catalog-tests}/src/test/java/org/eclipse/tractusx/edc/tests/catalog/CatalogPostgresqlTest.java (96%) rename {edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-spi => edc-tests/edc-controlplane/edr-api-tests}/build.gradle.kts (71%) rename edc-tests/{e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/edr => edc-controlplane/edr-api-tests/src/test/java/org/eclipse/tractusx/edc/tests/edrv2}/AbstractNegotiateEdrTest.java (74%) rename edc-tests/edc-controlplane/{edr-tests => edr-api-tests}/src/test/java/org/eclipse/tractusx/edc/tests/edrv2/EdrCacheApiEndToEndTest.java (97%) rename edc-tests/{e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/edr => edc-controlplane/edr-api-tests/src/test/java/org/eclipse/tractusx/edc/tests/edrv2}/NegotiateEdrInMemoryTest.java (85%) create mode 100644 edc-tests/edc-controlplane/fixtures/build.gradle.kts create mode 100644 edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/IdentityParticipant.java rename edc-tests/edc-controlplane/{edr-tests/src/test => fixtures/src/testFixtures}/java/org/eclipse/tractusx/edc/tests/MockBpnIdentityService.java (100%) create mode 100644 edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/ParticipantDataApi.java rename edc-tests/edc-controlplane/{edr-tests/src/test => fixtures/src/testFixtures}/java/org/eclipse/tractusx/edc/tests/ParticipantEdrApi.java (88%) rename edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-spi/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/spi/provider/gateway/authorization/AuthorizationHandlerRegistry.java => edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/TestRuntimeConfiguration.java (64%) rename edc-tests/edc-controlplane/{edr-tests/src/test => fixtures/src/testFixtures}/java/org/eclipse/tractusx/edc/tests/TxParticipant.java (72%) rename edc-tests/edc-controlplane/{edr-tests/src/test/java/org/eclipse/tractusx/edc/tests => fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/helpers}/CatalogHelperFunctions.java (91%) rename edc-tests/edc-controlplane/{edr-tests/src/test/java/org/eclipse/tractusx/edc/tests => fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/helpers}/EdrNegotiationHelperFunctions.java (83%) rename edc-tests/edc-controlplane/{edr-tests/src/test/java/org/eclipse/tractusx/edc/tests => fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/helpers}/Functions.java (67%) create mode 100644 edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/helpers/PolicyHelperFunctions.java rename edc-tests/{e2e-tests/src/test/java/org/eclipse/tractusx/edc => edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests}/helpers/QueryHelperFunctions.java (97%) rename edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-core/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/core/gateway/configuration/GatewayConfigurationRegistryImpl.java => edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/helpers/ReceivedEvent.java (52%) create mode 100644 edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/runtimes/DataWiper.java create mode 100644 edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/runtimes/KeyPool.java rename edc-tests/edc-controlplane/{edr-tests/src/test/java/org/eclipse/tractusx/edc/tests => fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/runtimes}/ParticipantRuntime.java (74%) create mode 100644 edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/runtimes/PgParticipantRuntime.java rename edc-tests/edc-controlplane/{edr-tests => iatp-tests}/build.gradle.kts (65%) rename edc-tests/{e2e-tests => edc-controlplane/iatp-tests}/src/test/java/org/eclipse/tractusx/edc/tests/transfer/AbstractHttpConsumerPullWithProxyTest.java (77%) rename edc-tests/{e2e-tests => edc-controlplane/iatp-tests}/src/test/java/org/eclipse/tractusx/edc/tests/transfer/DimHttpConsumerPullWithProxyInMemoryTest.java (82%) rename edc-tests/{e2e-tests => edc-controlplane/iatp-tests}/src/test/java/org/eclipse/tractusx/edc/tests/transfer/IatpHttpConsumerPullWithProxyInMemoryTest.java (86%) rename edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-core/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/core/gateway/auth/AuthorizationHandlerRegistryImpl.java => edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/iatp/IatpDimParticipant.java (52%) create mode 100644 edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/iatp/IatpParticipant.java rename edc-tests/{e2e-tests/src/test/java/org/eclipse/tractusx/edc/token => edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/iatp/dispatchers}/DimDispatcher.java (95%) create mode 100644 edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/iatp/dispatchers/KeycloakDispatcher.java create mode 100644 edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/iatp/harness/DataspaceIssuer.java create mode 100644 edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/iatp/harness/DidExampleResolver.java create mode 100644 edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/iatp/harness/IatpHelperFunctions.java create mode 100644 edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/iatp/harness/SecureTokenService.java create mode 100644 edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/iatp/runtime/IatpParticipantRuntime.java rename {edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-core => edc-tests/edc-controlplane/policy-tests}/build.gradle.kts (70%) rename edc-tests/{e2e-tests => edc-controlplane/policy-tests}/src/test/java/org/eclipse/tractusx/edc/tests/policy/AbstractPolicyMonitorTest.java (89%) rename edc-tests/{e2e-tests => edc-controlplane/policy-tests}/src/test/java/org/eclipse/tractusx/edc/tests/policy/PolicyMonitorInMemoryTest.java (97%) rename edc-tests/{e2e-tests => edc-controlplane/policy-tests}/src/test/java/org/eclipse/tractusx/edc/tests/policy/PolicyMonitorPostgresqlTest.java (96%) create mode 100644 edc-tests/edc-controlplane/ssi-summarycred-tests/build.gradle.kts rename edc-tests/{e2e-tests/src/test/java/org/eclipse/tractusx/edc/token => edc-controlplane/ssi-summarycred-tests/src/test/java/org/eclipse/tractusx/edc/tests}/KeycloakDispatcher.java (95%) rename edc-tests/{e2e-tests/src/test/java/org/eclipse/tractusx/edc/token => edc-controlplane/ssi-summarycred-tests/src/test/java/org/eclipse/tractusx/edc/tests}/MiwDispatcher.java (98%) create mode 100644 edc-tests/edc-controlplane/ssi-summarycred-tests/src/test/java/org/eclipse/tractusx/edc/tests/SsiParticipant.java rename edc-tests/{e2e-tests => edc-controlplane/ssi-summarycred-tests}/src/test/java/org/eclipse/tractusx/edc/tests/negotiation/AbstractContractNegotiateTest.java (75%) rename edc-tests/{e2e-tests => edc-controlplane/ssi-summarycred-tests}/src/test/java/org/eclipse/tractusx/edc/tests/negotiation/SsiContractNegotiationInMemoryTest.java (80%) create mode 100644 edc-tests/edc-controlplane/ssi-summarycred-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/AbstractHttpConsumerPullWithProxyTest.java rename edc-tests/{e2e-tests => edc-controlplane/ssi-summarycred-tests}/src/test/java/org/eclipse/tractusx/edc/tests/transfer/SsiHttpConsumerPullWithProxyInMemoryTest.java (77%) create mode 100644 edc-tests/edc-controlplane/ssi-summarycred-tests/src/test/resources/framework-policy.json create mode 100644 edc-tests/edc-controlplane/ssi-summarycred-tests/src/test/resources/summary-vc-no-dismantler.json create mode 100644 edc-tests/edc-controlplane/ssi-summarycred-tests/src/test/resources/summary-vc.json rename {edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-api => edc-tests/edc-controlplane/transfer-tests}/build.gradle.kts (67%) create mode 100644 edc-tests/edc-controlplane/transfer-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/AbstractHttpConsumerPullWithProxyTest.java rename edc-tests/{e2e-tests => edc-controlplane/transfer-tests}/src/test/java/org/eclipse/tractusx/edc/tests/transfer/AbstractHttpProviderPushTest.java (87%) rename edc-tests/{e2e-tests => edc-controlplane/transfer-tests}/src/test/java/org/eclipse/tractusx/edc/tests/transfer/HttpConsumerPullWithProxyInMemoryTest.java (97%) rename edc-tests/{e2e-tests => edc-controlplane/transfer-tests}/src/test/java/org/eclipse/tractusx/edc/tests/transfer/HttpConsumerPullWithProxyPostgresqlTest.java (96%) rename edc-tests/{e2e-tests => edc-controlplane/transfer-tests}/src/test/java/org/eclipse/tractusx/edc/tests/transfer/HttpProviderPushInMemoryTest.java (96%) rename edc-tests/{e2e-tests => edc-controlplane/transfer-tests}/src/test/java/org/eclipse/tractusx/edc/tests/transfer/HttpProviderPushInPostgresqlTest.java (96%) rename edc-tests/{e2e-tests/src/test/java/org/eclipse/tractusx/edc/helpers/AssetHelperFunctions.java => edc-controlplane/transfer-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/TransferProcessHelperFunctions.java} (57%) delete mode 100644 edc-tests/edc-dataplane/edc-dataplane-proxy-e2e/build.gradle.kts delete mode 100644 edc-tests/edc-dataplane/edc-dataplane-proxy-e2e/src/test/java/org/eclipse/tractusx/edc/dataplane/proxy/e2e/DpfProxyEndToEndTest.java delete mode 100644 edc-tests/edc-dataplane/edc-dataplane-proxy-e2e/src/test/java/org/eclipse/tractusx/edc/dataplane/proxy/e2e/EdrCacheSetup.java delete mode 100644 edc-tests/edc-dataplane/edc-dataplane-proxy-e2e/src/test/java/org/eclipse/tractusx/edc/dataplane/proxy/e2e/KeyStoreSetup.java delete mode 100644 edc-tests/runtime/extensions/src/main/java/org/eclipse/tractusx/edc/lifecycle/ConsumerEdrHandlerController.java delete mode 100644 edc-tests/runtime/extensions/src/main/java/org/eclipse/tractusx/edc/lifecycle/ConsumerServicesExtension.java create mode 100644 edc-tests/runtime/iatp/runtime-memory-sts/src/main/java/org/eclipse/tractusx/edc/lifecycle/SecureTokenServiceExtension.java rename {edc-extensions/data-encryption => edc-tests/runtime/iatp/runtime-memory-sts}/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension (93%) diff --git a/.github/workflows/verify.yaml b/.github/workflows/verify.yaml index dc76681c9..3eafae03c 100644 --- a/.github/workflows/verify.yaml +++ b/.github/workflows/verify.yaml @@ -116,8 +116,12 @@ jobs: strategy: fail-fast: false matrix: - variant: [ { dir: edc-tests/edc-controlplane}, - { dir: edc-tests/e2e-tests} + variant: [ { dir: edc-tests/edc-controlplane/catalog-tests }, + { dir: edc-tests/edc-controlplane/edr-api-tests }, + { dir: edc-tests/edc-controlplane/iatp-tests }, + { dir: edc-tests/edc-controlplane/policy-tests }, + { dir: edc-tests/edc-controlplane/ssi-summarycred-tests }, + { dir: edc-tests/edc-controlplane/transfer-tests } ] steps: - uses: actions/checkout@v4 diff --git a/DEPENDENCIES b/DEPENDENCIES index 54d232212..09628486e 100644 --- a/DEPENDENCIES +++ b/DEPENDENCIES @@ -278,6 +278,7 @@ maven/mavencentral/net.java.dev.jna/jna-platform/5.13.0, Apache-2.0 OR LGPL-2.1- maven/mavencentral/net.java.dev.jna/jna-platform/5.6.0, Apache-2.0 OR LGPL-2.1-or-later, approved, CQ22390 maven/mavencentral/net.java.dev.jna/jna/5.13.0, Apache-2.0 AND LGPL-2.1-or-later, approved, #6709 maven/mavencentral/net.javacrumbs.json-unit/json-unit-core/2.36.0, Apache-2.0, approved, clearlydefined +maven/mavencentral/net.minidev/accessors-smart/2.4.7, Apache-2.0, approved, #7515 maven/mavencentral/net.minidev/accessors-smart/2.5.0, Apache-2.0, approved, clearlydefined maven/mavencentral/net.minidev/json-smart/2.4.10, Apache-2.0, approved, #3288 maven/mavencentral/net.minidev/json-smart/2.4.7, Apache-2.0, approved, #3288 @@ -325,6 +326,7 @@ maven/mavencentral/org.bouncycastle/bcpkix-jdk18on/1.72, MIT, approved, #3789 maven/mavencentral/org.bouncycastle/bcpkix-jdk18on/1.77, MIT, approved, #11593 maven/mavencentral/org.bouncycastle/bcprov-jdk18on/1.72, MIT AND CC0-1.0, approved, #3538 maven/mavencentral/org.bouncycastle/bcprov-jdk18on/1.77, MIT AND CC0-1.0, approved, #11595 +maven/mavencentral/org.bouncycastle/bcutil-jdk18on/1.72, MIT, approved, #3790 maven/mavencentral/org.bouncycastle/bcutil-jdk18on/1.77, MIT, approved, #11596 maven/mavencentral/org.ccil.cowan.tagsoup/tagsoup/1.2.1, Apache-2.0, approved, clearlydefined maven/mavencentral/org.checkerframework/checker-qual/3.12.0, MIT, approved, clearlydefined @@ -376,7 +378,6 @@ maven/mavencentral/org.eclipse.edc/data-address-http-data-spi/0.5.2-SNAPSHOT, Ap maven/mavencentral/org.eclipse.edc/data-plane-aws-s3/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/data-plane-azure-storage/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/data-plane-client-embedded/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-plane-client/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/data-plane-control-api/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/data-plane-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/data-plane-http-oauth2-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc @@ -384,11 +385,11 @@ maven/mavencentral/org.eclipse.edc/data-plane-http-oauth2/0.5.2-SNAPSHOT, Apache maven/mavencentral/org.eclipse.edc/data-plane-http-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/data-plane-http/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/data-plane-public-api-v2/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-plane-public-api/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/data-plane-selector-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/data-plane-selector-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/data-plane-signaling-api-configuration/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/data-plane-signaling-api/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-signaling-client/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/data-plane-signaling-transform/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/data-plane-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/data-plane-util/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc @@ -478,8 +479,8 @@ maven/mavencentral/org.eclipse.edc/transaction-datasource-spi/0.5.2-SNAPSHOT, Ap maven/mavencentral/org.eclipse.edc/transaction-local/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/transaction-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/transfer-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/transfer-data-plane-signaling/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/transfer-data-plane-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/transfer-data-plane/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/transfer-process-api/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/transfer-process-store-sql/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/transfer-pull-http-dynamic-receiver/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc @@ -582,6 +583,7 @@ maven/mavencentral/org.ow2.asm/asm-commons/9.5, BSD-3-Clause, approved, #7553 maven/mavencentral/org.ow2.asm/asm-commons/9.6, BSD-3-Clause, approved, #10775 maven/mavencentral/org.ow2.asm/asm-tree/9.5, BSD-3-Clause, approved, #7555 maven/mavencentral/org.ow2.asm/asm-tree/9.6, BSD-3-Clause, approved, #10773 +maven/mavencentral/org.ow2.asm/asm/9.1, BSD-3-Clause, approved, CQ23029 maven/mavencentral/org.ow2.asm/asm/9.3, BSD-3-Clause, approved, clearlydefined maven/mavencentral/org.ow2.asm/asm/9.5, BSD-3-Clause, approved, #7554 maven/mavencentral/org.ow2.asm/asm/9.6, BSD-3-Clause, approved, #10776 diff --git a/core/core-utils/build.gradle.kts b/core/core-utils/build.gradle.kts index 331074def..5f5745992 100644 --- a/core/core-utils/build.gradle.kts +++ b/core/core-utils/build.gradle.kts @@ -22,4 +22,5 @@ plugins { } dependencies { + implementation(libs.edc.spi.core) } diff --git a/core/core-utils/src/main/java/org/eclipse/tractusx/edc/core/utils/RequiredConfigWarnings.java b/core/core-utils/src/main/java/org/eclipse/tractusx/edc/core/utils/RequiredConfigWarnings.java new file mode 100644 index 000000000..8a5ad0b87 --- /dev/null +++ b/core/core-utils/src/main/java/org/eclipse/tractusx/edc/core/utils/RequiredConfigWarnings.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.eclipse.tractusx.edc.core.utils; + +import org.eclipse.edc.spi.monitor.Monitor; + +public class RequiredConfigWarnings { + + public static void warningNotPresent(Monitor monitor, String missingConfig) { + monitor.severe("Mandatory config value missing: '%s'. This runtime will not be fully operational! Starting with v0.7.x this will be a runtime error.".formatted(missingConfig)); + } +} diff --git a/core/edr-core/src/main/java/org/eclipse/tractusx/edc/edr/core/manager/EdrManagerImpl.java b/core/edr-core/src/main/java/org/eclipse/tractusx/edc/edr/core/manager/EdrManagerImpl.java index 091f4e67f..9a6818d3e 100644 --- a/core/edr-core/src/main/java/org/eclipse/tractusx/edc/edr/core/manager/EdrManagerImpl.java +++ b/core/edr-core/src/main/java/org/eclipse/tractusx/edc/edr/core/manager/EdrManagerImpl.java @@ -247,20 +247,18 @@ private StatusResult fireTransferProcess(EndpointDataReferenceEntry entry) if (transferProcess == null) { return StatusResult.failure(ResponseStatus.FATAL_ERROR, format("Failed to find transfer process %s", entry.getTransferProcessId())); } - var dataRequest = transferProcess.getDataRequest(); - var transferRequest = TransferRequest.Builder.newInstance() - .assetId(dataRequest.getAssetId()) - .contractId(dataRequest.getContractId()) - .protocol(dataRequest.getProtocol()) - .counterPartyAddress(dataRequest.getConnectorAddress()) - .dataDestination(dataRequest.getDataDestination()) + .assetId(transferProcess.getAssetId()) + .contractId(transferProcess.getContractId()) + .protocol(transferProcess.getProtocol()) + .counterPartyAddress(transferProcess.getCounterPartyAddress()) + .dataDestination(transferProcess.getDataDestination()) .callbackAddresses(transferProcess.getCallbackAddresses()) .build(); var result = transferProcessService.initiateTransfer(transferRequest); if (result.failed()) { - var msg = format("Failed to initiate a transfer for contract %s and asset %s, error: %s", dataRequest.getContractId(), dataRequest.getAssetId(), result.getFailureDetail()); + var msg = format("Failed to initiate a transfer for contract %s and asset %s, error: %s", transferProcess.getContractId(), transferProcess.getAssetId(), result.getFailureDetail()); monitor.severe(msg); return StatusResult.failure(ResponseStatus.ERROR_RETRY, result.getFailureDetail()); } diff --git a/core/edr-core/src/test/java/org/eclipse/tractusx/edc/edr/core/manager/EdrManagerImplTest.java b/core/edr-core/src/test/java/org/eclipse/tractusx/edc/edr/core/manager/EdrManagerImplTest.java index b781c299e..f3944c207 100644 --- a/core/edr-core/src/test/java/org/eclipse/tractusx/edc/edr/core/manager/EdrManagerImplTest.java +++ b/core/edr-core/src/test/java/org/eclipse/tractusx/edc/edr/core/manager/EdrManagerImplTest.java @@ -22,7 +22,6 @@ import org.eclipse.edc.connector.contract.spi.types.negotiation.ContractRequest; import org.eclipse.edc.connector.spi.contractnegotiation.ContractNegotiationService; import org.eclipse.edc.connector.spi.transferprocess.TransferProcessService; -import org.eclipse.edc.connector.transfer.spi.types.DataRequest; import org.eclipse.edc.connector.transfer.spi.types.ProvisionedResourceSet; import org.eclipse.edc.connector.transfer.spi.types.TransferProcess; import org.eclipse.edc.connector.transfer.spi.types.TransferProcessStates; @@ -31,6 +30,7 @@ import org.eclipse.edc.spi.query.QuerySpec; import org.eclipse.edc.spi.result.ServiceResult; import org.eclipse.edc.spi.result.StoreResult; +import org.eclipse.edc.spi.types.domain.DataAddress; import org.eclipse.tractusx.edc.edr.spi.store.EndpointDataReferenceCache; import org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntry; import org.junit.jupiter.api.BeforeEach; @@ -254,30 +254,21 @@ private EndpointDataReferenceEntry.Builder edrEntryBuilder() { private TransferProcess.Builder createTransferProcessBuilder() { var processId = UUID.randomUUID().toString(); - var dataRequest = createDataRequestBuilder() - .processId(processId) - .protocol("protocol") - .connectorAddress("http://an/address") - .build(); return TransferProcess.Builder.newInstance() .provisionedResourceSet(ProvisionedResourceSet.Builder.newInstance().build()) .type(CONSUMER) .id("test-process-" + processId) .state(TransferProcessStates.COMPLETED.code()) - .dataRequest(dataRequest); - } - - private DataRequest.Builder createDataRequestBuilder() { - return DataRequest.Builder.newInstance() - .id(UUID.randomUUID().toString()) .contractId(UUID.randomUUID().toString()) .assetId(UUID.randomUUID().toString()) - .destinationType("test-type"); + .protocol("protocol") + .dataDestination(DataAddress.Builder.newInstance().type("test-type").build()) + .counterPartyAddress("http://an/address"); } private Criterion[] stateIs(int state) { - return aryEq(new Criterion[] {hasState(state)}); + return aryEq(new Criterion[]{ hasState(state) }); } } diff --git a/edc-controlplane/edc-controlplane-base/build.gradle.kts b/edc-controlplane/edc-controlplane-base/build.gradle.kts index 64f2ccabf..4af418d2d 100644 --- a/edc-controlplane/edc-controlplane-base/build.gradle.kts +++ b/edc-controlplane/edc-controlplane-base/build.gradle.kts @@ -26,11 +26,16 @@ dependencies { runtimeOnly(project(":core:edr-cache-core")) runtimeOnly(project(":core:edr-core")) runtimeOnly(project(":edc-extensions:dataplane:dataplane-selector-configuration")) - runtimeOnly(project(":edc-extensions:data-encryption")) runtimeOnly(project(":edc-extensions:provision-additional-headers")) - runtimeOnly(project(":edc-extensions:edr:edr-api")) + runtimeOnly(project(":edc-extensions:edr:edr-api-v2")) runtimeOnly(project(":edc-extensions:edr:edr-callback")) + runtimeOnly(project(":edc-extensions:tokenrefresh-handler")) + runtimeOnly(libs.edc.core.edrstore) + runtimeOnly(libs.edc.edr.store.receiver) + runtimeOnly(libs.edc.dpf.transfer.signaling) + + runtimeOnly(project(":edc-extensions:iatp:tx-iatp-sts-dim")) // needed for BPN validation runtimeOnly(project(":edc-extensions:bpn-validation")) diff --git a/edc-controlplane/edc-controlplane-postgresql-azure-vault/build.gradle.kts b/edc-controlplane/edc-controlplane-postgresql-azure-vault/build.gradle.kts index 78a4c2022..93a35e3ae 100644 --- a/edc-controlplane/edc-controlplane-postgresql-azure-vault/build.gradle.kts +++ b/edc-controlplane/edc-controlplane-postgresql-azure-vault/build.gradle.kts @@ -29,14 +29,12 @@ plugins { dependencies { runtimeOnly(project(":edc-controlplane:edc-controlplane-base")) runtimeOnly(project(":edc-extensions:postgresql-migration")) - runtimeOnly(project(":edc-extensions:edr:edr-cache-sql")) runtimeOnly(project(":edc-extensions:bpn-validation:business-partner-store-sql")) runtimeOnly(libs.edc.azure.vault) runtimeOnly(libs.bundles.edc.sqlstores) runtimeOnly(libs.edc.transaction.local) runtimeOnly(libs.edc.sql.pool) runtimeOnly(libs.edc.core.controlplane) - runtimeOnly(libs.edc.dpf.transfer) runtimeOnly(libs.postgres) } diff --git a/edc-controlplane/edc-controlplane-postgresql-hashicorp-vault/build.gradle.kts b/edc-controlplane/edc-controlplane-postgresql-hashicorp-vault/build.gradle.kts index 8c8c7cefa..c5f91e916 100644 --- a/edc-controlplane/edc-controlplane-postgresql-hashicorp-vault/build.gradle.kts +++ b/edc-controlplane/edc-controlplane-postgresql-hashicorp-vault/build.gradle.kts @@ -29,14 +29,12 @@ plugins { dependencies { runtimeOnly(project(":edc-controlplane:edc-controlplane-base")) runtimeOnly(project(":edc-extensions:postgresql-migration")) - runtimeOnly(project(":edc-extensions:edr:edr-cache-sql")) runtimeOnly(project(":edc-extensions:bpn-validation:business-partner-store-sql")) runtimeOnly(libs.edc.vault.hashicorp) runtimeOnly(libs.bundles.edc.sqlstores) runtimeOnly(libs.edc.transaction.local) runtimeOnly(libs.edc.sql.pool) runtimeOnly(libs.edc.core.controlplane) - runtimeOnly(libs.edc.dpf.transfer) runtimeOnly(libs.postgres) } diff --git a/edc-dataplane/edc-dataplane-azure-vault/build.gradle.kts b/edc-dataplane/edc-dataplane-azure-vault/build.gradle.kts index 3db121d5e..deef00f71 100644 --- a/edc-dataplane/edc-dataplane-azure-vault/build.gradle.kts +++ b/edc-dataplane/edc-dataplane-azure-vault/build.gradle.kts @@ -33,7 +33,6 @@ dependencies { } implementation(libs.edc.azure.identity) implementation("com.azure:azure-security-keyvault-secrets:4.8.0") - runtimeOnly(project(":edc-extensions:edr:edr-cache-sql")) runtimeOnly(libs.edc.transaction.local) runtimeOnly(libs.edc.sql.pool) runtimeOnly(libs.postgres) diff --git a/edc-dataplane/edc-dataplane-base/build.gradle.kts b/edc-dataplane/edc-dataplane-base/build.gradle.kts index d0cc8cfbb..49e47d00f 100644 --- a/edc-dataplane/edc-dataplane-base/build.gradle.kts +++ b/edc-dataplane/edc-dataplane-base/build.gradle.kts @@ -25,8 +25,6 @@ plugins { dependencies { runtimeOnly(project(":core:edr-cache-core")) runtimeOnly(project(":edc-extensions:dataplane:dataplane-proxy:edc-dataplane-proxy-consumer-api")) - runtimeOnly(project(":edc-extensions:dataplane:dataplane-proxy:edc-dataplane-proxy-provider-api")) - runtimeOnly(project(":edc-extensions:dataplane:dataplane-proxy:edc-dataplane-proxy-provider-core")) runtimeOnly(project(":edc-extensions:dataplane:dataplane-token-refresh:token-refresh-core")) runtimeOnly(project(":edc-extensions:dataplane:dataplane-token-refresh:token-refresh-api")) @@ -45,7 +43,6 @@ dependencies { runtimeOnly(libs.edc.dpf.api.control) runtimeOnly(libs.edc.dpf.api.signaling) - runtimeOnly(libs.edc.dpf.api.public.v1) runtimeOnly(libs.edc.dpf.api.public.v2) runtimeOnly(libs.edc.core.connector) runtimeOnly(libs.edc.boot) diff --git a/edc-dataplane/edc-dataplane-hashicorp-vault/build.gradle.kts b/edc-dataplane/edc-dataplane-hashicorp-vault/build.gradle.kts index 63063b271..5deeb1698 100644 --- a/edc-dataplane/edc-dataplane-hashicorp-vault/build.gradle.kts +++ b/edc-dataplane/edc-dataplane-hashicorp-vault/build.gradle.kts @@ -26,7 +26,6 @@ plugins { dependencies { implementation(project(":edc-dataplane:edc-dataplane-base")) runtimeOnly(libs.edc.vault.hashicorp) - runtimeOnly(project(":edc-extensions:edr:edr-cache-sql")) runtimeOnly(libs.edc.transaction.local) runtimeOnly(libs.edc.sql.pool) runtimeOnly(libs.postgres) diff --git a/edc-extensions/data-encryption/src/main/java/org/eclipse/tractusx/edc/data/encryption/ArrayUtil.java b/edc-extensions/data-encryption/src/main/java/org/eclipse/tractusx/edc/data/encryption/ArrayUtil.java deleted file mode 100644 index 65c6475c2..000000000 --- a/edc-extensions/data-encryption/src/main/java/org/eclipse/tractusx/edc/data/encryption/ArrayUtil.java +++ /dev/null @@ -1,44 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2022 Mercedes-Benz Tech Innovation GmbH - * Copyright (c) 2021,2022 Contributors to the Eclipse Foundation - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.data.encryption; - -public class ArrayUtil { - - private ArrayUtil() { - } - - public static byte[] concat(byte[] a, byte[] b) { - byte[] c = new byte[a.length + b.length]; - System.arraycopy(a, 0, c, 0, a.length); - System.arraycopy(b, 0, c, a.length, b.length); - return c; - } - - public static byte[] subArray(byte[] a, int startIndex, int length) { - if (startIndex + length > a.length) { - throw new IllegalArgumentException("Start index + length is greater than array length"); - } - - byte[] b = new byte[length]; - System.arraycopy(a, startIndex, b, 0, length); - return b; - } -} diff --git a/edc-extensions/data-encryption/src/main/java/org/eclipse/tractusx/edc/data/encryption/TxEncryptorExtension.java b/edc-extensions/data-encryption/src/main/java/org/eclipse/tractusx/edc/data/encryption/TxEncryptorExtension.java deleted file mode 100644 index d6a246824..000000000 --- a/edc-extensions/data-encryption/src/main/java/org/eclipse/tractusx/edc/data/encryption/TxEncryptorExtension.java +++ /dev/null @@ -1,78 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.data.encryption; - -import org.eclipse.edc.connector.transfer.dataplane.security.NoopDataEncrypter; -import org.eclipse.edc.connector.transfer.dataplane.spi.security.DataEncrypter; -import org.eclipse.edc.runtime.metamodel.annotation.Extension; -import org.eclipse.edc.runtime.metamodel.annotation.Inject; -import org.eclipse.edc.runtime.metamodel.annotation.Provider; -import org.eclipse.edc.runtime.metamodel.annotation.Setting; -import org.eclipse.edc.spi.security.Vault; -import org.eclipse.edc.spi.system.ServiceExtension; -import org.eclipse.edc.spi.system.ServiceExtensionContext; -import org.eclipse.tractusx.edc.data.encryption.aes.AesEncryptor; - -import java.util.Objects; - -import static java.lang.String.format; - -@Extension(value = "Registers a DataEncryptor") -public class TxEncryptorExtension implements ServiceExtension { - public static final String NAME = "Data Encryption Extension"; - public static final String AES_ALGORITHM = "AES"; - - @Setting(value = "Vault alias, under which the encryption key is stored in the vault", required = true) - public static final String ENCRYPTION_KEY_ALIAS = "edc.data.encryption.keys.alias"; - - @Setting(value = "Algorithm to be used", defaultValue = AES_ALGORITHM) - public static final String ENCRYPTION_ALGORITHM = "edc.data.encryption.algorithm"; - @Setting(value = "DEPRECATED - caching keys is unsafe and is not used anymore. Will be ignored.") - @Deprecated - public static final String CACHING_ENABLED = "edc.data.encryption.caching.enabled"; - @Setting(value = "DEPRECATED - caching keys is unsafe and is not used anymore. Will be ignored.") - @Deprecated - public static final String CACHING_SECONDS = "edc.data.encryption.caching.seconds"; - @Inject - private Vault vault; - - @Override - public String name() { - return NAME; - } - - @Provider - public DataEncrypter createEncryptor(ServiceExtensionContext context) { - var keyAlias = context.getSetting(ENCRYPTION_KEY_ALIAS, null); - Objects.requireNonNull(keyAlias, ENCRYPTION_KEY_ALIAS + " property not found"); - var algorithm = context.getSetting(ENCRYPTION_ALGORITHM, AES_ALGORITHM); - - if (context.getSetting(CACHING_ENABLED, null) != null || context.getSetting(CACHING_SECONDS, null) != null) { - context.getMonitor().warning(format("Caching the secret keys was deprecated because it is unsafe. " + - "This version will ignore the properties '%s' and '%s' and will NOT cache the keys", CACHING_ENABLED, CACHING_SECONDS)); - } - - if (algorithm.equalsIgnoreCase(AES_ALGORITHM)) { - return new AesEncryptor(vault, keyAlias); - } - context.getMonitor().warning(format("Algorithm %s is not known, will use a NOOP encryptor!", algorithm)); - return new NoopDataEncrypter(); - } -} diff --git a/edc-extensions/data-encryption/src/main/java/org/eclipse/tractusx/edc/data/encryption/aes/AesEncryptor.java b/edc-extensions/data-encryption/src/main/java/org/eclipse/tractusx/edc/data/encryption/aes/AesEncryptor.java deleted file mode 100644 index 6aa47938d..000000000 --- a/edc-extensions/data-encryption/src/main/java/org/eclipse/tractusx/edc/data/encryption/aes/AesEncryptor.java +++ /dev/null @@ -1,147 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.data.encryption.aes; - -import org.eclipse.edc.connector.transfer.dataplane.spi.security.DataEncrypter; -import org.eclipse.edc.spi.EdcException; -import org.eclipse.edc.spi.security.Vault; -import org.eclipse.tractusx.edc.data.encryption.ArrayUtil; - -import java.security.InvalidAlgorithmParameterException; -import java.security.InvalidKeyException; -import java.security.NoSuchAlgorithmException; -import java.security.SecureRandom; -import java.util.Arrays; -import java.util.Base64; -import javax.crypto.BadPaddingException; -import javax.crypto.Cipher; -import javax.crypto.IllegalBlockSizeException; -import javax.crypto.NoSuchPaddingException; -import javax.crypto.SecretKey; -import javax.crypto.spec.GCMParameterSpec; -import javax.crypto.spec.SecretKeySpec; - -import static org.eclipse.tractusx.edc.data.encryption.ArrayUtil.concat; - -/** - * This class implements the {@link DataEncrypter} interface by encrypting and decrypting an input string using the
    GCM mode. - * Furthermore, it uses the {@code AES/CBC/PKCS5Padding} alongside the {@link java.security.SecureRandom} class to generate initialisation vectors (IV). - */ -public class AesEncryptor implements DataEncrypter { - - public static final int GCM_AUTH_TAG_LENGTH = 128; - public static final String AES = "AES"; - private static final String AES_GCM = "AES/GCM/NoPadding"; - private static final int IV_SIZE_BYTES = 16; // 16 bytes - private static final int[] ALLOWED_SIZES = new int[] {16, 24, 32}; // AES allows for 128, 192 or 256 bits - private final Vault vault; - private final String secretAlias; - private final Base64.Decoder decoder = Base64.getDecoder(); - private final Base64.Encoder encoder = Base64.getEncoder(); - private final Cipher cipher; - - /** - * Initializes the encryptor with private key (stored in the vault). The key, that was stored in the vault, is expected to be in Base64 format, and - * this encryptor will produce encrypted text in Base64. - * - * @param vault A Vault instance that contains the encryption key. Keys should never be held in memory. - * @param secretAlias The alias under which the key was stored in the vault. The key, which is stored in the vault under the given alias, must be in Base64 format - */ - public AesEncryptor(Vault vault, String secretAlias) { - this.vault = vault; - this.secretAlias = secretAlias; - try { - cipher = Cipher.getInstance(AES_GCM); - } catch (NoSuchAlgorithmException | NoSuchPaddingException e) { - throw new EdcException("Error while instantiating Cipher", e); - } - } - - - @Override - public String encrypt(String raw) { - var key = getKey(secretAlias); - var iv = generateIv(IV_SIZE_BYTES); - try { - var gcmSpec = new GCMParameterSpec(GCM_AUTH_TAG_LENGTH, iv); - cipher.init(Cipher.ENCRYPT_MODE, key, gcmSpec); - - byte[] cipherText = cipher.doFinal(raw.getBytes()); - var ivAndCipher = concat(iv, cipherText); - - return encoder.encodeToString(ivAndCipher); - } catch (InvalidAlgorithmParameterException | IllegalBlockSizeException | BadPaddingException | InvalidKeyException e) { - throw new EdcException("Error while encrypting", e); - } - } - - /** - * The encrypted text is expected in Base64 format: it is simply the ciphertext encoded as Base64 - */ - @Override - public String decrypt(String encrypted) { - var key = getKey(secretAlias); - // will throw IllegalArgumentException if not base64 - var decodedCipher = decoder.decode(encrypted); - - if (decodedCipher.length < IV_SIZE_BYTES) { - throw new IllegalArgumentException("Decoded ciphertext was shorter than the IV size (" + IV_SIZE_BYTES + ")"); - } - var iv = ArrayUtil.subArray(decodedCipher, 0, IV_SIZE_BYTES); - var cipherText = ArrayUtil.subArray(decodedCipher, IV_SIZE_BYTES, decodedCipher.length - IV_SIZE_BYTES); - - var gcmSpec = new GCMParameterSpec(GCM_AUTH_TAG_LENGTH, iv); - - try { - cipher.init(Cipher.DECRYPT_MODE, key, gcmSpec); - byte[] plainText = cipher.doFinal(cipherText); - return new String(plainText); - } catch (InvalidAlgorithmParameterException | InvalidKeyException | BadPaddingException | IllegalBlockSizeException e) { - throw new EdcException("Error while decrypting", e); - } - } - - private byte[] generateIv(int length) { - byte[] iv = new byte[length]; - new SecureRandom().nextBytes(iv); - return iv; - } - - private SecretKey getKey(String alias) { - var secretBase64 = vault.resolveSecret(alias); - if (secretBase64 == null) { - throw new EdcException("Cannot perform AES encryption: secret key not found in vault"); - } - var decoded = decoder.decode(secretBase64); - if (isAllowedSize(decoded)) { - return new SecretKeySpec(decoded, AES); - } - throw new EdcException("Expected a key size of 16, 24 or 32 bytes byt found " + decoded.length); - } - - /** - * Check is the decoded byte array is 16, 24 or 32 bytes in size - */ - private boolean isAllowedSize(byte[] decoded) { - return Arrays.stream(ALLOWED_SIZES).anyMatch(i -> i == decoded.length); - } - - -} diff --git a/edc-extensions/data-encryption/src/test/java/org/eclipse/tractusx/edc/data/encryption/TxEncryptorExtensionTest.java b/edc-extensions/data-encryption/src/test/java/org/eclipse/tractusx/edc/data/encryption/TxEncryptorExtensionTest.java deleted file mode 100644 index e5fffc02a..000000000 --- a/edc-extensions/data-encryption/src/test/java/org/eclipse/tractusx/edc/data/encryption/TxEncryptorExtensionTest.java +++ /dev/null @@ -1,84 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.data.encryption; - -import org.eclipse.edc.connector.transfer.dataplane.security.NoopDataEncrypter; -import org.eclipse.edc.junit.extensions.DependencyInjectionExtension; -import org.eclipse.edc.spi.monitor.Monitor; -import org.eclipse.edc.spi.system.ServiceExtensionContext; -import org.eclipse.tractusx.edc.data.encryption.aes.AesEncryptor; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.ValueSource; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.eclipse.tractusx.edc.data.encryption.TxEncryptorExtension.CACHING_ENABLED; -import static org.eclipse.tractusx.edc.data.encryption.TxEncryptorExtension.CACHING_SECONDS; -import static org.eclipse.tractusx.edc.data.encryption.TxEncryptorExtension.ENCRYPTION_ALGORITHM; -import static org.eclipse.tractusx.edc.data.encryption.TxEncryptorExtension.ENCRYPTION_KEY_ALIAS; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.ArgumentMatchers.startsWith; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -@ExtendWith(DependencyInjectionExtension.class) -class TxEncryptorExtensionTest { - - private final Monitor monitor = mock(); - - @BeforeEach - void setup(ServiceExtensionContext context) { - context.registerService(Monitor.class, monitor); - when(context.getSetting(ENCRYPTION_KEY_ALIAS, null)).thenReturn("test-key"); - } - - @Test - void createEncryptor_noConfig_createsDefault(ServiceExtensionContext context, TxEncryptorExtension extension) { - var encryptor = extension.createEncryptor(context); - assertThat(encryptor).isInstanceOf(AesEncryptor.class); - } - - @Test - void createEncryptor_otherAlgorithm_createsNoop(ServiceExtensionContext context, TxEncryptorExtension extension) { - when(context.getSetting(eq(ENCRYPTION_ALGORITHM), any())).thenReturn("some-algorithm"); - var encryptor = extension.createEncryptor(context); - assertThat(encryptor).isInstanceOf(NoopDataEncrypter.class); - verify(monitor).warning(eq("Algorithm some-algorithm is not known, will use a NOOP encryptor!")); - } - - @Test - void createEncryptor_withPropertyEqualsAes(ServiceExtensionContext context, TxEncryptorExtension extension) { - when(context.getSetting(eq(ENCRYPTION_ALGORITHM), any())).thenReturn("AES"); - var encryptor = extension.createEncryptor(context); - assertThat(encryptor).isInstanceOf(AesEncryptor.class); - } - - @ParameterizedTest - @ValueSource(strings = { CACHING_ENABLED, CACHING_SECONDS }) - void verifyDeprecationWarnings(String deprecatedSetting, ServiceExtensionContext context, TxEncryptorExtension extension) { - when(context.getSetting(eq(deprecatedSetting), any())).thenReturn("doesn't matter"); - extension.createEncryptor(context); - verify(monitor).warning(startsWith("Caching the secret keys was deprecated because it is unsafe")); - } -} diff --git a/edc-extensions/data-encryption/src/test/java/org/eclipse/tractusx/edc/data/encryption/aes/AesEncryptorTest.java b/edc-extensions/data-encryption/src/test/java/org/eclipse/tractusx/edc/data/encryption/aes/AesEncryptorTest.java deleted file mode 100644 index 1cd99abd3..000000000 --- a/edc-extensions/data-encryption/src/test/java/org/eclipse/tractusx/edc/data/encryption/aes/AesEncryptorTest.java +++ /dev/null @@ -1,127 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.data.encryption.aes; - -import org.eclipse.edc.spi.EdcException; -import org.eclipse.edc.spi.security.Vault; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.ValueSource; - -import java.security.SecureRandom; -import java.util.Base64; -import javax.crypto.BadPaddingException; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -class AesEncryptorTest { - - private static final String TESTALIAS = "test-alias"; - private final Vault vaultMock = mock(); - private AesEncryptor encryptor; - - @BeforeEach - void setup() { - encryptor = new AesEncryptor(vaultMock, TESTALIAS); - } - - @ParameterizedTest - @ValueSource(ints = {16, 24, 32}) - void encrypt(int validSize) { - when(vaultMock.resolveSecret(eq(TESTALIAS))).thenReturn(generateBase64(validSize)); - - var encrypted = encryptor.encrypt("foobar barbaz"); - assertThat(encrypted).isNotNull(); - } - - @ParameterizedTest - @ValueSource(ints = {0, 1, 17, 33, 1024, 8192}) - void encrypt_invalidKeySize(int invalidKeySize) { - when(vaultMock.resolveSecret(eq(TESTALIAS))).thenReturn(generateBase64(invalidKeySize)); - assertThatThrownBy(() -> encryptor.encrypt("hello world!")) - .isInstanceOf(EdcException.class) - .hasMessage("Expected a key size of 16, 24 or 32 bytes byt found " + invalidKeySize); - } - - @Test - void encrypt_secretNotBase64() { - when(vaultMock.resolveSecret(eq(TESTALIAS))).thenReturn("not-base64"); - - assertThatThrownBy(() -> encryptor.encrypt("hello world!")) - .isInstanceOf(IllegalArgumentException.class) - .hasMessageStartingWith("Illegal base64 character"); - } - - @Test - void encrypt_secretNotExist() { - assertThatThrownBy(() -> encryptor.encrypt("hello world!")) - .isInstanceOf(EdcException.class) - .hasMessage("Cannot perform AES encryption: secret key not found in vault"); - } - - @Test - void decrypt() { - when(vaultMock.resolveSecret(eq(TESTALIAS))).thenReturn(generateBase64(32)); - var rawText = "hello world!"; - var encrypted = encryptor.encrypt(rawText); - assertThat(encryptor.decrypt(encrypted)).isEqualTo(rawText); - } - - @Test - void decrypt_wrongSecretKey() { - when(vaultMock.resolveSecret(eq(TESTALIAS))).thenReturn(generateBase64(32)); - var rawText = "hello world!"; - var encrypted = encryptor.encrypt(rawText); - when(vaultMock.resolveSecret(eq(TESTALIAS))).thenReturn(generateBase64(32)); - assertThatThrownBy(() -> encryptor.decrypt(encrypted)).isInstanceOf(EdcException.class) - .hasMessage("Error while decrypting") - .hasRootCauseInstanceOf(BadPaddingException.class); - } - - @Test - void decrypt_keyNotBase64() { - when(vaultMock.resolveSecret(eq(TESTALIAS))).thenReturn("not-base64"); - assertThatThrownBy(() -> encryptor.decrypt("encrypted-text")) - .isInstanceOf(IllegalArgumentException.class) - .hasMessageStartingWith("Illegal base64 character"); - } - - @Test - void decrypt_ciphertextTooShort() { - when(vaultMock.resolveSecret(eq(TESTALIAS))).thenReturn(generateBase64(32)); - var cipherText = Base64.getEncoder().encodeToString("asdf".getBytes()); - assertThatThrownBy(() -> encryptor.decrypt(cipherText)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessageStartingWith("Decoded ciphertext was shorter than the IV size (16)"); - } - - private String generateBase64(int validSize) { - var bytes = new byte[validSize]; - - new SecureRandom().nextBytes(bytes); - return Base64.getEncoder().encodeToString(bytes); - - } -} diff --git a/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-consumer-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/consumer/api/asset/ConsumerAssetRequestController.java b/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-consumer-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/consumer/api/asset/ConsumerAssetRequestController.java index 8e620f932..f2a22de1f 100644 --- a/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-consumer-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/consumer/api/asset/ConsumerAssetRequestController.java +++ b/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-consumer-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/consumer/api/asset/ConsumerAssetRequestController.java @@ -63,7 +63,6 @@ @Produces(MediaType.APPLICATION_JSON) public class ConsumerAssetRequestController implements ConsumerAssetRequestApi { public static final String BASE_URL = EDC_NAMESPACE + "baseUrl"; - private static final String HTTP_DATA = "HttpData"; private static final String ASYNC_TYPE = "async"; private static final String HEADER_AUTHORIZATION = "header:authorization"; private static final String BEARER_PREFIX = "Bearer "; diff --git a/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-api/README.md b/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-api/README.md deleted file mode 100644 index a931a6d46..000000000 --- a/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-api/README.md +++ /dev/null @@ -1,26 +0,0 @@ -# DataPlane Proxy Provider API - -This extension provide additional dataplane extension for proxying requests to backends. -The configuration of the proxy can be found [here](../edc-dataplane-proxy-provider-core/README.md) - -The provider proxy is mounted into the EDC default context, and it's available in the path `/gateway` - -The proxy will look for subPath in the request and match the subpath with the configured ones and forward -the rest of the path and query parameters. - -For example: - -with this URL `http://localhost:8181/api/gateway/aas/test` it will look for the `aas` alias in the configuration, -and it will compose the final url to call based on that configuration appending to it the remaining part of the path and query -parameters. - -When the proxy receive a request, it must contain the EDR, which will be decoded with the `token` validation endpoint. - -## Configuration - -| Key | Required | Default | Description | -|--------------------------------------------|----------------------------------------------------------------------------------------| -| tx.dpf.provider.proxy.thread.pool | | 10 | Thread pool size for the provider data plane proxy gateway | -| edc.dataplane.token.validation.endpoint | x | | URL of the token validation endpoint | -| web.http.gateway.context.path | | | Path to register the ProviderGatewayController to | -| web.http.gateway.context.port | | | Port to register the ProviderGatewayController to | diff --git a/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/api/DataPlaneProxyProviderApiExtension.java b/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/api/DataPlaneProxyProviderApiExtension.java deleted file mode 100644 index 644855e2c..000000000 --- a/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/api/DataPlaneProxyProviderApiExtension.java +++ /dev/null @@ -1,122 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.dataplane.proxy.provider.api; - -import org.eclipse.edc.connector.dataplane.spi.pipeline.PipelineService; -import org.eclipse.edc.runtime.metamodel.annotation.Extension; -import org.eclipse.edc.runtime.metamodel.annotation.Inject; -import org.eclipse.edc.runtime.metamodel.annotation.Setting; -import org.eclipse.edc.spi.http.EdcHttpClient; -import org.eclipse.edc.spi.monitor.Monitor; -import org.eclipse.edc.spi.system.ServiceExtension; -import org.eclipse.edc.spi.system.ServiceExtensionContext; -import org.eclipse.edc.spi.types.TypeManager; -import org.eclipse.edc.web.spi.WebService; -import org.eclipse.tractusx.edc.dataplane.proxy.provider.api.gateway.ProviderGatewayController; -import org.eclipse.tractusx.edc.dataplane.proxy.provider.api.validation.ProxyProviderDataAddressResolver; -import org.eclipse.tractusx.edc.dataplane.proxy.spi.provider.gateway.authorization.AuthorizationHandlerRegistry; -import org.eclipse.tractusx.edc.dataplane.proxy.spi.provider.gateway.configuration.GatewayConfigurationRegistry; - -import java.util.concurrent.ExecutorService; - -import static java.util.concurrent.Executors.newFixedThreadPool; - -/** - * Adds the consumer proxy data plane API. - */ -@Extension(value = DataPlaneProxyProviderApiExtension.NAME) -public class DataPlaneProxyProviderApiExtension implements ServiceExtension { - public static final int DEFAULT_THREAD_POOL = 10; - static final String NAME = "Data Plane Proxy Provider API"; - @Setting(value = "Thread pool size for the provider data plane proxy gateway", type = "int") - private static final String THREAD_POOL_SIZE = "tx.dpf.provider.proxy.thread.pool"; - - @Setting(value = "Path to register the ProviderGatewayController to", type = "String") - private static final String WEB_HTTP_GATEWAY_PATH_SETTING = "web.http.gateway.path"; - - @Setting(value = "Port to register the ProviderGatewayController to", type = "int") - private static final String WEB_HTTP_GATEWAY_PORT_SETTING = "web.http.gateway.port"; - - private static final String GATEWAY_CONTEXT = "gateway"; - - @Setting - private static final String CONTROL_PLANE_VALIDATION_ENDPOINT = "edc.dataplane.token.validation.endpoint"; - - @Inject - private WebService webService; - - @Inject - private PipelineService pipelineService; - - @Inject - private Monitor monitor; - - @Inject - private GatewayConfigurationRegistry configurationRegistry; - - @Inject - private AuthorizationHandlerRegistry authorizationRegistry; - - @Inject - private TypeManager typeManager; - - @Inject - private EdcHttpClient httpClient; - - private ExecutorService executorService; - - @Override - public String name() { - return NAME; - } - - @Override - public void initialize(ServiceExtensionContext context) { - executorService = newFixedThreadPool(context.getConfig().getInteger(THREAD_POOL_SIZE, DEFAULT_THREAD_POOL)); - - var validationEndpoint = context.getConfig().getString(CONTROL_PLANE_VALIDATION_ENDPOINT); - - var dataAddressResolver = new ProxyProviderDataAddressResolver(httpClient, validationEndpoint, typeManager.getMapper()); - - var controller = new ProviderGatewayController(pipelineService, - dataAddressResolver, - configurationRegistry, - authorizationRegistry, - executorService, - monitor); - - // If a setting for the port mapping for a separate gateway context exists, we assume the context also exists and register into that - // Otherwise we use the default context - if (context.getConfig().hasKey(WEB_HTTP_GATEWAY_PATH_SETTING) && context.getConfig().hasKey(WEB_HTTP_GATEWAY_PORT_SETTING)) { - webService.registerResource(GATEWAY_CONTEXT, controller); - } else { - webService.registerResource(controller); - } - } - - - @Override - public void shutdown() { - if (executorService != null) { - executorService.shutdown(); - } - } - -} diff --git a/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/api/gateway/ProviderGatewayApi.java b/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/api/gateway/ProviderGatewayApi.java deleted file mode 100644 index b4d169193..000000000 --- a/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/api/gateway/ProviderGatewayApi.java +++ /dev/null @@ -1,43 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.dataplane.proxy.provider.api.gateway; - -import io.swagger.v3.oas.annotations.OpenAPIDefinition; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.ws.rs.container.AsyncResponse; -import jakarta.ws.rs.container.ContainerRequestContext; -import jakarta.ws.rs.container.Suspended; -import jakarta.ws.rs.core.Context; - -/** - * Open API definition. - */ -@OpenAPIDefinition -@Tag(name = "Data Plane Proxy API") -public interface ProviderGatewayApi { - - @Operation(responses = { - @ApiResponse(content = @Content(mediaType = "application/json"), description = "Gets asset data") - }) - void requestAsset(@Context ContainerRequestContext context, @Suspended AsyncResponse response); -} diff --git a/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/api/gateway/ProviderGatewayController.java b/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/api/gateway/ProviderGatewayController.java deleted file mode 100644 index 00243cdc0..000000000 --- a/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/api/gateway/ProviderGatewayController.java +++ /dev/null @@ -1,253 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.dataplane.proxy.provider.api.gateway; - -import jakarta.ws.rs.GET; -import jakarta.ws.rs.Path; -import jakarta.ws.rs.container.AsyncResponse; -import jakarta.ws.rs.container.ContainerRequestContext; -import jakarta.ws.rs.container.Suspended; -import jakarta.ws.rs.core.Context; -import jakarta.ws.rs.core.HttpHeaders; -import jakarta.ws.rs.core.PathSegment; -import jakarta.ws.rs.core.Response; -import jakarta.ws.rs.core.StreamingOutput; -import org.eclipse.edc.connector.dataplane.http.spi.HttpDataAddress; -import org.eclipse.edc.connector.dataplane.spi.pipeline.StreamResult; -import org.eclipse.edc.connector.dataplane.spi.pipeline.TransferService; -import org.eclipse.edc.connector.dataplane.spi.resolver.DataAddressResolver; -import org.eclipse.edc.connector.dataplane.util.sink.AsyncStreamingDataSink; -import org.eclipse.edc.spi.monitor.Monitor; -import org.eclipse.edc.spi.result.Result; -import org.eclipse.edc.spi.types.domain.DataAddress; -import org.eclipse.edc.spi.types.domain.transfer.DataFlowStartMessage; -import org.eclipse.tractusx.edc.dataplane.proxy.spi.provider.gateway.authorization.AuthorizationHandlerRegistry; -import org.eclipse.tractusx.edc.dataplane.proxy.spi.provider.gateway.configuration.GatewayConfiguration; -import org.eclipse.tractusx.edc.dataplane.proxy.spi.provider.gateway.configuration.GatewayConfigurationRegistry; - -import java.util.Map; -import java.util.concurrent.ExecutorService; - -import static jakarta.ws.rs.core.MediaType.APPLICATION_JSON; -import static jakarta.ws.rs.core.Response.Status.BAD_REQUEST; -import static jakarta.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR; -import static jakarta.ws.rs.core.Response.Status.NOT_FOUND; -import static jakarta.ws.rs.core.Response.Status.UNAUTHORIZED; -import static jakarta.ws.rs.core.Response.status; -import static java.lang.String.format; -import static java.lang.String.join; -import static java.util.UUID.randomUUID; -import static java.util.stream.Collectors.joining; -import static org.eclipse.edc.spi.CoreConstants.EDC_NAMESPACE; -import static org.eclipse.tractusx.edc.dataplane.proxy.provider.api.response.ResponseHelper.createMessageResponse; - -/** - * Implements the HTTP data proxy API. - */ -@Path("/" + ProviderGatewayController.GATEWAY_PATH) -public class ProviderGatewayController implements ProviderGatewayApi { - protected static final String GATEWAY_PATH = "gateway"; - private static final String BASE_URL = EDC_NAMESPACE + "baseUrl"; - private static final String ASYNC = "async"; - - private static final int ALIAS_SEGMENT = 1; - private static final String BEARER_PREFIX = "Bearer "; - - private final TransferService transferService; - private final GatewayConfigurationRegistry configurationRegistry; - private final AuthorizationHandlerRegistry authorizationRegistry; - - private final DataAddressResolver dataAddressResolver; - - private final Monitor monitor; - - private final ExecutorService executorService; - - public ProviderGatewayController(TransferService transferService, - DataAddressResolver dataAddressResolver, - GatewayConfigurationRegistry configurationRegistry, - AuthorizationHandlerRegistry authorizationRegistry, - ExecutorService executorService, - Monitor monitor) { - this.transferService = transferService; - this.dataAddressResolver = dataAddressResolver; - this.configurationRegistry = configurationRegistry; - this.authorizationRegistry = authorizationRegistry; - this.executorService = executorService; - this.monitor = monitor; - } - - @GET - @Path("/{paths: .+}") - @Override - public void requestAsset(@Context ContainerRequestContext context, @Suspended AsyncResponse response) { - var tokens = context.getHeaders().get(HttpHeaders.AUTHORIZATION); - if (tokens == null || tokens.isEmpty()) { - response.resume(createMessageResponse(UNAUTHORIZED, "No bearer token", context.getMediaType())); - return; - } - var token = tokens.get(0); - if (!token.startsWith(BEARER_PREFIX)) { - response.resume(createMessageResponse(UNAUTHORIZED, "Invalid bearer token", context.getMediaType())); - return; - } else { - token = token.substring(BEARER_PREFIX.length()); - } - - - var uriInfo = context.getUriInfo(); - var segments = uriInfo.getPathSegments(); - if (segments.size() < 3 || !GATEWAY_PATH.equals(segments.get(0).getPath())) { - response.resume(createMessageResponse(BAD_REQUEST, "Invalid path", context.getMediaType())); - return; - } - - var alias = segments.get(ALIAS_SEGMENT).getPath(); - var configuration = configurationRegistry.getConfiguration(alias); - if (configuration == null) { - response.resume(createMessageResponse(NOT_FOUND, "Unknown path", context.getMediaType())); - return; - } - - var httpDataAddressResult = extractSourceDataAddress(token, configuration); - HttpDataAddress httpDataAddress; - - if (httpDataAddressResult.succeeded()) { - httpDataAddress = httpDataAddressResult.getContent(); - } else { - monitor.debug("Request to token validation endpoint failed with errors: " + join(", ", httpDataAddressResult.getFailureMessages())); - response.resume(createMessageResponse(UNAUTHORIZED, "Failed to decode data address", context.getMediaType())); - return; - } - - if (!configuration.getProxiedPath().startsWith(httpDataAddress.getBaseUrl())) { - response.resume(createMessageResponse(NOT_FOUND, "Data address path not matched", context.getMediaType())); - return; - } - - // calculate the sub-path, which all segments after the GATEWAY segment, including the alias segment - var subPath = segments.stream().skip(1).map(PathSegment::getPath).collect(joining("/")); - if (!authenticate(token, configuration.getAuthorizationType(), subPath, context, response)) { - return; - } - - // calculate the request path, which all segments after the alias segment - var requestPath = segments.stream().skip(2).map(PathSegment::getPath).collect(joining("/")); - var flowRequest = createRequest(requestPath, configuration, httpDataAddress); - - // transfer the data asynchronously - - AsyncStreamingDataSink.AsyncResponseContext asyncResponseContext = callback -> { - StreamingOutput output = t -> callback.outputStreamConsumer().accept(t); - var resp = Response.ok(output).type(callback.mediaType()).build(); - return response.resume(resp); - }; - var sink = new AsyncStreamingDataSink(asyncResponseContext, executorService); - - try { - transferService.transfer(flowRequest, sink).whenComplete((result, throwable) -> handleCompletion(response, result, throwable)); - } catch (Exception e) { - reportError(response, e); - } - } - - private DataFlowStartMessage createRequest(String subPath, GatewayConfiguration configuration, HttpDataAddress httpDataAddress) { - var path = configuration.getProxiedPath() + "/" + subPath; - - var sourceAddressBuilder = HttpDataAddress.Builder.newInstance() - .property(BASE_URL, path); - - httpDataAddress.getAdditionalHeaders().forEach(sourceAddressBuilder::addAdditionalHeader); - - var destinationAddress = DataAddress.Builder.newInstance() - .type(ASYNC) - .build(); - - return DataFlowStartMessage.Builder.newInstance() - .processId(randomUUID().toString()) - .sourceDataAddress(sourceAddressBuilder.build()) - .destinationDataAddress(destinationAddress) - .traceContext(Map.of()) - .build(); - } - - private boolean authenticate(String token, String authType, String subPath, ContainerRequestContext context, AsyncResponse response) { - var handler = authorizationRegistry.getHandler(authType); - if (handler == null) { - var correlationId = randomUUID().toString(); - monitor.severe(format("Authentication handler not configured for type: %s [id: %s]", authType, correlationId)); - response.resume(createMessageResponse(INTERNAL_SERVER_ERROR, format("Internal server error: %s", correlationId), context.getMediaType())); - return false; - } - - var authResponse = handler.authorize(token, subPath); - if (authResponse.failed()) { - response.resume(status(UNAUTHORIZED).build()); - return false; - } - return true; - } - - /** - * Handles a request completion, checking for errors. If no errors are present, nothing needs to be done as the response will have already been written to the client. - */ - private void handleCompletion(AsyncResponse response, StreamResult result, Throwable throwable) { - if (result != null && result.failed()) { - switch (result.reason()) { - case NOT_FOUND: - response.resume(status(NOT_FOUND).type(APPLICATION_JSON).build()); - break; - case NOT_AUTHORIZED: - response.resume(status(UNAUTHORIZED).type(APPLICATION_JSON).build()); - break; - case GENERAL_ERROR: - response.resume(status(INTERNAL_SERVER_ERROR).type(APPLICATION_JSON).build()); - break; - default: - throw new IllegalStateException("Unexpected value: " + result.reason()); - } - } else if (throwable != null) { - reportError(response, throwable); - } - } - - /** - * Reports an error to the client. On the provider side, the error is reported as a {@code INTERNAL_SERVER_ERROR} since the provider data plane is considered an origin server - * even though it may delegate requests to other internal sources. - */ - private void reportError(AsyncResponse response, Throwable throwable) { - monitor.severe("Error processing gateway request", throwable); - var entity = status(INTERNAL_SERVER_ERROR).entity(format("'%s'", throwable.getMessage())).type(APPLICATION_JSON).build(); - response.resume(entity); - } - - - private Result extractSourceDataAddress(String token, GatewayConfiguration configuration) { - return dataAddressResolver.resolve(token).map(dataAddress -> mapToHttpDataAddress(dataAddress, configuration, token)); - } - - private HttpDataAddress mapToHttpDataAddress(DataAddress dataAddress, GatewayConfiguration configuration, String token) { - var builder = HttpDataAddress.Builder.newInstance().copyFrom(dataAddress); - if (configuration.isForwardEdrToken()) { - builder.addAdditionalHeader(configuration.getForwardEdrTokenHeaderKey(), token); - } - return builder.build(); - } -} diff --git a/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/api/response/ResponseHelper.java b/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/api/response/ResponseHelper.java deleted file mode 100644 index eb449d52e..000000000 --- a/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/api/response/ResponseHelper.java +++ /dev/null @@ -1,49 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.dataplane.proxy.provider.api.response; - -import jakarta.ws.rs.core.MediaType; -import jakarta.ws.rs.core.Response; -import org.jetbrains.annotations.Nullable; - -import static jakarta.ws.rs.core.MediaType.APPLICATION_JSON; -import static jakarta.ws.rs.core.MediaType.TEXT_PLAIN; -import static jakarta.ws.rs.core.Response.status; -import static java.lang.String.format; - -/** - * Utility functions for creating responses. - */ -public class ResponseHelper { - - /** - * Creates a response with a message encoded for the given media type. Currently, {@code APPLICATION_JSON} and {@code TEXT_PLAIN} are supported. - */ - public static Response createMessageResponse(Response.Status status, String message, @Nullable MediaType mediaType) { - if (mediaType != null && APPLICATION_JSON.equals(mediaType.toString())) { - return status(status).entity(format("'%s'", message)).type(APPLICATION_JSON).build(); - } else { - return status(status).entity(format("%s", message)).type(TEXT_PLAIN).build(); - } - } - - private ResponseHelper() { - } -} diff --git a/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/api/validation/ProxyProviderDataAddressResolver.java b/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/api/validation/ProxyProviderDataAddressResolver.java deleted file mode 100644 index c9cc6901f..000000000 --- a/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/api/validation/ProxyProviderDataAddressResolver.java +++ /dev/null @@ -1,72 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2022 Amadeus - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.dataplane.proxy.provider.api.validation; - -import com.fasterxml.jackson.databind.ObjectMapper; -import jakarta.ws.rs.core.HttpHeaders; -import okhttp3.Request; -import org.eclipse.edc.connector.dataplane.spi.resolver.DataAddressResolver; -import org.eclipse.edc.spi.http.EdcHttpClient; -import org.eclipse.edc.spi.result.Result; -import org.eclipse.edc.spi.types.domain.DataAddress; - -import java.io.IOException; - -import static java.lang.String.format; - -public class ProxyProviderDataAddressResolver implements DataAddressResolver { - - private final EdcHttpClient httpClient; - private final String endpoint; - private final ObjectMapper mapper; - - public ProxyProviderDataAddressResolver(EdcHttpClient httpClient, String endpoint, ObjectMapper mapper) { - this.httpClient = httpClient; - this.endpoint = endpoint; - this.mapper = mapper; - } - - /** - * Resolves access token received in input of Data Plane public API (consumer pull) into the {@link DataAddress} - * of the requested data. - * - * @param token Access token received in input of the Data Plane public API - * @return Data address - */ - @Override - public Result resolve(String token) { - var request = new Request.Builder().url(endpoint).header(HttpHeaders.AUTHORIZATION, token).get().build(); - try (var response = httpClient.execute(request)) { - var body = response.body(); - var stringBody = body != null ? body.string() : null; - if (stringBody == null) { - return Result.failure("Token validation server returned null body"); - } - - if (response.isSuccessful()) { - return Result.success(mapper.readValue(stringBody, DataAddress.class)); - } else { - return Result.failure(format("Call to token validation sever failed: %s - %s. %s", response.code(), response.message(), stringBody)); - } - } catch (IOException e) { - return Result.failure("Unhandled exception occurred during call to token validation server: " + e.getMessage()); - } - } -} diff --git a/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-api/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension b/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-api/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension deleted file mode 100644 index cd51fc686..000000000 --- a/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-api/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension +++ /dev/null @@ -1,20 +0,0 @@ -################################################################################# -# Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) -# -# See the NOTICE file(s) distributed with this work for additional -# information regarding copyright ownership. -# -# This program and the accompanying materials are made available under the -# terms of the Apache License, Version 2.0 which is available at -# https://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. -# -# SPDX-License-Identifier: Apache-2.0 -################################################################################# - -org.eclipse.tractusx.edc.dataplane.proxy.provider.api.DataPlaneProxyProviderApiExtension diff --git a/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-api/src/test/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/api/response/DataPlaneProxyProviderApiExtensionTest.java b/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-api/src/test/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/api/response/DataPlaneProxyProviderApiExtensionTest.java deleted file mode 100644 index d68e4e076..000000000 --- a/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-api/src/test/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/api/response/DataPlaneProxyProviderApiExtensionTest.java +++ /dev/null @@ -1,119 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Mercedes Benz Tech Innovation GmbH - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.dataplane.proxy.provider.api.response; - -import org.eclipse.edc.junit.extensions.DependencyInjectionExtension; -import org.eclipse.edc.spi.monitor.Monitor; -import org.eclipse.edc.spi.system.ServiceExtensionContext; -import org.eclipse.edc.spi.system.configuration.ConfigFactory; -import org.eclipse.edc.spi.system.injection.ObjectFactory; -import org.eclipse.edc.spi.types.TypeManager; -import org.eclipse.edc.web.spi.WebService; -import org.eclipse.tractusx.edc.dataplane.proxy.provider.api.DataPlaneProxyProviderApiExtension; -import org.eclipse.tractusx.edc.dataplane.proxy.provider.api.gateway.ProviderGatewayController; -import org.eclipse.tractusx.edc.dataplane.proxy.provider.api.validation.ProxyProviderDataAddressResolver; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.Mockito; - -import java.util.HashMap; -import java.util.Map; - -@ExtendWith(DependencyInjectionExtension.class) -class DataPlaneProxyProviderApiExtensionTest { - - private DataPlaneProxyProviderApiExtension extension; - - private static final String CONFIG_THREAD_POOL_SIZE_KEY = "tx.dpf.provider.proxy.thread.pool"; - private static final String CONFIG_THREAD_POOL_SIZE_VALUE = "10"; - - private static final String CONFIG_WEB_HTTP_GATEWAY_PATH_KEY = "web.http.gateway.path"; - private static final String CONFIG_WEB_HTTP_GATEWAY_PATH_VALUE = "/api/v1/gateway"; - - private static final String CONFIG_WEB_HTTP_GATEWAY_PORT_KEY = "web.http.gateway.port"; - private static final String CONFIG_WEB_HTTP_GATEWAY_PORT_VALUE = "11111"; - - private static final String CONFIG_CONTROL_PLANE_VALIDATION_ENDPOINT_KEY = "edc.dataplane.token.validation.endpoint"; - private static final String CONFIG_CONTROL_PLANE_VALIDATION_ENDPOINT_VALUE = "http://example.com"; - - // mocks - private ServiceExtensionContext serviceExtensionContext; - private ProviderGatewayController providerGatewayController; - private Monitor monitor; - private WebService webService; - private ProxyProviderDataAddressResolver proxyProviderDataAddressResolver; - private TypeManager typeManager; - - - @BeforeEach - void setup(ObjectFactory factory, ServiceExtensionContext context) { - serviceExtensionContext = Mockito.mock(ServiceExtensionContext.class); - providerGatewayController = Mockito.mock(ProviderGatewayController.class); - monitor = Mockito.mock(Monitor.class); - webService = Mockito.mock(WebService.class); - proxyProviderDataAddressResolver = Mockito.mock(ProxyProviderDataAddressResolver.class); - typeManager = Mockito.mock(TypeManager.class); - - Mockito.when(serviceExtensionContext.getService(ProviderGatewayController.class)) - .thenReturn(providerGatewayController); - Mockito.when(serviceExtensionContext.getMonitor()).thenReturn(monitor); - context.registerService(TypeManager.class, typeManager); - context.registerService(WebService.class, webService); - - extension = factory.constructInstance(DataPlaneProxyProviderApiExtension.class); - } - - private Map getConfig() { - return new HashMap<>() { - { - put(CONFIG_THREAD_POOL_SIZE_KEY, CONFIG_THREAD_POOL_SIZE_VALUE); - put(CONFIG_CONTROL_PLANE_VALIDATION_ENDPOINT_KEY, CONFIG_CONTROL_PLANE_VALIDATION_ENDPOINT_VALUE); - } - }; - } - - private Map getConfigWithContext() { - var config = getConfig(); - config.put(CONFIG_WEB_HTTP_GATEWAY_PATH_KEY, CONFIG_WEB_HTTP_GATEWAY_PATH_VALUE); - config.put(CONFIG_WEB_HTTP_GATEWAY_PORT_KEY, CONFIG_WEB_HTTP_GATEWAY_PORT_VALUE); - return config; - } - - @Test - void testInitialize() { - var config = ConfigFactory.fromMap(getConfig()); - Mockito.when(serviceExtensionContext.getConfig()).thenReturn(config); - - extension.initialize(serviceExtensionContext); - - Mockito.verify(webService, Mockito.times(1)).registerResource(Mockito.any(ProviderGatewayController.class)); - } - - @Test - void testInitializeWithContext() { - var config = ConfigFactory.fromMap(getConfigWithContext()); - Mockito.when(serviceExtensionContext.getConfig()).thenReturn(config); - - extension.initialize(serviceExtensionContext); - - Mockito.verify(webService, Mockito.times(1)).registerResource(Mockito.any(String.class), Mockito.any(ProviderGatewayController.class)); - } -} diff --git a/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-api/src/test/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/api/response/ProxyProviderDataAddressResolverTest.java b/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-api/src/test/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/api/response/ProxyProviderDataAddressResolverTest.java deleted file mode 100644 index 5ffd665a7..000000000 --- a/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-api/src/test/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/api/response/ProxyProviderDataAddressResolverTest.java +++ /dev/null @@ -1,87 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.dataplane.proxy.provider.api.response; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import okhttp3.mockwebserver.MockResponse; -import okhttp3.mockwebserver.MockWebServer; -import org.eclipse.edc.spi.types.TypeManager; -import org.eclipse.edc.spi.types.domain.DataAddress; -import org.eclipse.tractusx.edc.dataplane.proxy.provider.api.validation.ProxyProviderDataAddressResolver; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import java.io.IOException; -import java.util.UUID; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.eclipse.edc.junit.testfixtures.TestUtils.getFreePort; -import static org.eclipse.edc.junit.testfixtures.TestUtils.testHttpClient; - -public class ProxyProviderDataAddressResolverTest { - - private static final ObjectMapper MAPPER = new TypeManager().getMapper(); - private static final int PORT = getFreePort(); - private static final String TOKEN_VALIDATION_SERVER_URL = "http://localhost:" + PORT; - private MockWebServer mockServer; - - private ProxyProviderDataAddressResolver resolver; - - @BeforeEach - public void startServer() throws IOException { - mockServer = new MockWebServer(); - mockServer.start(PORT); - resolver = new ProxyProviderDataAddressResolver(testHttpClient(), TOKEN_VALIDATION_SERVER_URL, MAPPER); - } - - @AfterEach - public void stopServer() throws IOException { - mockServer.shutdown(); - } - - @Test - void verifySuccessTokenValidation() throws JsonProcessingException { - var token = UUID.randomUUID().toString(); - var address = DataAddress.Builder.newInstance() - .type("test-type") - .build(); - - mockServer.enqueue(new MockResponse().setBody(MAPPER.writeValueAsString(address)).setResponseCode(200)); - - - var result = resolver.resolve(token); - - assertThat(result.succeeded()).isTrue(); - assertThat(result.getContent().getType()).isEqualTo(address.getType()); - } - - @Test - void verifyFailedResultReturnedIfServerResponseIsUnsuccessful() throws JsonProcessingException { - var token = UUID.randomUUID().toString(); - - mockServer.enqueue(new MockResponse().setResponseCode(400)); - - var result = resolver.resolve(token); - - assertThat(result.failed()).isTrue(); - } -} diff --git a/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-api/src/test/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/api/response/ResponseHelperTest.java b/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-api/src/test/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/api/response/ResponseHelperTest.java deleted file mode 100644 index 8f9a8cf21..000000000 --- a/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-api/src/test/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/api/response/ResponseHelperTest.java +++ /dev/null @@ -1,37 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.dataplane.proxy.provider.api.response; - -import org.junit.jupiter.api.Test; - -import static jakarta.ws.rs.core.MediaType.APPLICATION_JSON_TYPE; -import static jakarta.ws.rs.core.MediaType.TEXT_PLAIN_TYPE; -import static jakarta.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR; -import static org.assertj.core.api.Assertions.assertThat; -import static org.eclipse.tractusx.edc.dataplane.proxy.provider.api.response.ResponseHelper.createMessageResponse; - -class ResponseHelperTest { - - @Test - void verify_responses() { - assertThat(createMessageResponse(INTERNAL_SERVER_ERROR, "Some error", APPLICATION_JSON_TYPE).getEntity()).isEqualTo("'Some error'"); - assertThat(createMessageResponse(INTERNAL_SERVER_ERROR, "Some error", TEXT_PLAIN_TYPE).getEntity()).isEqualTo("Some error"); - } -} diff --git a/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-core/README.md b/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-core/README.md deleted file mode 100644 index 706a31e78..000000000 --- a/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-core/README.md +++ /dev/null @@ -1,13 +0,0 @@ -# DataPlane Proxy Provider Core - -This extension provide the base service and configuration for the DataPlane Provider Proxy. - -## Configuration - -| Key | Required | Default | Description | -|----------------------------------------------------|----------------------------------------------------------------------------------| -| tx.dpf.proxy.gateway.alias.proxied.path |X | 10 | The backend URL to proxy | -| tx.dpf.proxy.gateway.alias.proxied.edr.forward | | false | If the original EDR must be forwarded to the backend | -| tx.dpf.proxy.gateway.alias.proxied.edr.headerKey | | Edc-Edr | The header name to use when forwarding the EDR | - -Where `alias` is the first part of the subpath after `gateway` mentioned [here](../edc-dataplane-proxy-provider-api/README.md) diff --git a/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-core/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/core/ProxyProviderCoreExtension.java b/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-core/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/core/ProxyProviderCoreExtension.java deleted file mode 100644 index 1395550f8..000000000 --- a/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-core/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/core/ProxyProviderCoreExtension.java +++ /dev/null @@ -1,91 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.dataplane.proxy.provider.core; - -import org.eclipse.edc.runtime.metamodel.annotation.Extension; -import org.eclipse.edc.runtime.metamodel.annotation.Inject; -import org.eclipse.edc.runtime.metamodel.annotation.Provides; -import org.eclipse.edc.spi.monitor.Monitor; -import org.eclipse.edc.spi.security.Vault; -import org.eclipse.edc.spi.system.ServiceExtension; -import org.eclipse.edc.spi.system.ServiceExtensionContext; -import org.eclipse.tractusx.edc.dataplane.proxy.provider.core.gateway.auth.AuthorizationHandlerRegistryImpl; -import org.eclipse.tractusx.edc.dataplane.proxy.provider.core.gateway.configuration.GatewayConfigurationRegistryImpl; -import org.eclipse.tractusx.edc.dataplane.proxy.spi.provider.gateway.authorization.AuthorizationExtension; -import org.eclipse.tractusx.edc.dataplane.proxy.spi.provider.gateway.authorization.AuthorizationHandlerRegistry; -import org.eclipse.tractusx.edc.dataplane.proxy.spi.provider.gateway.configuration.GatewayConfigurationRegistry; -import org.jetbrains.annotations.NotNull; - -import static java.lang.String.format; -import static org.eclipse.edc.spi.result.Result.success; -import static org.eclipse.tractusx.edc.dataplane.proxy.provider.core.gateway.configuration.GatewayConfigurationLoader.loadConfiguration; -import static org.eclipse.tractusx.edc.dataplane.proxy.spi.provider.gateway.configuration.GatewayConfiguration.NO_AUTHORIZATION; - -/** - * Registers default services for the data plane provider proxy implementation. - */ -@Extension(value = ProxyProviderCoreExtension.NAME) -@Provides({ GatewayConfigurationRegistry.class, AuthorizationHandlerRegistry.class }) -public class ProxyProviderCoreExtension implements ServiceExtension { - static final String NAME = "Data Plane Provider Proxy Core"; - - @Inject(required = false) - private AuthorizationExtension authorizationExtension; - - @Inject - private Vault vault; - - @Inject - private Monitor monitor; - - @Override - public String name() { - return NAME; - } - - @Override - public void initialize(ServiceExtensionContext context) { - var configurationRegistry = new GatewayConfigurationRegistryImpl(); - context.registerService(GatewayConfigurationRegistry.class, configurationRegistry); - - if (authorizationExtension == null) { - context.getMonitor().info("Proxy JWT authorization is configured to only validate tokens and not provide path access control"); - authorizationExtension = (c, p) -> success(); - } - - var authorizationRegistry = createAuthorizationRegistry(); - context.registerService(AuthorizationHandlerRegistry.class, authorizationRegistry); - - loadConfiguration(context).forEach(configuration -> { - monitor.info(format("Registering gateway configuration alias `%s` to %s", configuration.getAlias(), configuration.getProxiedPath())); - configurationRegistry.register(configuration); - }); - } - - @NotNull - private AuthorizationHandlerRegistryImpl createAuthorizationRegistry() { - var authorizationRegistry = new AuthorizationHandlerRegistryImpl(); - - authorizationRegistry.register(NO_AUTHORIZATION, (t, p) -> success()); - - return authorizationRegistry; - } - -} diff --git a/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-core/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/core/gateway/configuration/GatewayConfigurationLoader.java b/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-core/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/core/gateway/configuration/GatewayConfigurationLoader.java deleted file mode 100644 index 3be3bc6f6..000000000 --- a/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-core/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/core/gateway/configuration/GatewayConfigurationLoader.java +++ /dev/null @@ -1,57 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.dataplane.proxy.provider.core.gateway.configuration; - -import org.eclipse.edc.spi.system.ServiceExtensionContext; -import org.eclipse.edc.spi.system.configuration.Config; -import org.eclipse.tractusx.edc.dataplane.proxy.spi.provider.gateway.configuration.GatewayConfiguration; - -import java.util.List; - -import static java.util.stream.Collectors.toList; -import static org.eclipse.tractusx.edc.dataplane.proxy.spi.provider.gateway.configuration.GatewayConfiguration.NO_AUTHORIZATION; - -/** - * Loads gateway configuration from the {@link #TX_GATEWAY_PREFIX} prefix. - */ -public class GatewayConfigurationLoader { - public static final String DEFAULT_FORWARD_EDR_HEADER_KEY = "Edc-Edr"; - static final String TX_GATEWAY_PREFIX = "tx.dpf.proxy.gateway"; - static final String AUTHORIZATION_TYPE = "authorization.type"; - static final String PROXIED_PATH = "proxied.path"; - static final String FORWARD_EDR = "proxied.edr.forward"; - static final String FORWARD_EDR_HEADER_KEY = "proxied.edr.headerKey"; - - public static List loadConfiguration(ServiceExtensionContext context) { - var root = context.getConfig(TX_GATEWAY_PREFIX); - return root.partition().map(GatewayConfigurationLoader::createGatewayConfiguration).collect(toList()); - } - - private static GatewayConfiguration createGatewayConfiguration(Config config) { - return GatewayConfiguration.Builder.newInstance() - .alias(config.currentNode()) - .authorizationType(config.getString(AUTHORIZATION_TYPE, NO_AUTHORIZATION)) - .forwardEdrToken(config.getBoolean(FORWARD_EDR, false)) - .forwardEdrTokenHeaderKey(config.getString(FORWARD_EDR_HEADER_KEY, DEFAULT_FORWARD_EDR_HEADER_KEY)) - - .proxiedPath(config.getString(PROXIED_PATH)) - .build(); - } -} diff --git a/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-core/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension b/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-core/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension deleted file mode 100644 index c3031b319..000000000 --- a/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-core/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension +++ /dev/null @@ -1,20 +0,0 @@ -################################################################################# -# Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) -# -# See the NOTICE file(s) distributed with this work for additional -# information regarding copyright ownership. -# -# This program and the accompanying materials are made available under the -# terms of the Apache License, Version 2.0 which is available at -# https://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. -# -# SPDX-License-Identifier: Apache-2.0 -################################################################################# - -org.eclipse.tractusx.edc.dataplane.proxy.provider.core.ProxyProviderCoreExtension diff --git a/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-core/src/test/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/core/gateway/auth/AuthorizationHandlerRegistryImplTest.java b/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-core/src/test/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/core/gateway/auth/AuthorizationHandlerRegistryImplTest.java deleted file mode 100644 index 59bf7b0fd..000000000 --- a/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-core/src/test/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/core/gateway/auth/AuthorizationHandlerRegistryImplTest.java +++ /dev/null @@ -1,37 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.dataplane.proxy.provider.core.gateway.auth; - -import org.eclipse.tractusx.edc.dataplane.proxy.spi.provider.gateway.authorization.AuthorizationHandler; -import org.junit.jupiter.api.Test; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.mock; - -class AuthorizationHandlerRegistryImplTest { - - @Test - void verify_registration() { - var registry = new AuthorizationHandlerRegistryImpl(); - registry.register("alias", mock(AuthorizationHandler.class)); - - assertThat(registry.getHandler("alias")).isNotNull(); - } -} diff --git a/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-core/src/test/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/core/gateway/configuration/GatewayConfigurationLoaderTest.java b/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-core/src/test/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/core/gateway/configuration/GatewayConfigurationLoaderTest.java deleted file mode 100644 index b087cb078..000000000 --- a/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-core/src/test/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/core/gateway/configuration/GatewayConfigurationLoaderTest.java +++ /dev/null @@ -1,57 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.dataplane.proxy.provider.core.gateway.configuration; - -import org.eclipse.edc.spi.system.ServiceExtensionContext; -import org.eclipse.edc.spi.system.configuration.ConfigFactory; -import org.junit.jupiter.api.Test; - -import java.util.Map; - -import static java.lang.String.format; -import static org.assertj.core.api.Assertions.assertThat; -import static org.eclipse.tractusx.edc.dataplane.proxy.provider.core.gateway.configuration.GatewayConfigurationLoader.AUTHORIZATION_TYPE; -import static org.eclipse.tractusx.edc.dataplane.proxy.provider.core.gateway.configuration.GatewayConfigurationLoader.PROXIED_PATH; -import static org.eclipse.tractusx.edc.dataplane.proxy.provider.core.gateway.configuration.GatewayConfigurationLoader.TX_GATEWAY_PREFIX; -import static org.eclipse.tractusx.edc.dataplane.proxy.spi.provider.gateway.configuration.GatewayConfiguration.NO_AUTHORIZATION; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -class GatewayConfigurationLoaderTest { - - @Test - void verify_loadConfiguration() { - var context = mock(ServiceExtensionContext.class); - - var config = ConfigFactory.fromMap( - Map.of(format("alias.%s", AUTHORIZATION_TYPE), NO_AUTHORIZATION, - format("alias.%s", PROXIED_PATH), "https://test.com")); - when(context.getConfig(TX_GATEWAY_PREFIX)).thenReturn(config); - - var configurations = GatewayConfigurationLoader.loadConfiguration(context); - - assertThat(configurations).isNotEmpty(); - var configuration = configurations.get(0); - - assertThat(configuration.getAlias()).isEqualTo("alias"); - assertThat(configuration.getAuthorizationType()).isEqualTo(NO_AUTHORIZATION); - assertThat(configuration.getProxiedPath()).isEqualTo("https://test.com"); - } -} diff --git a/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-core/src/test/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/core/gateway/configuration/GatewayConfigurationRegistryImplTest.java b/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-core/src/test/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/core/gateway/configuration/GatewayConfigurationRegistryImplTest.java deleted file mode 100644 index 3bd00bbc6..000000000 --- a/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-core/src/test/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/core/gateway/configuration/GatewayConfigurationRegistryImplTest.java +++ /dev/null @@ -1,36 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.dataplane.proxy.provider.core.gateway.configuration; - -import org.eclipse.tractusx.edc.dataplane.proxy.spi.provider.gateway.configuration.GatewayConfiguration; -import org.junit.jupiter.api.Test; - -import static org.assertj.core.api.Assertions.assertThat; - -class GatewayConfigurationRegistryImplTest { - - @Test - void verify_Configuration() { - var registry = new GatewayConfigurationRegistryImpl(); - registry.register(GatewayConfiguration.Builder.newInstance().proxiedPath("https://test.com").alias("alias").build()); - - assertThat(registry.getConfiguration("alias")).isNotNull(); - } -} diff --git a/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-spi/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/spi/provider/gateway/authorization/AuthorizationExtension.java b/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-spi/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/spi/provider/gateway/authorization/AuthorizationExtension.java deleted file mode 100644 index 1f520bea2..000000000 --- a/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-spi/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/spi/provider/gateway/authorization/AuthorizationExtension.java +++ /dev/null @@ -1,39 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.dataplane.proxy.spi.provider.gateway.authorization; - -import org.eclipse.edc.spi.iam.ClaimToken; -import org.eclipse.edc.spi.result.Result; - -/** - * Performs an authorization check for the given path against a set of claims. - */ -public interface AuthorizationExtension { - - /** - * Performs an authorization check for the given path against the presented claims. The path is the request alias path, not - * the proxied path. - * - * @param token the validated claim token - * @param path the request alias path, not the dereferenced proxied path - */ - Result authorize(ClaimToken token, String path); - -} diff --git a/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-spi/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/spi/provider/gateway/authorization/AuthorizationHandler.java b/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-spi/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/spi/provider/gateway/authorization/AuthorizationHandler.java deleted file mode 100644 index b5a1752b3..000000000 --- a/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-spi/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/spi/provider/gateway/authorization/AuthorizationHandler.java +++ /dev/null @@ -1,38 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.dataplane.proxy.spi.provider.gateway.authorization; - -import org.eclipse.edc.spi.result.Result; - -/** - * Performs an authorization using the request token for a given path. Implementation support different token formats such as JWT. - */ -@FunctionalInterface -public interface AuthorizationHandler { - - /** - * Performs the authorization check. - * - * @param token the unvalidated token - * @param path the request alias path, not the dereferenced proxied path - */ - Result authorize(String token, String path); - -} diff --git a/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-spi/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/spi/provider/gateway/configuration/GatewayConfiguration.java b/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-spi/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/spi/provider/gateway/configuration/GatewayConfiguration.java deleted file mode 100644 index 6d797a8b0..000000000 --- a/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-spi/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/spi/provider/gateway/configuration/GatewayConfiguration.java +++ /dev/null @@ -1,107 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.dataplane.proxy.spi.provider.gateway.configuration; - -import static java.util.Objects.requireNonNull; - -/** - * A configuration that exposes a proxied endpoint via an alias. Each configuration is associated with an extensible {@code authorizationType} such as - * {@link #NO_AUTHORIZATION} (the default) and {@link #NO_AUTHORIZATION}. The {@code proxiedPath} will be prepended to a request sub-path to create an absolute endpoint - * URL where data is fetched from. - */ -public class GatewayConfiguration { - public static final String NO_AUTHORIZATION = "none"; - - private String alias; - private String proxiedPath; - private String authorizationType = NO_AUTHORIZATION; - - private boolean forwardEdrToken; - private String forwardEdrTokenHeaderKey; - - - private GatewayConfiguration() { - } - - public String getAlias() { - return alias; - } - - public String getProxiedPath() { - return proxiedPath; - } - - public String getAuthorizationType() { - return authorizationType; - } - - public boolean isForwardEdrToken() { - return forwardEdrToken; - } - - public String getForwardEdrTokenHeaderKey() { - return forwardEdrTokenHeaderKey; - } - - public static class Builder { - - private final GatewayConfiguration configuration; - - private Builder() { - configuration = new GatewayConfiguration(); - } - - public static Builder newInstance() { - return new Builder(); - } - - public Builder alias(String alias) { - this.configuration.alias = alias; - return this; - } - - public Builder proxiedPath(String proxiedPath) { - this.configuration.proxiedPath = proxiedPath; - return this; - } - - public Builder authorizationType(String authorizationType) { - this.configuration.authorizationType = authorizationType; - return this; - } - - public Builder forwardEdrToken(boolean forwardEdrToken) { - this.configuration.forwardEdrToken = forwardEdrToken; - return this; - } - - public Builder forwardEdrTokenHeaderKey(String forwardEdrTokenHeaderKey) { - this.configuration.forwardEdrTokenHeaderKey = forwardEdrTokenHeaderKey; - return this; - } - - public GatewayConfiguration build() { - requireNonNull(configuration.alias, "alias"); - requireNonNull(configuration.proxiedPath, "proxiedPath"); - requireNonNull(configuration.authorizationType, "authorizationType"); - return configuration; - } - } -} diff --git a/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-spi/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/spi/provider/gateway/configuration/GatewayConfigurationRegistry.java b/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-spi/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/spi/provider/gateway/configuration/GatewayConfigurationRegistry.java deleted file mode 100644 index 11d4454ea..000000000 --- a/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-spi/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/spi/provider/gateway/configuration/GatewayConfigurationRegistry.java +++ /dev/null @@ -1,40 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.dataplane.proxy.spi.provider.gateway.configuration; - -import org.jetbrains.annotations.Nullable; - -/** - * Manages {@link GatewayConfiguration}s. - */ -public interface GatewayConfigurationRegistry { - - /** - * Returns the configuration for the given alias or null if not found. - */ - @Nullable - GatewayConfiguration getConfiguration(String alias); - - /** - * Registers a configuration for the given alias. - */ - void register(GatewayConfiguration configuration); - -} diff --git a/edc-extensions/dataplane/dataplane-selector-configuration/src/main/java/org/eclipse/tractusx/edc/dataplane/selector/configuration/DataPlaneSelectorConfigurationServiceExtension.java b/edc-extensions/dataplane/dataplane-selector-configuration/src/main/java/org/eclipse/tractusx/edc/dataplane/selector/configuration/DataPlaneSelectorConfigurationServiceExtension.java index ab156d163..a1f175d58 100644 --- a/edc-extensions/dataplane/dataplane-selector-configuration/src/main/java/org/eclipse/tractusx/edc/dataplane/selector/configuration/DataPlaneSelectorConfigurationServiceExtension.java +++ b/edc-extensions/dataplane/dataplane-selector-configuration/src/main/java/org/eclipse/tractusx/edc/dataplane/selector/configuration/DataPlaneSelectorConfigurationServiceExtension.java @@ -33,18 +33,21 @@ import org.eclipse.edc.spi.system.configuration.Config; import java.util.Arrays; -import java.util.List; import java.util.Map; import java.util.function.Predicate; import java.util.stream.Collectors; -@Requires({DataPlaneSelectorService.class}) +import static java.lang.String.format; +import static java.lang.String.join; + +@Requires({ DataPlaneSelectorService.class }) public class DataPlaneSelectorConfigurationServiceExtension implements ServiceExtension { public static final String CONFIG_PREFIX = "edc.dataplane.selector"; public static final String URL_SUFFIX = "url"; public static final String DESTINATION_TYPES_SUFFIX = "destinationtypes"; public static final String SOURCE_TYPES_SUFFIX = "sourcetypes"; + public static final String TRANSFER_TYPES_SUFFIX = "transfertypes"; public static final String PROPERTIES_SUFFIX = "properties"; public static final String PUBLIC_API_URL_PROPERTY = "publicApiUrl"; @@ -52,7 +55,7 @@ public class DataPlaneSelectorConfigurationServiceExtension implements ServiceEx private static final String COMMA = ","; private static final String LOG_MISSING_CONFIGURATION = NAME + ": Missing configuration for " + CONFIG_PREFIX + ".%s.%s"; private static final String LOG_SKIP_BC_MISSING_CONFIGURATION = NAME + ": Configuration issues. Skip registering of Data Plane Instance '%s'"; - private static final String LOG_REGISTERED = NAME + ": Registered Data Plane Instance. (id=%s, url=%s, sourceTypes=%s, destinationTypes=%s, properties=)"; + private static final String LOG_REGISTERED = NAME + ": Registered Data Plane Instance. (id=%s, url=%s, sourceTypes=%s, destinationTypes=%s, transferType=%s, properties=)"; private Monitor monitor; private DataPlaneSelectorService dataPlaneSelectorService; @@ -68,77 +71,80 @@ public void initialize(final ServiceExtensionContext serviceExtensionContext) { serviceExtensionContext.getService(DataPlaneSelectorService.class); this.monitor = serviceExtensionContext.getMonitor(); - final Config config = serviceExtensionContext.getConfig(CONFIG_PREFIX); + var config = serviceExtensionContext.getConfig(CONFIG_PREFIX); config.partition().forEach(this::configureDataPlaneInstance); } private void configureDataPlaneInstance(final Config config) { - final String id = config.currentNode(); + var id = config.currentNode(); - final String url = config.getString(URL_SUFFIX, ""); - final List sourceTypes = + var url = config.getString(URL_SUFFIX, ""); + var sourceTypes = Arrays.stream(config.getString(SOURCE_TYPES_SUFFIX, "").split(COMMA)) .map(String::trim) .filter(Predicate.not(String::isEmpty)) .distinct() .collect(Collectors.toList()); - final List destinationTypes = + var destinationTypes = Arrays.stream(config.getString(DESTINATION_TYPES_SUFFIX, "").split(COMMA)) .map(String::trim) .filter(Predicate.not(String::isEmpty)) .distinct() .collect(Collectors.toList()); - final String propertiesJson = config.getString(PROPERTIES_SUFFIX, "{}"); + var propertiesJson = config.getString(PROPERTIES_SUFFIX, "{}"); + + var transferTypes = Arrays.stream(config.getString(TRANSFER_TYPES_SUFFIX, "").split(COMMA)) + .map(String::trim) + .filter(Predicate.not(String::isEmpty)) + .distinct() + .collect(Collectors.toList()); if (url.isEmpty()) { - monitor.warning(String.format(LOG_MISSING_CONFIGURATION, id, URL_SUFFIX)); + monitor.warning(format(LOG_MISSING_CONFIGURATION, id, URL_SUFFIX)); } if (sourceTypes.isEmpty()) { - monitor.warning(String.format(LOG_MISSING_CONFIGURATION, id, SOURCE_TYPES_SUFFIX)); + monitor.warning(format(LOG_MISSING_CONFIGURATION, id, SOURCE_TYPES_SUFFIX)); } if (destinationTypes.isEmpty()) { - monitor.warning(String.format(LOG_MISSING_CONFIGURATION, id, DESTINATION_TYPES_SUFFIX)); + monitor.warning(format(LOG_MISSING_CONFIGURATION, id, DESTINATION_TYPES_SUFFIX)); + } + + if (transferTypes.isEmpty()) { + monitor.warning(format(LOG_MISSING_CONFIGURATION, id, TRANSFER_TYPES_SUFFIX)); } - final Map properties; + Map properties; try { - ObjectMapper mapper = new ObjectMapper(); - properties = mapper.readValue(propertiesJson, new TypeReference>() { + var mapper = new ObjectMapper(); + properties = mapper.readValue(propertiesJson, new TypeReference<>() { }); } catch (JsonProcessingException e) { throw new EdcException(e); } - final boolean missingPublicApiProperty = !properties.containsKey(PUBLIC_API_URL_PROPERTY); + var missingPublicApiProperty = !properties.containsKey(PUBLIC_API_URL_PROPERTY); if (missingPublicApiProperty) { - monitor.warning(String.format(LOG_MISSING_CONFIGURATION, id, PROPERTIES_SUFFIX) + "." + PUBLIC_API_URL_PROPERTY); + monitor.warning(format(LOG_MISSING_CONFIGURATION, id, PROPERTIES_SUFFIX) + "." + PUBLIC_API_URL_PROPERTY); } - final boolean invalidConfiguration = - url.isEmpty() || sourceTypes.isEmpty() || destinationTypes.isEmpty(); + var invalidConfiguration = url.isEmpty() || sourceTypes.isEmpty() || destinationTypes.isEmpty(); if (invalidConfiguration || missingPublicApiProperty) { - monitor.warning(String.format(LOG_SKIP_BC_MISSING_CONFIGURATION, id)); + monitor.warning(format(LOG_SKIP_BC_MISSING_CONFIGURATION, id)); return; } - final DataPlaneInstance.Builder builder = - DataPlaneInstance.Builder.newInstance().id(id).url(url); + var builder = DataPlaneInstance.Builder.newInstance().id(id).url(url); sourceTypes.forEach(builder::allowedSourceType); destinationTypes.forEach(builder::allowedDestType); + transferTypes.forEach(builder::allowedTransferType); properties.forEach(builder::property); dataPlaneSelectorService.addInstance(builder.build()); - monitor.debug( - String.format( - LOG_REGISTERED, - id, - url, - String.join(", ", sourceTypes), - String.join(", ", destinationTypes))); + monitor.debug(LOG_REGISTERED.formatted(id, url, join(", ", sourceTypes), join(", ", destinationTypes), join(", ", transferTypes))); } } diff --git a/edc-extensions/dataplane/dataplane-selector-configuration/src/test/java/org/eclipse/tractusx/edc/dataplane/selector/configuration/DataPlaneSelectorConfigurationServiceExtensionEdcExtensionTest.java b/edc-extensions/dataplane/dataplane-selector-configuration/src/test/java/org/eclipse/tractusx/edc/dataplane/selector/configuration/DataPlaneSelectorConfigurationServiceExtensionEdcExtensionTest.java deleted file mode 100644 index eaa6d6434..000000000 --- a/edc-extensions/dataplane/dataplane-selector-configuration/src/test/java/org/eclipse/tractusx/edc/dataplane/selector/configuration/DataPlaneSelectorConfigurationServiceExtensionEdcExtensionTest.java +++ /dev/null @@ -1,161 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2022 Mercedes-Benz Tech Innovation GmbH - * Copyright (c) 2021,2022 Contributors to the Eclipse Foundation - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.dataplane.selector.configuration; - -import org.eclipse.edc.connector.dataplane.selector.spi.DataPlaneSelectorService; -import org.eclipse.edc.junit.annotations.ComponentTest; -import org.eclipse.edc.junit.extensions.EdcExtension; -import org.eclipse.edc.runtime.metamodel.annotation.Provides; -import org.eclipse.edc.spi.system.ServiceExtension; -import org.eclipse.edc.spi.system.ServiceExtensionContext; -import org.eclipse.edc.spi.types.domain.DataAddress; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.Mockito; - -import java.util.HashMap; -import java.util.Map; - -@ComponentTest -@ExtendWith(EdcExtension.class) -class DataPlaneSelectorConfigurationServiceExtensionEdcExtensionTest { - - private static final String S3_BUCKET = "s3-bucket"; - private static final String BLOB_STORAGE = "blob-storage"; - private static final String LOCAL_FILE_SYSTEM = "local-file-system"; - - private static final String DATA_PLANE_INSTANCE_ID = "test-plane"; - private static final String DATA_PLANE_INSTANCE_URL = "http://127.0.0.1:8080/test"; - private static final String DATA_PLANE_INSTANCE_SOURCE_TYPES = - String.format("%s, %s", S3_BUCKET, BLOB_STORAGE); - private static final String DATA_PLANE_INSTANCE_DESTINATION_TYPES = LOCAL_FILE_SYSTEM; - - // mocks - private DataPlaneSelectorService dataPlaneSelectorService; - - @BeforeEach - final void beforeEach(EdcExtension extension) { - dataPlaneSelectorService = Mockito.mock(DataPlaneSelectorService.class); - - extension.registerSystemExtension(ServiceExtension.class, new TestExtension()); - extension.setConfiguration(getConfig()); - } - - private Map getConfig() { - final String urlKey = - String.format( - "%s.%s.%s", - DataPlaneSelectorConfigurationServiceExtension.CONFIG_PREFIX, - DATA_PLANE_INSTANCE_ID, - DataPlaneSelectorConfigurationServiceExtension.URL_SUFFIX); - final String sourceTypesKey = - String.format( - "%s.%s.%s", - DataPlaneSelectorConfigurationServiceExtension.CONFIG_PREFIX, - DATA_PLANE_INSTANCE_ID, - DataPlaneSelectorConfigurationServiceExtension.SOURCE_TYPES_SUFFIX); - final String destinationTypesKey = - String.format( - "%s.%s.%s", - DataPlaneSelectorConfigurationServiceExtension.CONFIG_PREFIX, - DATA_PLANE_INSTANCE_ID, - DataPlaneSelectorConfigurationServiceExtension.DESTINATION_TYPES_SUFFIX); - final String propertiesKey = - String.format( - "%s.%s.%s", - DataPlaneSelectorConfigurationServiceExtension.CONFIG_PREFIX, - DATA_PLANE_INSTANCE_ID, - DataPlaneSelectorConfigurationServiceExtension.PROPERTIES_SUFFIX); - - return new HashMap<>() { - { - put(urlKey, DATA_PLANE_INSTANCE_URL); - put(sourceTypesKey, DATA_PLANE_INSTANCE_SOURCE_TYPES); - put(destinationTypesKey, DATA_PLANE_INSTANCE_DESTINATION_TYPES); - put( - propertiesKey, - String.format( - "{ \"%s\": \"%s\" }", - DataPlaneSelectorConfigurationServiceExtension.PUBLIC_API_URL_PROPERTY, - DATA_PLANE_INSTANCE_URL)); - } - }; - } - - @Test - void registersDataPlaneInstance() { - Mockito.verify(dataPlaneSelectorService, Mockito.times(1)) - .addInstance( - Mockito.argThat( - dataPlaneInstance -> { - final DataAddress s3Source = - DataAddress.Builder.newInstance().type(S3_BUCKET).build(); - final DataAddress blobSource = - DataAddress.Builder.newInstance().type(BLOB_STORAGE).build(); - final DataAddress fsSink = - DataAddress.Builder.newInstance().type(LOCAL_FILE_SYSTEM).build(); - - final boolean matchingId = - dataPlaneInstance.getId().equals(DATA_PLANE_INSTANCE_ID); - final boolean matchingUrl = - dataPlaneInstance.getUrl().toString().equals(DATA_PLANE_INSTANCE_URL); - final boolean matchingCanHandleS3ToFileSystem = - dataPlaneInstance.canHandle(s3Source, fsSink); - final boolean matchingCanHandleBlobToFileSystem = - dataPlaneInstance.canHandle(blobSource, fsSink); - - if (!matchingId) { - System.err.printf( - "Expected ID %s, but got %s%n", - DATA_PLANE_INSTANCE_ID, dataPlaneInstance.getId()); - } - if (!matchingUrl) { - System.err.printf( - "Expected URL %s, but got %s%n", - DATA_PLANE_INSTANCE_URL, dataPlaneInstance.getUrl()); - } - if (!matchingCanHandleS3ToFileSystem) { - System.err.printf( - "Expected Instance to be handle source %s and sink %s%n", - S3_BUCKET, LOCAL_FILE_SYSTEM); - } - if (!matchingCanHandleBlobToFileSystem) { - System.err.printf( - "Expected Instance to be handle source %s and sink %s%n", - BLOB_STORAGE, LOCAL_FILE_SYSTEM); - } - - return matchingId && - matchingUrl && - matchingCanHandleS3ToFileSystem && - matchingCanHandleBlobToFileSystem; - })); - } - - @Provides({DataPlaneSelectorService.class}) - private class TestExtension implements ServiceExtension { - - public void initialize(ServiceExtensionContext context) { - context.registerService(DataPlaneSelectorService.class, dataPlaneSelectorService); - } - } -} diff --git a/edc-extensions/dataplane/dataplane-selector-configuration/src/test/java/org/eclipse/tractusx/edc/dataplane/selector/configuration/DataPlaneSelectorConfigurationServiceExtensionTest.java b/edc-extensions/dataplane/dataplane-selector-configuration/src/test/java/org/eclipse/tractusx/edc/dataplane/selector/configuration/DataPlaneSelectorConfigurationServiceExtensionTest.java index 55b685242..549d23705 100644 --- a/edc-extensions/dataplane/dataplane-selector-configuration/src/test/java/org/eclipse/tractusx/edc/dataplane/selector/configuration/DataPlaneSelectorConfigurationServiceExtensionTest.java +++ b/edc-extensions/dataplane/dataplane-selector-configuration/src/test/java/org/eclipse/tractusx/edc/dataplane/selector/configuration/DataPlaneSelectorConfigurationServiceExtensionTest.java @@ -24,10 +24,8 @@ import org.eclipse.edc.spi.EdcException; import org.eclipse.edc.spi.monitor.Monitor; import org.eclipse.edc.spi.system.ServiceExtensionContext; -import org.eclipse.edc.spi.system.configuration.Config; import org.eclipse.edc.spi.system.configuration.ConfigFactory; import org.eclipse.edc.spi.types.domain.DataAddress; -import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtensionContext; @@ -35,12 +33,27 @@ import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.ArgumentsProvider; import org.junit.jupiter.params.provider.ArgumentsSource; -import org.mockito.Mockito; import java.util.HashMap; import java.util.Map; import java.util.stream.Stream; +import static org.eclipse.tractusx.edc.dataplane.selector.configuration.DataPlaneSelectorConfigurationServiceExtension.CONFIG_PREFIX; +import static org.eclipse.tractusx.edc.dataplane.selector.configuration.DataPlaneSelectorConfigurationServiceExtension.DESTINATION_TYPES_SUFFIX; +import static org.eclipse.tractusx.edc.dataplane.selector.configuration.DataPlaneSelectorConfigurationServiceExtension.PROPERTIES_SUFFIX; +import static org.eclipse.tractusx.edc.dataplane.selector.configuration.DataPlaneSelectorConfigurationServiceExtension.PUBLIC_API_URL_PROPERTY; +import static org.eclipse.tractusx.edc.dataplane.selector.configuration.DataPlaneSelectorConfigurationServiceExtension.SOURCE_TYPES_SUFFIX; +import static org.eclipse.tractusx.edc.dataplane.selector.configuration.DataPlaneSelectorConfigurationServiceExtension.URL_SUFFIX; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.Mockito.anyString; +import static org.mockito.Mockito.argThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + class DataPlaneSelectorConfigurationServiceExtensionTest { private static final String S3_BUCKET = "s3-bucket"; private static final String BLOB_STORAGE = "blob-storage"; @@ -48,172 +61,92 @@ class DataPlaneSelectorConfigurationServiceExtensionTest { private static final String DATA_PLANE_INSTANCE_ID = "test-plane"; private static final String DATA_PLANE_INSTANCE_URL = "http://127.0.0.1:8080/test"; - private static final String DATA_PLANE_INSTANCE_SOURCE_TYPES = - String.format("%s, %s", S3_BUCKET, BLOB_STORAGE); + private static final String DATA_PLANE_INSTANCE_SOURCE_TYPES = "%s, %s".formatted(S3_BUCKET, BLOB_STORAGE); private static final String DATA_PLANE_INSTANCE_DESTINATION_TYPES = LOCAL_FILE_SYSTEM; - private static final String URL_KEY = - String.format( - "%s.%s", - DATA_PLANE_INSTANCE_ID, DataPlaneSelectorConfigurationServiceExtension.URL_SUFFIX); - private static final String SOURCE_TYPES_KEY = - String.format( - "%s.%s", - DATA_PLANE_INSTANCE_ID, - DataPlaneSelectorConfigurationServiceExtension.SOURCE_TYPES_SUFFIX); - private static final String DESTINATION_TYPES_KEY = - String.format( - "%s.%s", - DATA_PLANE_INSTANCE_ID, - DataPlaneSelectorConfigurationServiceExtension.DESTINATION_TYPES_SUFFIX); - private static final String PROPERTIES_KEY = - String.format( - "%s.%s", - DATA_PLANE_INSTANCE_ID, DataPlaneSelectorConfigurationServiceExtension.PROPERTIES_SUFFIX); - + private static final String URL_KEY = "%s.%s".formatted(DATA_PLANE_INSTANCE_ID, URL_SUFFIX); + private static final String SOURCE_TYPES_KEY = "%s.%s".formatted(DATA_PLANE_INSTANCE_ID, SOURCE_TYPES_SUFFIX); + private static final String DESTINATION_TYPES_KEY = "%s.%s".formatted(DATA_PLANE_INSTANCE_ID, DESTINATION_TYPES_SUFFIX); + private static final String PROPERTIES_KEY = "%s.%s".formatted(DATA_PLANE_INSTANCE_ID, PROPERTIES_SUFFIX); + private final ServiceExtensionContext serviceExtensionContext = mock(); + private final DataPlaneSelectorService dataPlaneSelectorService = mock(); + private final Monitor monitor = mock(); private DataPlaneSelectorConfigurationServiceExtension extension; - // mocks - private ServiceExtensionContext serviceExtensionContext; - private DataPlaneSelectorService dataPlaneSelectorService; - private Monitor monitor; - @BeforeEach void setup() { extension = new DataPlaneSelectorConfigurationServiceExtension(); - serviceExtensionContext = Mockito.mock(ServiceExtensionContext.class); - dataPlaneSelectorService = Mockito.mock(DataPlaneSelectorService.class); - monitor = Mockito.mock(Monitor.class); - - Mockito.when(serviceExtensionContext.getService(DataPlaneSelectorService.class)) + when(serviceExtensionContext.getService(DataPlaneSelectorService.class)) .thenReturn(dataPlaneSelectorService); - Mockito.when(serviceExtensionContext.getMonitor()).thenReturn(monitor); - } - - private Map getConfig() { - return new HashMap<>() { - { - put(URL_KEY, DATA_PLANE_INSTANCE_URL); - put(SOURCE_TYPES_KEY, DATA_PLANE_INSTANCE_SOURCE_TYPES); - put(DESTINATION_TYPES_KEY, DATA_PLANE_INSTANCE_DESTINATION_TYPES); - put( - PROPERTIES_KEY, - String.format( - "{ \"%s\": \"%s\" }", - DataPlaneSelectorConfigurationServiceExtension.PUBLIC_API_URL_PROPERTY, - DATA_PLANE_INSTANCE_URL)); - } - }; + when(serviceExtensionContext.getMonitor()).thenReturn(monitor); } @Test void testName() { - final DataPlaneSelectorConfigurationServiceExtension extension = - new DataPlaneSelectorConfigurationServiceExtension(); + var extension = new DataPlaneSelectorConfigurationServiceExtension(); - Assertions.assertNotNull(extension.name()); - Assertions.assertEquals("Data Plane Selector Configuration Extension", extension.name()); + assertNotNull(extension.name()); + assertEquals("Data Plane Selector Configuration Extension", extension.name()); } @Test void testInitialize() { - final Config config = ConfigFactory.fromMap(getConfig()); - - Mockito.when(serviceExtensionContext.getConfig("edc.dataplane.selector")).thenReturn(config); - + var config = ConfigFactory.fromMap(getConfig()); + when(serviceExtensionContext.getConfig("edc.dataplane.selector")).thenReturn(config); extension.initialize(serviceExtensionContext); - Mockito.verify(serviceExtensionContext, Mockito.times(1)) - .getService(DataPlaneSelectorService.class); - Mockito.verify(serviceExtensionContext, Mockito.times(1)).getMonitor(); - Mockito.when( - serviceExtensionContext.getConfig( - DataPlaneSelectorConfigurationServiceExtension.CONFIG_PREFIX)) + verify(serviceExtensionContext, times(1)).getService(DataPlaneSelectorService.class); + verify(serviceExtensionContext, times(1)).getMonitor(); + when(serviceExtensionContext.getConfig(CONFIG_PREFIX)) .thenReturn(config); - Mockito.verify(dataPlaneSelectorService, Mockito.times(1)) - .addInstance( - Mockito.argThat( - dataPlaneInstance -> { - final DataAddress s3Source = - DataAddress.Builder.newInstance().type(S3_BUCKET).build(); - final DataAddress blobSource = - DataAddress.Builder.newInstance().type(BLOB_STORAGE).build(); - final DataAddress fsSink = - DataAddress.Builder.newInstance().type(LOCAL_FILE_SYSTEM).build(); - - final boolean matchingId = - dataPlaneInstance.getId().equals(DATA_PLANE_INSTANCE_ID); - final boolean matchingUrl = - dataPlaneInstance.getUrl().toString().equals(DATA_PLANE_INSTANCE_URL); - final boolean matchingCanHandleS3ToFileSystem = - dataPlaneInstance.canHandle(s3Source, fsSink); - final boolean matchingCanHandleBlobToFileSystem = - dataPlaneInstance.canHandle(blobSource, fsSink); - - if (!matchingId) { - System.err.printf( - "Expected ID %s, but got %s%n", - DATA_PLANE_INSTANCE_ID, dataPlaneInstance.getId()); - } - if (!matchingUrl) { - System.err.printf( - "Expected URL %s, but got %s%n", - DATA_PLANE_INSTANCE_URL, dataPlaneInstance.getUrl()); - } - if (!matchingCanHandleS3ToFileSystem) { - System.err.printf( - "Expected Instance to be handle source %s and sink %s%n", - S3_BUCKET, LOCAL_FILE_SYSTEM); - } - if (!matchingCanHandleBlobToFileSystem) { - System.err.printf( - "Expected Instance to be handle source %s and sink %s%n", - BLOB_STORAGE, LOCAL_FILE_SYSTEM); - } - - return matchingId && - matchingUrl && - matchingCanHandleS3ToFileSystem && - matchingCanHandleBlobToFileSystem; - })); + verify(dataPlaneSelectorService, times(1)) + .addInstance(argThat(dataPlaneInstance -> { + var s3Source = DataAddress.Builder.newInstance().type(S3_BUCKET).build(); + var blobSource = DataAddress.Builder.newInstance().type(BLOB_STORAGE).build(); + var fsSink = DataAddress.Builder.newInstance().type(LOCAL_FILE_SYSTEM).build(); + + return dataPlaneInstance.getId().equals(DATA_PLANE_INSTANCE_ID) && + dataPlaneInstance.getUrl().toString().equals(DATA_PLANE_INSTANCE_URL) && + dataPlaneInstance.canHandle(s3Source, fsSink) && + dataPlaneInstance.canHandle(blobSource, fsSink); + })); } @ParameterizedTest @ArgumentsSource(MissingConfigArgumentsProvider.class) void testWarningOnPropertyMissing(String configKey, String configValue) { - Map configMap = getConfig(); + var configMap = getConfig(); configMap.put(configKey, configValue); - - final Config config = ConfigFactory.fromMap(configMap); - - Mockito.when( - serviceExtensionContext.getConfig( - DataPlaneSelectorConfigurationServiceExtension.CONFIG_PREFIX)) - .thenReturn(config); - + var config = ConfigFactory.fromMap(configMap); + when(serviceExtensionContext.getConfig(CONFIG_PREFIX)).thenReturn(config); extension.initialize(serviceExtensionContext); // one warning config missing, one warning data plane instance skipped - Mockito.verify(monitor, Mockito.times(2)).warning(Mockito.anyString()); + verify(monitor, times(3)).warning(anyString()); } @Test void throwsExceptionOnPropertiesNoJson() { - Map configMap = getConfig(); + var configMap = getConfig(); configMap.put(PROPERTIES_KEY, "no json"); + var config = ConfigFactory.fromMap(configMap); + when(serviceExtensionContext.getConfig(CONFIG_PREFIX)).thenReturn(config); - final Config config = ConfigFactory.fromMap(configMap); - - Mockito.when( - serviceExtensionContext.getConfig( - DataPlaneSelectorConfigurationServiceExtension.CONFIG_PREFIX)) - .thenReturn(config); + assertThrows(EdcException.class, () -> extension.initialize(serviceExtensionContext)); + } - Assertions.assertThrows( - EdcException.class, () -> extension.initialize(serviceExtensionContext)); + private Map getConfig() { + return new HashMap<>() { + { + put(URL_KEY, DATA_PLANE_INSTANCE_URL); + put(SOURCE_TYPES_KEY, DATA_PLANE_INSTANCE_SOURCE_TYPES); + put(DESTINATION_TYPES_KEY, DATA_PLANE_INSTANCE_DESTINATION_TYPES); + put(PROPERTIES_KEY, "{ \"%s\": \"%s\" }".formatted(PUBLIC_API_URL_PROPERTY, DATA_PLANE_INSTANCE_URL)); + } + }; } private static class MissingConfigArgumentsProvider implements ArgumentsProvider { diff --git a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceExtension.java b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceExtension.java index e60aecca1..67f218bbb 100644 --- a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceExtension.java +++ b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceExtension.java @@ -42,7 +42,6 @@ import java.time.Clock; import java.util.function.Supplier; -import static org.eclipse.edc.connector.dataplane.spi.TransferDataPlaneConfig.TOKEN_SIGNER_PRIVATE_KEY_ALIAS; import static org.eclipse.tractusx.edc.dataplane.tokenrefresh.core.DataPlaneTokenRefreshServiceExtension.NAME; @Extension(value = NAME) @@ -54,6 +53,11 @@ public class DataPlaneTokenRefreshServiceExtension implements ServiceExtension { @Setting(value = "The HTTP endpoint where clients can request a renewal of their access token for the public dataplane API") public static final String REFRESH_ENDPOINT_PROPERTY = "edc.dataplane.token.refresh.endpoint"; + @Setting(value = "Alias of private key used for signing tokens, retrieved from private key resolver") + public static final String TOKEN_SIGNER_PRIVATE_KEY_ALIAS = "edc.transfer.proxy.token.signer.privatekey.alias"; + + @Setting(value = "Alias of public key used for verifying the tokens, retrieved from the vault") + public static final String TOKEN_VERIFIER_PUBLIC_KEY_ALIAS = "edc.transfer.proxy.token.verifier.publickey.alias"; @Inject private TokenValidationService tokenValidationService; @@ -105,7 +109,7 @@ private DataPlaneTokenRefreshServiceImpl getTokenRefreshService(ServiceExtension monitor.debug("Token refresh time tolerance: %d s".formatted(expiryTolerance)); tokenRefreshService = new DataPlaneTokenRefreshServiceImpl(clock, tokenValidationService, didPkResolver, accessTokenDataStore, new JwtGenerationService(), getPrivateKeySupplier(context), context.getMonitor(), refreshEndpoint, expiryTolerance, - vault, typeManager.getMapper()); + () -> context.getConfig().getString(TOKEN_VERIFIER_PUBLIC_KEY_ALIAS), vault, typeManager.getMapper()); } return tokenRefreshService; } @@ -121,6 +125,7 @@ private String getRefreshEndpointConfig(ServiceExtensionContext context, Monitor return refreshEndpoint; } + @NotNull private Supplier getPrivateKeySupplier(ServiceExtensionContext context) { return () -> { diff --git a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImpl.java b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImpl.java index 4c3cd8cb5..281e35f85 100644 --- a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImpl.java +++ b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImpl.java @@ -30,10 +30,13 @@ import org.eclipse.edc.spi.iam.TokenParameters; import org.eclipse.edc.spi.iam.TokenRepresentation; import org.eclipse.edc.spi.monitor.Monitor; +import org.eclipse.edc.spi.query.Criterion; +import org.eclipse.edc.spi.query.QuerySpec; import org.eclipse.edc.spi.result.Result; import org.eclipse.edc.spi.security.Vault; import org.eclipse.edc.spi.types.domain.DataAddress; import org.eclipse.edc.token.rules.ExpirationIssuedAtValidationRule; +import org.eclipse.edc.token.spi.KeyIdDecorator; import org.eclipse.edc.token.spi.TokenDecorator; import org.eclipse.edc.token.spi.TokenGenerationService; import org.eclipse.edc.token.spi.TokenValidationRule; @@ -75,6 +78,7 @@ public class DataPlaneTokenRefreshServiceImpl implements DataPlaneTokenRefreshSe private final AccessTokenDataStore accessTokenDataStore; private final TokenGenerationService tokenGenerationService; private final Supplier privateKeySupplier; + private final Supplier publicKeyIdSupplier; private final Monitor monitor; private final String refreshEndpoint; private final Clock clock; @@ -90,6 +94,7 @@ public DataPlaneTokenRefreshServiceImpl(Clock clock, Monitor monitor, String refreshEndpoint, int tokenExpiryToleranceSeconds, + Supplier publicKeyIdSupplier, Vault vault, ObjectMapper objectMapper) { this.tokenValidationService = tokenValidationService; @@ -100,6 +105,7 @@ public DataPlaneTokenRefreshServiceImpl(Clock clock, this.monitor = monitor; this.refreshEndpoint = refreshEndpoint; this.clock = clock; + this.publicKeyIdSupplier = publicKeyIdSupplier; this.vault = vault; this.objectMapper = objectMapper; authenticationTokenValidationRules = List.of(new IssuerEqualsSubjectRule(), @@ -202,7 +208,7 @@ public Result obtainToken(TokenParameters tokenParameters, // the refresh token information must be returned in the EDR var edrAdditionalData = new HashMap<>(additionalTokenData); edrAdditionalData.put("refreshToken", refreshTokenResult.getContent().tokenRepresentation().getToken()); - edrAdditionalData.put("expiresIn", DEFAULT_EXPIRY_IN_SECONDS); + edrAdditionalData.put("expiresIn", String.valueOf(DEFAULT_EXPIRY_IN_SECONDS)); edrAdditionalData.put("refreshEndpoint", refreshEndpoint); var edrTokenRepresentation = TokenRepresentation.Builder.newInstance() @@ -220,16 +226,40 @@ public Result resolve(String token) { return resolveToken(token, accessTokenRules); } + @Override + public Result revoke(String transferProcessId, String reason) { + var query = QuerySpec.Builder.newInstance() + .filter(new Criterion("additionalProperties.process_id", "=", transferProcessId)) + .build(); + + var tokens = accessTokenDataStore.query(query); + return tokens.stream().map(this::deleteTokenData) + .reduce(Result::merge) + .orElseGet(() -> Result.failure("AccessTokenData associated to the transfer with ID '%s' does not exist.".formatted(transferProcessId))); + } + + private Result deleteTokenData(AccessTokenData tokenData) { + var result = accessTokenDataStore.deleteById(tokenData.id()); + if (result.failed()) { + return Result.failure(result.getFailureDetail()); + } else { + return Result.success(); + } + } + /** * Creates a token that has an ID based on the given token parameters. If the token parameters don't contain a "jti" claim, one * will be generated at random. */ private Result createToken(TokenParameters tokenParameters) { - var claimDecorators = tokenParameters.getClaims().entrySet().stream().map(e -> (TokenDecorator) claimDecorator -> claimDecorator.claims(e.getKey(), e.getValue())); + var claims = new HashMap<>(tokenParameters.getClaims()); + claims.put(JwtRegisteredClaimNames.ISSUED_AT, clock.instant().getEpochSecond()); // iat is millis in upstream -> bug + var claimDecorators = claims.entrySet().stream().map(e -> (TokenDecorator) claimDecorator -> claimDecorator.claims(e.getKey(), e.getValue())); var headerDecorators = tokenParameters.getHeaders().entrySet().stream().map(e -> (TokenDecorator) headerDecorator -> headerDecorator.header(e.getKey(), e.getValue())); var tokenId = new AtomicReference<>(tokenParameters.getStringClaim(TOKEN_ID_CLAIM)); var allDecorators = new ArrayList<>(Stream.concat(claimDecorators, headerDecorators).toList()); + allDecorators.add(new KeyIdDecorator(publicKeyIdSupplier.get())); // if there is no "jti" header on the token params, we'll assign a random one, and add it back to the decorators if (tokenId.get() == null) { diff --git a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImplComponentTest.java b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImplComponentTest.java index d8261e852..82707a82e 100644 --- a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImplComponentTest.java +++ b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImplComponentTest.java @@ -89,6 +89,7 @@ void setup() throws JOSEException { mock(), TEST_REFRESH_ENDPOINT, 1, + () -> providerKey.getKeyID(), new InMemoryVault(mock()), new ObjectMapper()); diff --git a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImplTest.java b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImplTest.java index 1d3b58e2f..e619fa452 100644 --- a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImplTest.java +++ b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImplTest.java @@ -61,7 +61,7 @@ class DataPlaneTokenRefreshServiceImplTest { private final DidPublicKeyResolver didPublicKeyResolver = mock(); private final DataPlaneTokenRefreshServiceImpl accessTokenService = new DataPlaneTokenRefreshServiceImpl(Clock.systemUTC(), tokenValidationService, didPublicKeyResolver, accessTokenDataStore, tokenGenService, mock(), mock(), "https://example.com", 1, - mock(), new ObjectMapper()); + () -> "keyid", mock(), new ObjectMapper()); @Test diff --git a/edc-extensions/edr/edr-callback/src/main/java/org/eclipse/tractusx/edc/callback/ContractNegotiationCallback.java b/edc-extensions/edr/edr-callback/src/main/java/org/eclipse/tractusx/edc/callback/ContractNegotiationCallback.java index 74bd92aea..bb537a9e8 100644 --- a/edc-extensions/edr/edr-callback/src/main/java/org/eclipse/tractusx/edc/callback/ContractNegotiationCallback.java +++ b/edc-extensions/edr/edr-callback/src/main/java/org/eclipse/tractusx/edc/callback/ContractNegotiationCallback.java @@ -35,7 +35,7 @@ public class ContractNegotiationCallback implements InProcessCallback { - public static final DataAddress DATA_DESTINATION = DataAddress.Builder.newInstance().type("HttpProxy").build(); + public static final DataAddress DATA_DESTINATION = DataAddress.Builder.newInstance().type("HttpProxy-PULL").build(); private final TransferProcessService transferProcessService; private final Monitor monitor; diff --git a/edc-extensions/edr/edr-callback/src/main/java/org/eclipse/tractusx/edc/callback/TransferProcessLocalCallback.java b/edc-extensions/edr/edr-callback/src/main/java/org/eclipse/tractusx/edc/callback/TransferProcessLocalCallback.java index 6e5a4a0ac..6188f3d6c 100644 --- a/edc-extensions/edr/edr-callback/src/main/java/org/eclipse/tractusx/edc/callback/TransferProcessLocalCallback.java +++ b/edc-extensions/edr/edr-callback/src/main/java/org/eclipse/tractusx/edc/callback/TransferProcessLocalCallback.java @@ -82,7 +82,7 @@ private Result handleTransferProcessTermination(TransferProcessTerminated return transactionContext.execute(() -> { var transferProcess = transferProcessStore.findById(terminated.getTransferProcessId()); if (transferProcess != null) { - stopEdrNegotiation(transferProcess.getDataRequest().getAssetId(), transferProcess.getDataRequest().getContractId(), terminated.getReason()); + stopEdrNegotiation(transferProcess.getAssetId(), transferProcess.getContractId(), terminated.getReason()); return Result.success(); } else { return Result.failure(format("Failed to find a transfer process with ID %s", terminated.getTransferProcessId())); @@ -113,15 +113,15 @@ private Result storeEdr(EndpointDataReference edr) { } var cacheEntry = EndpointDataReferenceEntry.Builder.newInstance() .transferProcessId(transferProcess.getId()) - .assetId(transferProcess.getDataRequest().getAssetId()) - .agreementId(transferProcess.getDataRequest().getContractId()) + .assetId(transferProcess.getAssetId()) + .agreementId(transferProcess.getContractId()) .providerId(contractNegotiation.getCounterPartyId()) .state(EndpointDataReferenceEntryStates.NEGOTIATED.code()) .expirationTimestamp(expirationTime.getContent()) .contractNegotiationId(contractNegotiationId) .build(); - cleanOldEdr(transferProcess.getDataRequest().getAssetId(), transferProcess.getDataRequest().getContractId()); + cleanOldEdr(transferProcess.getAssetId(), transferProcess.getContractId()); edrCache.save(cacheEntry, edr); return Result.success(); diff --git a/edc-extensions/edr/edr-callback/src/test/java/org/eclipse/tractusx/edc/callback/TransferProcessLocalCallbackTest.java b/edc-extensions/edr/edr-callback/src/test/java/org/eclipse/tractusx/edc/callback/TransferProcessLocalCallbackTest.java index 290ce3528..ad9a3f318 100644 --- a/edc-extensions/edr/edr-callback/src/test/java/org/eclipse/tractusx/edc/callback/TransferProcessLocalCallbackTest.java +++ b/edc-extensions/edr/edr-callback/src/test/java/org/eclipse/tractusx/edc/callback/TransferProcessLocalCallbackTest.java @@ -27,7 +27,6 @@ import org.eclipse.edc.connector.transfer.spi.event.TransferProcessProvisioned; import org.eclipse.edc.connector.transfer.spi.event.TransferProcessRequested; import org.eclipse.edc.connector.transfer.spi.store.TransferProcessStore; -import org.eclipse.edc.connector.transfer.spi.types.DataRequest; import org.eclipse.edc.connector.transfer.spi.types.TransferProcess; import org.eclipse.edc.spi.monitor.Monitor; import org.eclipse.edc.spi.result.Result; @@ -100,15 +99,11 @@ void invoke_shouldStoreTheEdrInCache_whenDataAddressIsPresent() { var edr = getEdr(); - var dataRequest = DataRequest.Builder.newInstance().id(edr.getId()) - .destinationType("HttpProxy") - .assetId(assetId) - .contractId(contractId) - .build(); - var transferProcess = TransferProcess.Builder.newInstance() .id(transferProcessId) - .dataRequest(dataRequest) + .assetId(assetId) + .contractId(contractId) + .dataDestination(DataAddress.Builder.newInstance().type("HttpProxy").build()) .build(); var edrEntry = EndpointDataReferenceEntry.Builder.newInstance() @@ -207,15 +202,11 @@ void invoke_shouldStopEdrNegotiation_whenTerminatedMessageReceived() { var contractId = "contractId"; var edr = getEdr(); - var dataRequest = DataRequest.Builder.newInstance().id(edr.getId()) - .destinationType("HttpProxy") - .assetId(assetId) - .contractId(contractId) - .build(); - var transferProcess = TransferProcess.Builder.newInstance() .id(transferProcessId) - .dataRequest(dataRequest) + .assetId(assetId) + .contractId(contractId) + .dataDestination(DataAddress.Builder.newInstance().type("HttpProxy").build()) .build(); var edrEntry = EndpointDataReferenceEntry.Builder.newInstance() diff --git a/edc-extensions/iatp/tx-iatp-sts-dim/src/main/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/DimSecureTokenServiceExtension.java b/edc-extensions/iatp/tx-iatp-sts-dim/src/main/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/DimSecureTokenServiceExtension.java index 5b161a848..0722510f8 100644 --- a/edc-extensions/iatp/tx-iatp-sts-dim/src/main/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/DimSecureTokenServiceExtension.java +++ b/edc-extensions/iatp/tx-iatp-sts-dim/src/main/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/DimSecureTokenServiceExtension.java @@ -29,9 +29,11 @@ import org.eclipse.edc.spi.system.ServiceExtension; import org.eclipse.edc.spi.system.ServiceExtensionContext; import org.eclipse.edc.spi.types.TypeManager; +import org.eclipse.tractusx.edc.core.utils.PathUtils; import org.eclipse.tractusx.edc.iam.iatp.sts.dim.oauth.DimOauth2Client; -import static org.eclipse.tractusx.edc.core.utils.PathUtils.removeTrailingSlash; +import static java.util.Optional.ofNullable; +import static org.eclipse.tractusx.edc.core.utils.RequiredConfigWarnings.warningNotPresent; @Extension(DimSecureTokenServiceExtension.NAME) public class DimSecureTokenServiceExtension implements ServiceExtension { @@ -55,6 +57,7 @@ public class DimSecureTokenServiceExtension implements ServiceExtension { @Inject private TypeManager typeManager; + @Override public String name() { return NAME; @@ -62,7 +65,14 @@ public String name() { @Provider public SecureTokenService secureTokenService(ServiceExtensionContext context) { - return new DimSecureTokenService(httpClient, removeTrailingSlash(context.getConfig().getString(DIM_URL)), dimOauth2Client, typeManager.getMapper(), monitor); - } + var dimUrl = ofNullable(context.getConfig().getString(DIM_URL, null)) + .map(PathUtils::removeTrailingSlash) + .orElse(null); + if (dimUrl == null) { + warningNotPresent(context.getMonitor().withPrefix("STS Client for DIM"), DIM_URL); + } + + return new DimSecureTokenService(httpClient, dimUrl, dimOauth2Client, typeManager.getMapper(), monitor); + } } \ No newline at end of file diff --git a/edc-extensions/iatp/tx-iatp-sts-dim/src/main/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/DimStsConfigurationExtension.java b/edc-extensions/iatp/tx-iatp-sts-dim/src/main/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/DimStsConfigurationExtension.java index e0e653438..4f5674955 100644 --- a/edc-extensions/iatp/tx-iatp-sts-dim/src/main/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/DimStsConfigurationExtension.java +++ b/edc-extensions/iatp/tx-iatp-sts-dim/src/main/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/DimStsConfigurationExtension.java @@ -24,8 +24,10 @@ import org.eclipse.edc.runtime.metamodel.annotation.Setting; import org.eclipse.edc.spi.system.ServiceExtension; import org.eclipse.edc.spi.system.ServiceExtensionContext; +import org.eclipse.tractusx.edc.core.utils.PathUtils; -import static org.eclipse.tractusx.edc.core.utils.PathUtils.removeTrailingSlash; +import static java.util.Optional.ofNullable; +import static org.eclipse.tractusx.edc.core.utils.RequiredConfigWarnings.warningNotPresent; /** * Configuration Extension for the STS OAuth2 client @@ -44,6 +46,7 @@ public class DimStsConfigurationExtension implements ServiceExtension { protected static final String NAME = "DIM STS client configuration extension"; + @Override public String name() { return NAME; @@ -52,9 +55,21 @@ public String name() { @Provider public StsRemoteClientConfiguration clientConfiguration(ServiceExtensionContext context) { - var tokenUrl = removeTrailingSlash(context.getConfig().getString(TOKEN_URL)); - var clientId = context.getConfig().getString(CLIENT_ID); - var clientSecretAlias = context.getConfig().getString(CLIENT_SECRET_ALIAS); + var tokenUrl = ofNullable(context.getConfig().getString(TOKEN_URL, null)) + .map(PathUtils::removeTrailingSlash).orElse(null); + var clientId = context.getConfig().getString(CLIENT_ID, null); + var clientSecretAlias = context.getConfig().getString(CLIENT_SECRET_ALIAS, null); + + var monitor = context.getMonitor().withPrefix("STS Client for DIM"); + if (tokenUrl == null) { + warningNotPresent(monitor, TOKEN_URL); + } + if (clientId == null) { + warningNotPresent(monitor, CLIENT_ID); + } + if (clientSecretAlias == null) { + warningNotPresent(monitor, CLIENT_SECRET_ALIAS); + } return new StsRemoteClientConfiguration(tokenUrl, clientId, clientSecretAlias); } diff --git a/edc-extensions/iatp/tx-iatp-sts-dim/src/test/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/DimSecureServiceExtensionTest.java b/edc-extensions/iatp/tx-iatp-sts-dim/src/test/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/DimSecureServiceExtensionTest.java index 36d836bb5..b8d99569b 100644 --- a/edc-extensions/iatp/tx-iatp-sts-dim/src/test/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/DimSecureServiceExtensionTest.java +++ b/edc-extensions/iatp/tx-iatp-sts-dim/src/test/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/DimSecureServiceExtensionTest.java @@ -20,14 +20,13 @@ package org.eclipse.tractusx.edc.iam.iatp.sts.dim; import org.eclipse.edc.junit.extensions.DependencyInjectionExtension; -import org.eclipse.edc.spi.EdcException; import org.eclipse.edc.spi.system.ServiceExtensionContext; import org.eclipse.edc.spi.system.configuration.Config; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.assertj.core.api.Assertions.assertThatNoException; import static org.eclipse.tractusx.edc.iam.iatp.sts.dim.DimSecureTokenServiceExtension.DIM_URL; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -39,13 +38,13 @@ public class DimSecureServiceExtensionTest { void initialize(ServiceExtensionContext context, DimSecureTokenServiceExtension extension) { var config = mock(Config.class); when(context.getConfig()).thenReturn(config); - when(config.getString(DIM_URL)).thenReturn("url"); + when(config.getString(DIM_URL, null)).thenReturn("url"); assertThat(extension.secureTokenService(context)).isInstanceOf(DimSecureTokenService.class); } @Test - void initialize_shouldThrow_whenUrlIsMissing(ServiceExtensionContext context, DimSecureTokenServiceExtension extension) { - assertThatThrownBy(() -> extension.secureTokenService(context)).isInstanceOf(EdcException.class); + void initialize_shouldNotThrow_whenUrlIsMissing(ServiceExtensionContext context, DimSecureTokenServiceExtension extension) { + assertThatNoException().isThrownBy(() -> extension.secureTokenService(context)); } } diff --git a/edc-extensions/iatp/tx-iatp-sts-dim/src/test/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/DimStsConfigurationExtensionTest.java b/edc-extensions/iatp/tx-iatp-sts-dim/src/test/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/DimStsConfigurationExtensionTest.java index a2a8dc1da..62ac06d85 100644 --- a/edc-extensions/iatp/tx-iatp-sts-dim/src/test/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/DimStsConfigurationExtensionTest.java +++ b/edc-extensions/iatp/tx-iatp-sts-dim/src/test/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/DimStsConfigurationExtensionTest.java @@ -39,9 +39,9 @@ public class DimStsConfigurationExtensionTest { void initialize(ServiceExtensionContext context, DimStsConfigurationExtension extension) { var config = mock(Config.class); when(context.getConfig()).thenReturn(config); - when(config.getString(TOKEN_URL)).thenReturn("url"); - when(config.getString(CLIENT_ID)).thenReturn("clientId"); - when(config.getString(CLIENT_SECRET_ALIAS)).thenReturn("clientSecretAlias"); + when(config.getString(TOKEN_URL, null)).thenReturn("url"); + when(config.getString(CLIENT_ID, null)).thenReturn("clientId"); + when(config.getString(CLIENT_SECRET_ALIAS, null)).thenReturn("clientSecretAlias"); assertThat(extension.clientConfiguration(context)).satisfies(stsConfig -> { assertThat(stsConfig.clientId()).isEqualTo("clientId"); diff --git a/edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/transferprocess/V0_0_15__Alter_TransferProcess_InlineDataAddress.sql b/edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/transferprocess/V0_0_15__Alter_TransferProcess_InlineDataAddress.sql new file mode 100644 index 000000000..469bd0149 --- /dev/null +++ b/edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/transferprocess/V0_0_15__Alter_TransferProcess_InlineDataAddress.sql @@ -0,0 +1,28 @@ +-- +-- Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +-- +-- This program and the accompanying materials are made available under the +-- terms of the Apache License, Version 2.0 which is available at +-- https://www.apache.org/licenses/LICENSE-2.0 +-- +-- SPDX-License-Identifier: Apache-2.0 +-- +-- Contributors: +-- Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - initial API and implementation +-- + +-- drop datarequest +DROP TABLE IF EXISTS edc_data_request; +-- add columns +ALTER TABLE edc_transfer_process + ADD COLUMN correlation_id VARCHAR; +ALTER TABLE edc_transfer_process + ADD COLUMN counter_party_address VARCHAR; +ALTER TABLE edc_transfer_process + ADD COLUMN protocol VARCHAR; +ALTER TABLE edc_transfer_process + ADD COLUMN asset_id VARCHAR; +ALTER TABLE edc_transfer_process + ADD COLUMN contract_id VARCHAR; +ALTER TABLE edc_transfer_process + ADD COLUMN data_destination JSON; diff --git a/edc-extensions/provision-additional-headers/src/main/java/org/eclipse/tractusx/edc/provision/additionalheaders/AdditionalHeadersProvisioner.java b/edc-extensions/provision-additional-headers/src/main/java/org/eclipse/tractusx/edc/provision/additionalheaders/AdditionalHeadersProvisioner.java index 1bf3928dc..f810b4af2 100644 --- a/edc-extensions/provision-additional-headers/src/main/java/org/eclipse/tractusx/edc/provision/additionalheaders/AdditionalHeadersProvisioner.java +++ b/edc-extensions/provision-additional-headers/src/main/java/org/eclipse/tractusx/edc/provision/additionalheaders/AdditionalHeadersProvisioner.java @@ -54,15 +54,14 @@ public CompletableFuture> provision(AdditionalHe .addAdditionalHeader("Edc-Bpn", resourceDefinition.getBpn()) .build(); - var provisioned = - AdditionalHeadersProvisionedResource.Builder.newInstance() - .id(UUID.randomUUID().toString()) - .resourceDefinitionId(resourceDefinition.getId()) - .transferProcessId(resourceDefinition.getTransferProcessId()) - .dataAddress(address) - .resourceName(UUID.randomUUID().toString()) - .hasToken(false) - .build(); + var provisioned = AdditionalHeadersProvisionedResource.Builder.newInstance() + .id(UUID.randomUUID().toString()) + .resourceDefinitionId(resourceDefinition.getId()) + .transferProcessId(resourceDefinition.getTransferProcessId()) + .dataAddress(address) + .resourceName(UUID.randomUUID().toString()) + .hasToken(false) + .build(); var response = ProvisionResponse.Builder.newInstance().resource(provisioned).build(); var result = StatusResult.success(response); diff --git a/edc-extensions/provision-additional-headers/src/main/java/org/eclipse/tractusx/edc/provision/additionalheaders/AdditionalHeadersResourceDefinitionGenerator.java b/edc-extensions/provision-additional-headers/src/main/java/org/eclipse/tractusx/edc/provision/additionalheaders/AdditionalHeadersResourceDefinitionGenerator.java index 83838ac89..26f12fa15 100644 --- a/edc-extensions/provision-additional-headers/src/main/java/org/eclipse/tractusx/edc/provision/additionalheaders/AdditionalHeadersResourceDefinitionGenerator.java +++ b/edc-extensions/provision-additional-headers/src/main/java/org/eclipse/tractusx/edc/provision/additionalheaders/AdditionalHeadersResourceDefinitionGenerator.java @@ -42,7 +42,7 @@ class AdditionalHeadersResourceDefinitionGenerator implements ProviderResourceDe @Override public @Nullable ResourceDefinition generate(TransferProcess transferProcess, DataAddress dataAddress, Policy policy) { - var bpn = Optional.of(transferProcess.getDataRequest().getContractId()) + var bpn = Optional.of(transferProcess.getContractId()) .map(contractAgreementService::findById) .map(ContractAgreement::getConsumerId) .orElse(null); @@ -50,7 +50,7 @@ class AdditionalHeadersResourceDefinitionGenerator implements ProviderResourceDe return AdditionalHeadersResourceDefinition.Builder.newInstance() .id(UUID.randomUUID().toString()) .dataAddress(dataAddress) - .contractId(transferProcess.getDataRequest().getContractId()) + .contractId(transferProcess.getContractId()) .bpn(bpn) .build(); } diff --git a/edc-extensions/provision-additional-headers/src/test/java/org/eclipse/tractusx/edc/provision/additionalheaders/AdditionalHeadersResourceDefinitionGeneratorTest.java b/edc-extensions/provision-additional-headers/src/test/java/org/eclipse/tractusx/edc/provision/additionalheaders/AdditionalHeadersResourceDefinitionGeneratorTest.java index 22d42af87..81e03b8d9 100644 --- a/edc-extensions/provision-additional-headers/src/test/java/org/eclipse/tractusx/edc/provision/additionalheaders/AdditionalHeadersResourceDefinitionGeneratorTest.java +++ b/edc-extensions/provision-additional-headers/src/test/java/org/eclipse/tractusx/edc/provision/additionalheaders/AdditionalHeadersResourceDefinitionGeneratorTest.java @@ -23,7 +23,6 @@ import org.eclipse.edc.connector.dataplane.http.spi.HttpDataAddress; import org.eclipse.edc.connector.spi.contractagreement.ContractAgreementService; import org.eclipse.edc.connector.transfer.spi.provision.ProviderResourceDefinitionGenerator; -import org.eclipse.edc.connector.transfer.spi.types.DataRequest; import org.eclipse.edc.connector.transfer.spi.types.TransferProcess; import org.eclipse.edc.policy.model.Policy; import org.eclipse.edc.spi.types.domain.DataAddress; @@ -57,13 +56,8 @@ private static ContractAgreement contractAgreementWithBpn(String bpn) { @Test void canGenerate_shouldReturnFalseForNotHttpDataAddresses() { var dataAddress = DataAddress.Builder.newInstance().type("any").build(); - var dataRequest = - DataRequest.Builder.newInstance() - .id(UUID.randomUUID().toString()) - .dataDestination(dataAddress) - .build(); var build = Policy.Builder.newInstance().build(); - var transferProcess = TransferProcess.Builder.newInstance().dataRequest(dataRequest).build(); + var transferProcess = TransferProcess.Builder.newInstance().build(); var result = generator.canGenerate(transferProcess, dataAddress, build); @@ -73,13 +67,8 @@ void canGenerate_shouldReturnFalseForNotHttpDataAddresses() { @Test void canGenerate_shouldReturnTrueForHttpDataAddresses() { var dataAddress = DataAddress.Builder.newInstance().type("HttpData").build(); - var dataRequest = - DataRequest.Builder.newInstance() - .id(UUID.randomUUID().toString()) - .dataDestination(dataAddress) - .build(); var build = Policy.Builder.newInstance().build(); - var transferProcess = TransferProcess.Builder.newInstance().dataRequest(dataRequest).build(); + var transferProcess = TransferProcess.Builder.newInstance().build(); var result = generator.canGenerate(transferProcess, dataAddress, build); @@ -89,15 +78,12 @@ void canGenerate_shouldReturnTrueForHttpDataAddresses() { @Test void shouldCreateResourceDefinitionWithDataAddress() { var dataAddress = HttpDataAddress.Builder.newInstance().baseUrl("http://any").build(); - var dataRequest = - DataRequest.Builder.newInstance() - .id(UUID.randomUUID().toString()) - .dataDestination(dataAddress) - .contractId("contractId") - .build(); var build = Policy.Builder.newInstance().build(); when(contractAgreementService.findById(any())).thenReturn(contractAgreementWithBpn("bpn")); - var transferProcess = TransferProcess.Builder.newInstance().dataRequest(dataRequest).build(); + var transferProcess = TransferProcess.Builder.newInstance() + .dataDestination(dataAddress) + .contractId("contractId") + .build(); var result = generator.generate(transferProcess, dataAddress, build); diff --git a/edc-extensions/tokenrefresh-handler/build.gradle.kts b/edc-extensions/tokenrefresh-handler/build.gradle.kts index 65e3ba221..d48210726 100644 --- a/edc-extensions/tokenrefresh-handler/build.gradle.kts +++ b/edc-extensions/tokenrefresh-handler/build.gradle.kts @@ -23,6 +23,7 @@ plugins { } dependencies { + implementation(project(":core:core-utils")) implementation(project(":spi:core-spi")) implementation(project(":spi:tokenrefresh-spi")) implementation(libs.edc.spi.core) diff --git a/edc-extensions/tokenrefresh-handler/src/main/java/org/eclipse/tractusx/edc/common/tokenrefresh/TokenRefreshHandlerExtension.java b/edc-extensions/tokenrefresh-handler/src/main/java/org/eclipse/tractusx/edc/common/tokenrefresh/TokenRefreshHandlerExtension.java index 7fb54d155..607a75817 100644 --- a/edc-extensions/tokenrefresh-handler/src/main/java/org/eclipse/tractusx/edc/common/tokenrefresh/TokenRefreshHandlerExtension.java +++ b/edc-extensions/tokenrefresh-handler/src/main/java/org/eclipse/tractusx/edc/common/tokenrefresh/TokenRefreshHandlerExtension.java @@ -28,6 +28,7 @@ import org.eclipse.edc.spi.system.ServiceExtension; import org.eclipse.edc.spi.system.ServiceExtensionContext; import org.eclipse.edc.spi.types.TypeManager; +import org.eclipse.tractusx.edc.core.utils.RequiredConfigWarnings; import org.eclipse.tractusx.edc.spi.tokenrefresh.common.TokenRefreshHandler; import static org.eclipse.tractusx.edc.common.tokenrefresh.TokenRefreshHandlerExtension.NAME; @@ -58,6 +59,10 @@ public TokenRefreshHandler createTokenRefreshHander(ServiceExtensionContext cont } private String getOwnDid(ServiceExtensionContext context) { - return context.getConfig().getString(PARTICIPANT_DID_PROPERTY); + var did = context.getConfig().getString(PARTICIPANT_DID_PROPERTY, null); + if (did == null) { + RequiredConfigWarnings.warningNotPresent(context.getMonitor().withPrefix("Token Refresh Handler"), PARTICIPANT_DID_PROPERTY); + } + return did; } } diff --git a/edc-extensions/transferprocess-sftp-provisioner/src/test/java/org/eclipse/tractusx/edc/transferprocess/sftp/provisioner/SftpProviderResourceDefinitionGeneratorTest.java b/edc-extensions/transferprocess-sftp-provisioner/src/test/java/org/eclipse/tractusx/edc/transferprocess/sftp/provisioner/SftpProviderResourceDefinitionGeneratorTest.java index 7f8b0a126..13eccdbff 100644 --- a/edc-extensions/transferprocess-sftp-provisioner/src/test/java/org/eclipse/tractusx/edc/transferprocess/sftp/provisioner/SftpProviderResourceDefinitionGeneratorTest.java +++ b/edc-extensions/transferprocess-sftp-provisioner/src/test/java/org/eclipse/tractusx/edc/transferprocess/sftp/provisioner/SftpProviderResourceDefinitionGeneratorTest.java @@ -21,7 +21,6 @@ package org.eclipse.tractusx.edc.transferprocess.sftp.provisioner; -import org.eclipse.edc.connector.transfer.spi.types.DataRequest; import org.eclipse.edc.connector.transfer.spi.types.TransferProcess; import org.eclipse.edc.policy.model.Policy; import org.eclipse.edc.spi.types.domain.DataAddress; @@ -34,7 +33,6 @@ import java.security.KeyPairGenerator; import java.security.NoSuchAlgorithmException; -import static org.eclipse.tractusx.edc.transferprocess.sftp.provisioner.NoOpSftpProvisioner.DATA_ADDRESS_TYPE; import static org.eclipse.tractusx.edc.transferprocess.sftp.provisioner.NoOpSftpProvisioner.PROVIDER_TYPE; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -64,14 +62,13 @@ void generate_successful() throws NoSuchAlgorithmException { var port = 22; var path = "path"; - var dataRequest = DataRequest.Builder.newInstance().destinationType(DATA_ADDRESS_TYPE).build(); var sftpUser = SftpUser.Builder.newInstance().name(name).password(password).keyPair(keyPair).build(); var sftpLocation = SftpLocation.Builder.newInstance().host(host).port(port).path(path).build(); final DataAddress dataAddress = SftpDataAddress.Builder.newInstance().sftpUser(sftpUser).sftpLocation(sftpLocation).build(); var policy = Policy.Builder.newInstance().build(); - var transferProcess = TransferProcess.Builder.newInstance().dataRequest(dataRequest).build(); + var transferProcess = TransferProcess.Builder.newInstance().build(); var resourceDefinition = (SftpProviderResourceDefinition) generator.generate(transferProcess, dataAddress, policy); @@ -89,12 +86,10 @@ void generate_successful() throws NoSuchAlgorithmException { @Test void generate_wrongDataAddressType() { - var dataRequest = - DataRequest.Builder.newInstance().destinationType(DATA_ADDRESS_TYPE).build(); var dataAddress = DataAddress.Builder.newInstance().type("wrong").build(); var policy = Policy.Builder.newInstance().build(); - var transferProcess = TransferProcess.Builder.newInstance().dataRequest(dataRequest).build(); + var transferProcess = TransferProcess.Builder.newInstance().build(); var resourceDefinition = (SftpProviderResourceDefinition) generator.generate(transferProcess, dataAddress, policy); diff --git a/edc-tests/e2e-tests/build.gradle.kts b/edc-tests/e2e-tests/build.gradle.kts index a9c9730c2..d0ee8cf35 100644 --- a/edc-tests/e2e-tests/build.gradle.kts +++ b/edc-tests/e2e-tests/build.gradle.kts @@ -24,7 +24,6 @@ plugins { dependencies { testImplementation(project(":spi:edr-spi")) - testImplementation(project(":edc-extensions:edr:edr-api")) testImplementation(libs.okhttp.mockwebserver) testImplementation(libs.restAssured) testImplementation(libs.nimbus.jwt) diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/helpers/CatalogHelperFunctions.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/helpers/CatalogHelperFunctions.java index 56bf62478..642c8cee7 100644 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/helpers/CatalogHelperFunctions.java +++ b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/helpers/CatalogHelperFunctions.java @@ -19,32 +19,16 @@ package org.eclipse.tractusx.edc.helpers; -import jakarta.json.Json; -import jakarta.json.JsonArray; import jakarta.json.JsonObject; import jakarta.json.JsonValue; import org.eclipse.edc.connector.contract.spi.ContractId; -import static org.eclipse.edc.catalog.spi.CatalogRequest.CATALOG_REQUEST_QUERY_SPEC; import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.ID; import static org.eclipse.edc.jsonld.spi.PropertyAndTypeNames.ODRL_POLICY_ATTRIBUTE; -import static org.eclipse.edc.spi.CoreConstants.EDC_NAMESPACE; public class CatalogHelperFunctions { - public static JsonObject createCatalogRequest(JsonObject query, String dspEndpoint) { - var jsonBuilder = Json.createObjectBuilder(); - jsonBuilder.add("@type", "CatalogRequest"); - jsonBuilder.add(EDC_NAMESPACE + "counterPartyAddress", dspEndpoint); - jsonBuilder.add(EDC_NAMESPACE + "protocol", "dataspace-protocol-http"); - - if (query != null) { - jsonBuilder.add(CATALOG_REQUEST_QUERY_SPEC, query); - } - return jsonBuilder.build(); - } - public static ContractId getDatasetContractId(JsonObject dataset) { var id = dataset.getJsonArray(ODRL_POLICY_ATTRIBUTE).get(0).asJsonObject().getString(ID); return ContractId.parseId(id).orElseThrow(f -> new RuntimeException(f.getFailureDetail())); @@ -58,19 +42,4 @@ public static String getDatasetAssetId(JsonValue dataset) { return getDatasetContractId(dataset.asJsonObject()).assetIdPart(); } - public static JsonArray getDatasetPolicies(JsonObject dataset) { - return dataset.getJsonArray(ODRL_POLICY_ATTRIBUTE); - } - - public static JsonObject getDatasetFirstPolicy(JsonObject dataset) { - return dataset.getJsonArray(ODRL_POLICY_ATTRIBUTE).stream().findFirst().get().asJsonObject(); - } - - public static JsonObject getDatasetFirstPolicy(JsonValue dataset) { - return getDatasetFirstPolicy(dataset.asJsonObject()); - } - - public static JsonArray getDatasetPolicies(JsonValue dataset) { - return getDatasetPolicies(dataset.asJsonObject()); - } } diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/helpers/ContractDefinitionHelperFunctions.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/helpers/ContractDefinitionHelperFunctions.java deleted file mode 100644 index a286091c0..000000000 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/helpers/ContractDefinitionHelperFunctions.java +++ /dev/null @@ -1,47 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.helpers; - -import jakarta.json.Json; -import jakarta.json.JsonObject; - -import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.ID; -import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.TYPE; -import static org.eclipse.edc.spi.CoreConstants.EDC_NAMESPACE; - -public class ContractDefinitionHelperFunctions { - - public static JsonObject createContractDefinition(String assetId, String definitionId, String accessPolicyId, String contractPolicyId) { - return Json.createObjectBuilder() - .add(ID, definitionId) - .add(TYPE, EDC_NAMESPACE + "ContractDefinition") - .add(EDC_NAMESPACE + "accessPolicyId", accessPolicyId) - .add(EDC_NAMESPACE + "contractPolicyId", contractPolicyId) - .add(EDC_NAMESPACE + "assetsSelector", Json.createArrayBuilder() - .add(Json.createObjectBuilder() - .add(TYPE, "CriterionDto") - .add(EDC_NAMESPACE + "operandLeft", EDC_NAMESPACE + "id") - .add(EDC_NAMESPACE + "operator", "=") - .add(EDC_NAMESPACE + "operandRight", assetId) - .build()) - .build()) - .build(); - } -} diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/helpers/ContractNegotiationHelperFunctions.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/helpers/ContractNegotiationHelperFunctions.java deleted file mode 100644 index da4b033b6..000000000 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/helpers/ContractNegotiationHelperFunctions.java +++ /dev/null @@ -1,47 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.helpers; - -import jakarta.json.Json; -import jakarta.json.JsonObject; -import org.eclipse.edc.jsonld.TitaniumJsonLd; -import org.eclipse.edc.jsonld.spi.JsonLd; -import org.eclipse.edc.spi.monitor.Monitor; - -import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.TYPE; -import static org.eclipse.edc.protocol.dsp.spi.types.HttpMessageProtocol.DATASPACE_PROTOCOL_HTTP; -import static org.eclipse.edc.spi.CoreConstants.EDC_NAMESPACE; -import static org.mockito.Mockito.mock; - -public class ContractNegotiationHelperFunctions { - - private static final JsonLd JSON_LD = new TitaniumJsonLd(mock(Monitor.class)); - - public static JsonObject createNegotiationRequest(String counterPartyAddress, String providerId, JsonObject policy) { - return Json.createObjectBuilder() - .add(TYPE, EDC_NAMESPACE + "NegotiationInitiateRequestDto") - .add(EDC_NAMESPACE + "providerId", providerId) - .add(EDC_NAMESPACE + "counterPartyAddress", counterPartyAddress) - .add(EDC_NAMESPACE + "protocol", DATASPACE_PROTOCOL_HTTP) - .add(EDC_NAMESPACE + "policy", JSON_LD.compact(policy).getContent()) - .build(); - } - -} diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/helpers/EdrNegotiationHelperFunctions.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/helpers/EdrNegotiationHelperFunctions.java deleted file mode 100644 index 0d69075fd..000000000 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/helpers/EdrNegotiationHelperFunctions.java +++ /dev/null @@ -1,74 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.helpers; - -import jakarta.json.Json; -import jakarta.json.JsonArray; -import jakarta.json.JsonArrayBuilder; -import jakarta.json.JsonObject; -import org.eclipse.edc.jsonld.TitaniumJsonLd; -import org.eclipse.edc.jsonld.spi.JsonLd; -import org.eclipse.edc.spi.event.Event; -import org.eclipse.edc.spi.monitor.Monitor; -import org.eclipse.tractusx.edc.api.edr.dto.NegotiateEdrRequestDto; - -import java.util.Set; - -import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.TYPE; -import static org.eclipse.edc.protocol.dsp.spi.types.HttpMessageProtocol.DATASPACE_PROTOCOL_HTTP; -import static org.eclipse.edc.spi.CoreConstants.EDC_NAMESPACE; -import static org.mockito.Mockito.mock; - -public class EdrNegotiationHelperFunctions { - - private static final JsonLd JSON_LD = new TitaniumJsonLd(mock(Monitor.class)); - - public static JsonObject createEdrNegotiationRequest(String connectorAddress, String providerId, String offerId, String assetId, JsonObject policy, JsonArray callbacks) { - return Json.createObjectBuilder() - .add(TYPE, NegotiateEdrRequestDto.EDR_REQUEST_DTO_TYPE) - .add(EDC_NAMESPACE + "counterPartyId", providerId) - .add(EDC_NAMESPACE + "providerId", providerId) - .add(EDC_NAMESPACE + "counterPartyAddress", connectorAddress) - .add(EDC_NAMESPACE + "protocol", DATASPACE_PROTOCOL_HTTP) - .add(EDC_NAMESPACE + "offer", Json.createObjectBuilder() - .add(EDC_NAMESPACE + "offerId", offerId) - .add(EDC_NAMESPACE + "assetId", assetId) - .add(EDC_NAMESPACE + "policy", JSON_LD.compact(policy).getContent()) - ) - .add(EDC_NAMESPACE + "callbackAddresses", callbacks) - .build(); - } - - public static JsonObject createCallback(String url, boolean transactional, Set events) { - return Json.createObjectBuilder() - .add(TYPE, EDC_NAMESPACE + "CallbackAddress") - .add(EDC_NAMESPACE + "transactional", transactional) - .add(EDC_NAMESPACE + "uri", url) - .add(EDC_NAMESPACE + "events", events - .stream() - .collect(Json::createArrayBuilder, JsonArrayBuilder::add, JsonArrayBuilder::add) - .build()) - .build(); - } - - public static ReceivedEvent createEvent(Class klass) { - return ReceivedEvent.Builder.newInstance().type(klass.getSimpleName()).build(); - } -} diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/helpers/PolicyHelperFunctions.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/helpers/PolicyHelperFunctions.java index 2c7f62c04..87766c02f 100644 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/helpers/PolicyHelperFunctions.java +++ b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/helpers/PolicyHelperFunctions.java @@ -51,8 +51,6 @@ public class PolicyHelperFunctions { private static final String ODRL_JSONLD = "http://www.w3.org/ns/odrl.jsonld"; private static final String BUSINESS_PARTNER_EVALUATION_KEY = "BusinessPartnerNumber"; - public static final String BUSINESS_PARTNER_LEGACY_EVALUATION_KEY = TX_NAMESPACE + BUSINESS_PARTNER_EVALUATION_KEY; - private static final String BUSINESS_PARTNER_CONSTRAINT_KEY = TX_NAMESPACE + "BusinessPartnerGroup"; private static final ObjectMapper MAPPER = JacksonJsonLd.createObjectMapper(); diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/helpers/TransferProcessHelperFunctions.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/helpers/TransferProcessHelperFunctions.java index 9f9c35340..e5aba8adc 100644 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/helpers/TransferProcessHelperFunctions.java +++ b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/helpers/TransferProcessHelperFunctions.java @@ -22,28 +22,11 @@ import jakarta.json.Json; import jakarta.json.JsonObject; -import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.ID; import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.TYPE; -import static org.eclipse.edc.protocol.dsp.spi.types.HttpMessageProtocol.DATASPACE_PROTOCOL_HTTP; import static org.eclipse.edc.spi.CoreConstants.EDC_NAMESPACE; public class TransferProcessHelperFunctions { - public static JsonObject createTransferRequest(String dataRequestId, String counterPartyAddress, String contractId, String assetId, boolean managedResources, JsonObject destination) { - return Json.createObjectBuilder() - .add(TYPE, EDC_NAMESPACE + "TransferRequestDto") - .add(ID, dataRequestId) - .add(EDC_NAMESPACE + "connectorId", "connectorId") - .add(EDC_NAMESPACE + "dataDestination", destination) - .add(EDC_NAMESPACE + "protocol", DATASPACE_PROTOCOL_HTTP) - .add(EDC_NAMESPACE + "assetId", assetId) - .add(EDC_NAMESPACE + "contractId", contractId) - .add(EDC_NAMESPACE + "counterPartyAddress", counterPartyAddress) - .add(EDC_NAMESPACE + "managedResources", managedResources) - .build(); - - } - public static JsonObject createProxyRequest() { return Json.createObjectBuilder() diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/tx/ParticipantDataApi.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/tx/ParticipantDataApi.java index a9ca1cb7f..ce2198f5e 100644 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/tx/ParticipantDataApi.java +++ b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/tx/ParticipantDataApi.java @@ -19,16 +19,12 @@ package org.eclipse.tractusx.edc.lifecycle.tx; -import io.restassured.response.Response; import org.eclipse.edc.spi.types.domain.edr.EndpointDataReference; import java.util.Map; import static io.restassured.RestAssured.given; -import static java.lang.String.format; import static org.assertj.core.api.Assertions.assertThat; -import static org.eclipse.tractusx.edc.lifecycle.tx.TxParticipant.API_KEY; -import static org.eclipse.tractusx.edc.lifecycle.tx.TxParticipant.PROXY_SUBPATH; /** @@ -36,75 +32,7 @@ */ public class ParticipantDataApi { - private final TxParticipant participant; - - public ParticipantDataApi(TxParticipant participant) { - this.participant = participant; - } - - /** - * Pull the data using the Consumer DataPlane and the provider's gateway with an asset id - * - * @return the data - */ - public String pullProxyDataByAssetId(TxParticipant provider, String assetId) { - var body = Map.of("assetId", assetId, "endpointUrl", format("%s/gateway/aas/test", provider.gatewayEndpoint())); - return getProxyData(body); - } - - /** - * Pull the data using the Consumer DataPlane and the provider's gateway with an transfer process id - * - * @return the data - */ - public String pullProxyDataByTransferProcessId(TxParticipant provider, String transferProcessId) { - var body = Map.of("transferProcessId", transferProcessId, - "endpointUrl", format("%s/gateway/aas/test", provider.gatewayEndpoint())); - return getProxyData(body); - - } - - /** - * Pull the data using the Consumer DataPlane and the provider's gateway with an asset id - * - * @return the data - */ - public Response pullProxyDataResponseByAssetId(TxParticipant provider, String assetId) { - var body = Map.of("assetId", assetId, - "endpointUrl", format("%s/gateway/aas/test", provider.gatewayEndpoint()), - "providerId", provider.getBpn()); - return proxyRequest(body); - } - - /** - * Pull the data using the Consumer DataPlane with an asset id - * - * @return the data - */ - public String pullProviderDataPlaneDataByAssetId(TxParticipant provider, String assetId) { - var body = Map.of("assetId", assetId); - return getProxyData(body); - } - - /** - * Pull the data using the Consumer DataPlane with an asset id and additional parameters - * - * @return the data - */ - public String pullProviderDataPlaneDataByAssetIdAndCustomProperties(TxParticipant provider, String assetId, String path, String params) { - var body = Map.of("assetId", assetId, "pathSegments", path, "queryParams", params); - return getProxyData(body); - } - - /** - * Pull the data using the Consumer DataPlane - * - * @return the data - */ - public String pullProviderDataPlaneDataByTransferProcessId(TxParticipant provider, String transferProcessId) { - var body = Map.of("transferProcessId", transferProcessId); - return getProxyData(body); - + public ParticipantDataApi() { } /** @@ -125,19 +53,4 @@ public String pullData(EndpointDataReference edr, Map queryParam return response.body().asString(); } - private String getProxyData(Map body) { - return proxyRequest(body) - .then() - .assertThat().statusCode(200) - .extract().body().asString(); - } - - private Response proxyRequest(Map body) { - return given() - .baseUri(participant.dataPlaneProxy().toString()) - .header("x-api-key", API_KEY) - .contentType("application/json") - .body(body) - .post(PROXY_SUBPATH); - } } diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/tx/ParticipantEdrApi.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/tx/ParticipantEdrApi.java index ce717fc23..801fc691e 100644 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/tx/ParticipantEdrApi.java +++ b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/tx/ParticipantEdrApi.java @@ -19,59 +19,24 @@ package org.eclipse.tractusx.edc.lifecycle.tx; -import io.restassured.response.ValidatableResponse; -import io.restassured.specification.RequestSpecification; -import jakarta.json.Json; -import jakarta.json.JsonArray; -import jakarta.json.JsonObject; import org.eclipse.edc.spi.types.domain.edr.EndpointDataReference; -import org.eclipse.edc.test.system.utils.Participant; import java.net.URI; import java.util.concurrent.atomic.AtomicReference; import static io.restassured.RestAssured.given; -import static io.restassured.http.ContentType.JSON; -import static jakarta.json.Json.createObjectBuilder; -import static org.assertj.core.api.Assertions.assertThat; -import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.CONTEXT; -import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.ID; -import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.TYPE; -import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.VOCAB; -import static org.eclipse.edc.jsonld.spi.PropertyAndTypeNames.ODRL_ASSIGNER_ATTRIBUTE; -import static org.eclipse.edc.jsonld.spi.PropertyAndTypeNames.ODRL_TARGET_ATTRIBUTE; -import static org.eclipse.edc.spi.CoreConstants.EDC_NAMESPACE; -import static org.eclipse.tractusx.edc.helpers.CatalogHelperFunctions.getDatasetContractId; -import static org.eclipse.tractusx.edc.helpers.CatalogHelperFunctions.getDatasetFirstPolicy; -import static org.eclipse.tractusx.edc.helpers.EdrNegotiationHelperFunctions.createEdrNegotiationRequest; /** * E2E test helper for the EDR APIs */ public class ParticipantEdrApi { - private final TxParticipant participant; private final URI edrBackend; - public ParticipantEdrApi(TxParticipant participant, Participant.Endpoint managementEndpoint, URI edrBackend) { - this.participant = participant; + public ParticipantEdrApi(URI edrBackend) { this.edrBackend = edrBackend; } - /** - * Get the cached EDR for a transfer process - * - * @param transferProcessId The transfer process id - * @return The EDR - */ - public JsonObject getEdr(String transferProcessId) { - return getEdrRequest(transferProcessId) - .statusCode(200) - .extract() - .body() - .as(JsonObject.class); - } - /** * Get the cached EDR for a transfer process cached in a backend * @@ -94,146 +59,4 @@ public EndpointDataReference getDataReferenceFromBackend(String transferProcessI return dataReference.get(); } - /** - * Get the cached EDR for a transfer process as {@link ValidatableResponse} - * - * @param transferProcessId The transfer process id - * @return The {@link ValidatableResponse} - */ - public ValidatableResponse getEdrRequest(String transferProcessId) { - return baseEdrRequest() - .when() - .get("/edrs/{id}", transferProcessId) - .then(); - } - - /** - * Get the cached EDR for a transfer process as {@link ValidatableResponse} - * - * @param transferProcessId The transfer process id - * @return The {@link ValidatableResponse} - */ - public ValidatableResponse getEdrRequestV2(String transferProcessId, boolean autoRefresh) { - return baseEdrRequest() - .when() - .get("/v2/edrs/{id}/dataaddress?auto_refresh={auto_refresh}", transferProcessId, autoRefresh) - .then() - .log().ifError(); - - } - - /** - * Triggers the explicit renewal of an EDR identified by {@code transferProcessId} - */ - public ValidatableResponse refreshEdr(String transferProcessId) { - return baseEdrRequest() - .when() - .post("/v2/edrs/{id}/refresh", transferProcessId) - .then() - .log().ifError(); - } - - /** - * Start an EDR negotiation using the EDRs API. - * - * @param other The provider - * @param assetId The asset ID - * @param callbacks The callbacks - * @return The contract negotiation id - */ - public String negotiateEdr(TxParticipant other, String assetId, JsonArray callbacks) { - var dataset = participant.getDatasetForAsset(other, assetId); - assertThat(dataset).withFailMessage("Catalog received from " + other.getName() + " was empty!").isNotEmpty(); - - var policy = createObjectBuilder(getDatasetFirstPolicy(dataset)) - .add(ODRL_TARGET_ATTRIBUTE, createObjectBuilder().add(ID, dataset.get(ID))) - .add(ODRL_ASSIGNER_ATTRIBUTE, createObjectBuilder().add(ID, other.getBpn())) - .build(); - var contractId = getDatasetContractId(dataset); - - var requestBody = createEdrNegotiationRequest(other.getProtocolEndpoint().getUrl().toString(), other.getBpn(), contractId.toString(), contractId.assetIdPart(), policy, callbacks); - - - var response = baseEdrRequest() - .when() - .body(requestBody) - .post("/edrs") - .then(); - - var body = response.extract().body().asString(); - assertThat(response.extract().statusCode()).withFailMessage(body).isBetween(200, 299); - - return response.extract().jsonPath().getString(ID); - } - - /** - * Get the cached EDRs for a contract negotiation - * - * @param contractNegotiationId The contract negotiation id - * @return The EDRs - */ - public JsonArray getEdrEntriesByContractNegotiationId(String contractNegotiationId) { - return baseEdrRequest() - .when() - .get("/edrs?contractNegotiationId={contractNegotiationId}", contractNegotiationId) - .then() - .statusCode(200) - .extract() - .body() - .as(JsonArray.class); - } - - /** - * Get the cached EDRs for a contract agreement - * - * @param agreementId The contract agreement id - * @return The EDRs - */ - public JsonArray getEdrEntriesByAgreementId(String agreementId) { - return baseEdrRequest() - .when() - .get("/edrs?agreementId={agreementId}", agreementId) - .then() - .statusCode(200) - .extract() - .body() - .as(JsonArray.class); - } - - /** - * Get the cached EDRs for an asset - * - * @param assetId The asset id - * @return The EDRs - */ - public JsonArray getEdrEntriesByAssetId(String assetId) { - return baseEdrRequest() - .when() - .get("/edrs?assetId={assetId}", assetId) - .then() - .statusCode(200) - .extract() - .body() - .as(JsonArray.class); - } - - /** - * Creates a query spec as JSON object that can be passed into the new EDR-V2 API (/request). Not yet used - */ - private String createQuery(String leftOp, String op, String rightOp) { - return Json.createObjectBuilder() - .add(CONTEXT, Json.createObjectBuilder().add(VOCAB, EDC_NAMESPACE).build()) - .add(TYPE, "QuerySpec") - .add("filterExpression", Json.createObjectBuilder() - .add("operandLeft", leftOp) - .add("operator", op) - .add("operandRight", rightOp) - .build()) - .build() - .toString(); - } - - private RequestSpecification baseEdrRequest() { - return participant.getManagementEndpoint().baseRequest().contentType(JSON); - } } diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/tx/TxParticipant.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/tx/TxParticipant.java index 1d1ac34cf..0bae06240 100644 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/tx/TxParticipant.java +++ b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/tx/TxParticipant.java @@ -195,6 +195,7 @@ public Map getConfiguration() { put("edc.data.encryption.keys.alias", "test-alias"); put("tx.dpf.proxy.gateway.aas.proxied.path", backendProviderProxy.toString()); put("tx.dpf.proxy.gateway.aas.authorization.type", "none"); + put("edc.iam.issuer.id", "did:web:" + name); } }; } @@ -301,8 +302,8 @@ public TxParticipant build() { super.timeout(ASYNC_TIMEOUT); super.build(); - this.participant.edrs = new ParticipantEdrApi(participant, participant.managementEndpoint, participant.backend); - this.participant.data = new ParticipantDataApi(participant); + this.participant.edrs = new ParticipantEdrApi(participant.backend); + this.participant.data = new ParticipantDataApi(); return participant; } } diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/edr/AbstractDeleteEdrTest.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/edr/AbstractDeleteEdrTest.java deleted file mode 100644 index 4a2a8164e..000000000 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/edr/AbstractDeleteEdrTest.java +++ /dev/null @@ -1,102 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.tests.edr; - -import jakarta.json.Json; -import org.eclipse.edc.policy.model.Operator; -import org.eclipse.tractusx.edc.lifecycle.tx.TxParticipant; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Map; -import java.util.UUID; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.awaitility.Awaitility.await; -import static org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntryStates.EXPIRED; -import static org.eclipse.tractusx.edc.helpers.PolicyHelperFunctions.bpnGroupPolicy; -import static org.eclipse.tractusx.edc.lifecycle.TestRuntimeConfiguration.PLATO_BPN; -import static org.eclipse.tractusx.edc.lifecycle.TestRuntimeConfiguration.PLATO_NAME; -import static org.eclipse.tractusx.edc.lifecycle.TestRuntimeConfiguration.SOKRATES_BPN; -import static org.eclipse.tractusx.edc.lifecycle.TestRuntimeConfiguration.SOKRATES_NAME; -import static org.eclipse.tractusx.edc.tests.TestCommon.ASYNC_TIMEOUT; - -public abstract class AbstractDeleteEdrTest { - - protected static final TxParticipant SOKRATES = TxParticipant.Builder.newInstance() - .name(SOKRATES_NAME) - .id(SOKRATES_BPN) - .build(); - - protected static final TxParticipant PLATO = TxParticipant.Builder.newInstance() - .name(PLATO_NAME) - .id(PLATO_BPN) - .build(); - - @Test - @DisplayName("Verify that expired EDR are deleted") - void negotiateEdr_shouldRemoveExpiredEdrs() throws IOException { - - var assetId = UUID.randomUUID().toString(); - - var authCodeHeaderName = "test-authkey"; - var authCode = "test-authcode"; - - Map dataAddress = Map.of( - "name", "transfer-test", - "baseUrl", "http://test:8080", - "type", "HttpData", - "contentType", "application/json", - "authKey", authCodeHeaderName, - "authCode", authCode - ); - PLATO.createAsset(assetId, Map.of(), dataAddress); - - PLATO.storeBusinessPartner(SOKRATES.getBpn(), "test-group1", "test-group2"); - var accessPolicy = PLATO.createPolicyDefinition(bpnGroupPolicy(Operator.NEQ, "forbidden-policy")); - var contractPolicy = PLATO.createPolicyDefinition(bpnGroupPolicy(Operator.EQ, "test-group1", "test-group2")); - PLATO.createContractDefinition(assetId, "def-1", accessPolicy, contractPolicy); - - var callbacks = Json.createArrayBuilder() - .build(); - - SOKRATES.edrs().negotiateEdr(PLATO, assetId, callbacks); - - var expired = new ArrayList(); - - await().atMost(ASYNC_TIMEOUT) - .untilAsserted(() -> { - var edrCaches = SOKRATES.edrs().getEdrEntriesByAssetId(assetId); - var localExpired = edrCaches.stream() - .filter(json -> json.asJsonObject().getJsonString("tx:edrState").getString().equals(EXPIRED.name())) - .map(json -> json.asJsonObject().getJsonString("transferProcessId").getString()) - .toList(); - assertThat(localExpired).hasSizeGreaterThan(0); - expired.add(localExpired.get(0)); - }); - - await().atMost(ASYNC_TIMEOUT) - .untilAsserted(() -> expired.forEach((id) -> SOKRATES.edrs().getEdrRequest(id).statusCode(404))); - - } - -} diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/edr/AbstractRenewalEdrTest.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/edr/AbstractRenewalEdrTest.java deleted file mode 100644 index 14a673495..000000000 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/edr/AbstractRenewalEdrTest.java +++ /dev/null @@ -1,183 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.tests.edr; - -import jakarta.json.Json; -import okhttp3.mockwebserver.MockResponse; -import okhttp3.mockwebserver.MockWebServer; -import org.assertj.core.api.Condition; -import org.eclipse.edc.connector.transfer.spi.event.TransferProcessStarted; -import org.eclipse.edc.connector.transfer.spi.types.TransferProcessStates; -import org.eclipse.edc.policy.model.Operator; -import org.eclipse.tractusx.edc.lifecycle.tx.TxParticipant; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; - -import java.io.IOException; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.UUID; -import java.util.stream.Collectors; - -import static org.assertj.core.api.Assertions.anyOf; -import static org.assertj.core.api.Assertions.assertThat; -import static org.awaitility.Awaitility.await; -import static org.awaitility.pollinterval.FibonacciPollInterval.fibonacci; -import static org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntryStates.EXPIRED; -import static org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntryStates.NEGOTIATED; -import static org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntryStates.REFRESHING; -import static org.eclipse.tractusx.edc.helpers.EdrNegotiationHelperFunctions.createCallback; -import static org.eclipse.tractusx.edc.helpers.EdrNegotiationHelperFunctions.createEvent; -import static org.eclipse.tractusx.edc.helpers.PolicyHelperFunctions.bpnGroupPolicy; -import static org.eclipse.tractusx.edc.lifecycle.TestRuntimeConfiguration.PLATO_BPN; -import static org.eclipse.tractusx.edc.lifecycle.TestRuntimeConfiguration.PLATO_NAME; -import static org.eclipse.tractusx.edc.lifecycle.TestRuntimeConfiguration.SOKRATES_BPN; -import static org.eclipse.tractusx.edc.lifecycle.TestRuntimeConfiguration.SOKRATES_NAME; -import static org.eclipse.tractusx.edc.tests.TestCommon.ASYNC_POLL_INTERVAL; -import static org.eclipse.tractusx.edc.tests.TestCommon.ASYNC_TIMEOUT; -import static org.eclipse.tractusx.edc.tests.edr.TestFunctions.waitForEvent; - -public abstract class AbstractRenewalEdrTest { - - protected static final TxParticipant SOKRATES = TxParticipant.Builder.newInstance() - .name(SOKRATES_NAME) - .id(SOKRATES_BPN) - .build(); - - protected static final TxParticipant PLATO = TxParticipant.Builder.newInstance() - .name(PLATO_NAME) - .id(PLATO_BPN) - .build(); - - MockWebServer server; - - @BeforeEach - void setup() { - server = new MockWebServer(); - } - - @Test - @DisplayName("Verify that the EDR is renewed") - void negotiateEdr_shouldRenewTheEdr() throws IOException { - - var expectedEvents = List.of( - createEvent(TransferProcessStarted.class), - createEvent(TransferProcessStarted.class)); - - var assetId = UUID.randomUUID().toString(); - var url = server.url("/mock/api"); - server.start(); - - var authCodeHeaderName = "test-authkey"; - var authCode = "test-authcode"; - - Map dataAddress = Map.of( - "name", "transfer-test", - "baseUrl", url.toString(), - "type", "HttpData", - "contentType", "application/json", - "authKey", authCodeHeaderName, - "authCode", authCode - ); - - PLATO.createAsset(assetId, Map.of(), dataAddress); - - PLATO.storeBusinessPartner(SOKRATES.getBpn(), "test-group1", "test-group2"); - var accessPolicy = PLATO.createPolicyDefinition(bpnGroupPolicy(Operator.IS_NONE_OF, "forbidden-policy")); - var contractPolicy = PLATO.createPolicyDefinition(bpnGroupPolicy(Operator.IS_ANY_OF, "test-group1", "test-group2")); - PLATO.createContractDefinition(assetId, "def-1", accessPolicy, contractPolicy); - - var callbacks = Json.createArrayBuilder() - .add(createCallback(url.toString(), true, Set.of("transfer.process.started"))) - .build(); - - expectedEvents.forEach(event -> server.enqueue(new MockResponse())); - - SOKRATES.edrs().negotiateEdr(PLATO, assetId, callbacks); - - var events = expectedEvents.stream() - .map(receivedEvent -> waitForEvent(server)) - .collect(Collectors.toList()); - - assertThat(expectedEvents).usingRecursiveFieldByFieldElementComparator().containsAll(events); - - var edrCachesBuilder = Json.createArrayBuilder(); - - await().atMost(ASYNC_TIMEOUT) - .pollInterval(ASYNC_POLL_INTERVAL) - .untilAsserted(() -> { - var localEdrCaches = SOKRATES.edrs().getEdrEntriesByAssetId(assetId); - assertThat(localEdrCaches).hasSizeGreaterThan(1); - localEdrCaches.forEach(edrCachesBuilder::add); - }); - - var edrCaches = edrCachesBuilder.build(); - - assertThat(edrCaches) - .extracting(json -> json.asJsonObject().getJsonString("tx:edrState").getString()) - .areAtMost(1, anyOf(stateCondition(NEGOTIATED.name(), "Negotiated"), stateCondition(REFRESHING.name(), "Refreshing"))) - .areAtLeast(1, stateCondition(EXPIRED.name(), "Expired")); - - var transferProcessId = edrCaches.stream() - .filter(json -> json.asJsonObject().getJsonString("tx:edrState").getString().equals(EXPIRED.name())) - .map(json -> json.asJsonObject().getJsonString("transferProcessId").getString()) - .findFirst() - .orElseThrow(); - - // Check Termination on Sokrates - await().pollInterval(fibonacci()) - .atMost(ASYNC_TIMEOUT) - .untilAsserted(() -> { - var tpState = SOKRATES.getTransferProcessState(transferProcessId); - assertThat(tpState).isNotNull().isEqualTo(TransferProcessStates.TERMINATED.toString()); - }); - - - // Check Termination on Plato - await().pollInterval(fibonacci()) - .atMost(ASYNC_TIMEOUT) - .untilAsserted(() -> { - var tpState = PLATO.getTransferProcesses() - .stream() - .filter(json -> json.asJsonObject().getJsonString("correlationId").getString().equals(transferProcessId)) - .map(json -> json.asJsonObject().getJsonString("state").getString()) - .findFirst(); - - assertThat(tpState) - .isPresent() - .hasValue(TransferProcessStates.TERMINATED.toString()); - }); - } - - - @AfterEach - void teardown() throws IOException { - server.shutdown(); - } - - - private Condition stateCondition(String value, String description) { - return new Condition<>(m -> m.equals(value), description); - } - -} diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/edr/DeleteEdrInMemoryTest.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/edr/DeleteEdrInMemoryTest.java deleted file mode 100644 index 4e1c606b1..000000000 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/edr/DeleteEdrInMemoryTest.java +++ /dev/null @@ -1,63 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.tests.edr; - - -import com.nimbusds.jose.util.Base64; -import org.eclipse.edc.junit.annotations.EndToEndTest; -import org.eclipse.edc.spi.security.Vault; -import org.eclipse.tractusx.edc.lifecycle.ParticipantRuntime; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.extension.RegisterExtension; - -import java.security.SecureRandom; - -@EndToEndTest -public class DeleteEdrInMemoryTest extends AbstractDeleteEdrTest { - - @RegisterExtension - protected static final ParticipantRuntime SOKRATES_RUNTIME = new ParticipantRuntime( - ":edc-tests:runtime:runtime-memory", - SOKRATES.getName(), - SOKRATES.getBpn(), - SOKRATES.renewalConfiguration("5") - ); - - @RegisterExtension - protected static final ParticipantRuntime PLATO_RUNTIME = new ParticipantRuntime( - ":edc-tests:runtime:runtime-memory", - PLATO.getName(), - PLATO.getBpn(), - PLATO.renewalConfiguration() - ); - - @BeforeAll - static void prepare() { - var bytes = new byte[32]; - - new SecureRandom().nextBytes(bytes); - var value = Base64.encode(bytes).toString(); - var vault = SOKRATES_RUNTIME.getContext().getService(Vault.class); - vault.storeSecret("test-alias", value); - vault = PLATO_RUNTIME.getContext().getService(Vault.class); - vault.storeSecret("test-alias", value); - - } -} diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/edr/DeleteEdrPostgresqlTest.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/edr/DeleteEdrPostgresqlTest.java deleted file mode 100644 index 518393325..000000000 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/edr/DeleteEdrPostgresqlTest.java +++ /dev/null @@ -1,44 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.tests.edr; - -import org.eclipse.edc.junit.annotations.PostgresqlIntegrationTest; -import org.eclipse.tractusx.edc.lifecycle.PgParticipantRuntime; -import org.junit.jupiter.api.extension.RegisterExtension; - -@PostgresqlIntegrationTest -public class DeleteEdrPostgresqlTest extends AbstractDeleteEdrTest { - - @RegisterExtension - protected static final PgParticipantRuntime SOKRATES_RUNTIME = new PgParticipantRuntime( - ":edc-tests:runtime:runtime-postgresql", - SOKRATES.getName(), - SOKRATES.getBpn(), - SOKRATES.renewalConfiguration("5") - ); - @RegisterExtension - protected static final PgParticipantRuntime PLATO_RUNTIME = new PgParticipantRuntime( - ":edc-tests:runtime:runtime-postgresql", - PLATO.getName(), - PLATO.getBpn(), - PLATO.renewalConfiguration() - ); - -} diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/edr/NegotiateEdrPostgresqlHashicorpVaultTest.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/edr/NegotiateEdrPostgresqlHashicorpVaultTest.java deleted file mode 100644 index db2768d4d..000000000 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/edr/NegotiateEdrPostgresqlHashicorpVaultTest.java +++ /dev/null @@ -1,48 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.tests.edr; - -import org.eclipse.edc.junit.annotations.PostgresqlIntegrationTest; -import org.eclipse.tractusx.edc.lifecycle.PgHashicorpParticipantRuntime; -import org.eclipse.tractusx.edc.lifecycle.PgParticipantRuntime; -import org.junit.jupiter.api.extension.RegisterExtension; - -@PostgresqlIntegrationTest -public class NegotiateEdrPostgresqlHashicorpVaultTest extends AbstractNegotiateEdrTest { - - @RegisterExtension - protected static final PgParticipantRuntime PLATO_RUNTIME = new PgParticipantRuntime( - ":edc-tests:runtime:runtime-postgresql", - PLATO.getName(), - PLATO.getBpn(), - PLATO.getConfiguration() - ); - private static final String VAULT_DIRECTORY = "testDir/"; - - @RegisterExtension - protected static final PgHashicorpParticipantRuntime SOKRATES_RUNTIME = new PgHashicorpParticipantRuntime( - ":edc-tests:runtime:runtime-postgresql-hashicorp", - SOKRATES.getName(), - SOKRATES.getBpn(), - VAULT_DIRECTORY, - SOKRATES.getConfiguration() - ); - -} diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/edr/NegotiateEdrPostgresqlTest.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/edr/NegotiateEdrPostgresqlTest.java deleted file mode 100644 index f42c9bd3e..000000000 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/edr/NegotiateEdrPostgresqlTest.java +++ /dev/null @@ -1,44 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.tests.edr; - -import org.eclipse.edc.junit.annotations.PostgresqlIntegrationTest; -import org.eclipse.tractusx.edc.lifecycle.PgParticipantRuntime; -import org.junit.jupiter.api.extension.RegisterExtension; - -@PostgresqlIntegrationTest -public class NegotiateEdrPostgresqlTest extends AbstractNegotiateEdrTest { - - @RegisterExtension - protected static final PgParticipantRuntime SOKRATES_RUNTIME = new PgParticipantRuntime( - ":edc-tests:runtime:runtime-postgresql", - SOKRATES.getName(), - SOKRATES.getBpn(), - SOKRATES.getConfiguration() - ); - @RegisterExtension - protected static final PgParticipantRuntime PLATO_RUNTIME = new PgParticipantRuntime( - ":edc-tests:runtime:runtime-postgresql", - PLATO.getName(), - PLATO.getBpn(), - PLATO.getConfiguration() - ); - -} diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/edr/RenewalEdrInMemoryTest.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/edr/RenewalEdrInMemoryTest.java deleted file mode 100644 index ae0b7df87..000000000 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/edr/RenewalEdrInMemoryTest.java +++ /dev/null @@ -1,63 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.tests.edr; - - -import com.nimbusds.jose.util.Base64; -import org.eclipse.edc.junit.annotations.EndToEndTest; -import org.eclipse.edc.spi.security.Vault; -import org.eclipse.tractusx.edc.lifecycle.ParticipantRuntime; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.extension.RegisterExtension; - -import java.security.SecureRandom; - -@EndToEndTest -public class RenewalEdrInMemoryTest extends AbstractRenewalEdrTest { - - @RegisterExtension - protected static final ParticipantRuntime SOKRATES_RUNTIME = new ParticipantRuntime( - ":edc-tests:runtime:runtime-memory", - SOKRATES.getName(), - SOKRATES.getBpn(), - SOKRATES.renewalConfiguration() - ); - - @RegisterExtension - protected static final ParticipantRuntime PLATO_RUNTIME = new ParticipantRuntime( - ":edc-tests:runtime:runtime-memory", - PLATO.getName(), - PLATO.getBpn(), - PLATO.renewalConfiguration() - ); - - @BeforeAll - static void prepare() { - var bytes = new byte[32]; - - new SecureRandom().nextBytes(bytes); - var value = Base64.encode(bytes).toString(); - var vault = SOKRATES_RUNTIME.getContext().getService(Vault.class); - vault.storeSecret("test-alias", value); - vault = PLATO_RUNTIME.getContext().getService(Vault.class); - vault.storeSecret("test-alias", value); - - } -} diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/edr/RenewalEdrPostgresqlTest.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/edr/RenewalEdrPostgresqlTest.java deleted file mode 100644 index 9a99b5378..000000000 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/edr/RenewalEdrPostgresqlTest.java +++ /dev/null @@ -1,44 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.tests.edr; - -import org.eclipse.edc.junit.annotations.PostgresqlIntegrationTest; -import org.eclipse.tractusx.edc.lifecycle.PgParticipantRuntime; -import org.junit.jupiter.api.extension.RegisterExtension; - -@PostgresqlIntegrationTest -public class RenewalEdrPostgresqlTest extends AbstractRenewalEdrTest { - - @RegisterExtension - protected static final PgParticipantRuntime SOKRATES_RUNTIME = new PgParticipantRuntime( - ":edc-tests:runtime:runtime-postgresql", - SOKRATES.getName(), - SOKRATES.getBpn(), - SOKRATES.renewalConfiguration() - ); - @RegisterExtension - protected static final PgParticipantRuntime PLATO_RUNTIME = new PgParticipantRuntime( - ":edc-tests:runtime:runtime-postgresql", - PLATO.getName(), - PLATO.getBpn(), - PLATO.renewalConfiguration() - ); - -} diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/edr/TestFunctions.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/edr/TestFunctions.java deleted file mode 100644 index 64a99c5eb..000000000 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/edr/TestFunctions.java +++ /dev/null @@ -1,45 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.tests.edr; - -import com.fasterxml.jackson.databind.ObjectMapper; -import okhttp3.mockwebserver.MockWebServer; -import org.eclipse.tractusx.edc.helpers.ReceivedEvent; - -import java.util.concurrent.TimeUnit; - -public class TestFunctions { - - - private static final ObjectMapper MAPPER = new ObjectMapper(); - - public static ReceivedEvent waitForEvent(MockWebServer server) { - try { - var request = server.takeRequest(60, TimeUnit.SECONDS); - if (request != null) { - return MAPPER.readValue(request.getBody().inputStream(), ReceivedEvent.class); - } else { - throw new RuntimeException("Timeout exceeded waiting for events"); - } - } catch (Exception e) { - throw new RuntimeException(e); - } - } -} diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/proxy/AbstractDataPlaneProxyTest.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/proxy/AbstractDataPlaneProxyTest.java deleted file mode 100644 index f5f020bd3..000000000 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/proxy/AbstractDataPlaneProxyTest.java +++ /dev/null @@ -1,328 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.tests.proxy; - -import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.ObjectMapper; -import jakarta.json.Json; -import okhttp3.mockwebserver.Dispatcher; -import okhttp3.mockwebserver.MockResponse; -import okhttp3.mockwebserver.MockWebServer; -import okhttp3.mockwebserver.RecordedRequest; -import org.eclipse.edc.connector.transfer.spi.event.TransferProcessStarted; -import org.eclipse.edc.policy.model.Operator; -import org.eclipse.edc.spi.event.EventEnvelope; -import org.eclipse.tractusx.edc.lifecycle.tx.TxParticipant; -import org.jetbrains.annotations.NotNull; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; - -import java.io.IOException; -import java.util.Map; -import java.util.Set; -import java.util.UUID; -import java.util.concurrent.TimeUnit; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.awaitility.Awaitility.await; -import static org.eclipse.tractusx.edc.helpers.EdrNegotiationHelperFunctions.createCallback; -import static org.eclipse.tractusx.edc.helpers.PolicyHelperFunctions.bpnGroupPolicy; -import static org.eclipse.tractusx.edc.lifecycle.TestRuntimeConfiguration.PLATO_BPN; -import static org.eclipse.tractusx.edc.lifecycle.TestRuntimeConfiguration.PLATO_NAME; -import static org.eclipse.tractusx.edc.lifecycle.TestRuntimeConfiguration.SOKRATES_BPN; -import static org.eclipse.tractusx.edc.lifecycle.TestRuntimeConfiguration.SOKRATES_NAME; -import static org.eclipse.tractusx.edc.tests.TestCommon.ASYNC_POLL_INTERVAL; -import static org.eclipse.tractusx.edc.tests.TestCommon.ASYNC_TIMEOUT; - -public abstract class AbstractDataPlaneProxyTest { - - protected static final TxParticipant SOKRATES = TxParticipant.Builder.newInstance() - .name(SOKRATES_NAME) - .id(SOKRATES_BPN) - .build(); - - protected static final TxParticipant PLATO = TxParticipant.Builder.newInstance() - .name(PLATO_NAME) - .id(PLATO_BPN) - .build(); - private static final String CUSTOM_BASE_PATH = "/custom"; - private static final String CUSTOM_SUB_PATH = "/sub"; - private static final String CUSTOM_QUERY_PARAMS = "foo=bar"; - private static final String CUSTOM_FULL_PATH = CUSTOM_BASE_PATH + CUSTOM_SUB_PATH + "?" + CUSTOM_QUERY_PARAMS; - private final ObjectMapper mapper = new ObjectMapper(); - private MockWebServer server; - - @NotNull - private static Map dataAddress(String url) { - return Map.of( - "baseUrl", url, - "type", "HttpData", - "contentType", "application/json", - "authKey", "test-authkey", - "authCode", "test-authcode", - "proxyPath", "true", - "proxyQueryParams", "true" - ); - } - - @Test - @DisplayName("Verify E2E flow with Data Plane proxies and EDR") - void httpPullDataTransfer_withEdrAndProxy() { - - var eventsUrl = server.url(PLATO.backendProviderProxy().getPath()); - - var assetId = UUID.randomUUID().toString(); - - var dataAddress = dataAddress(eventsUrl.url().toString()); - - PLATO.createAsset(assetId, Map.of(), dataAddress); - - PLATO.storeBusinessPartner(SOKRATES.getBpn(), "test-group1", "test-group2"); - var accessPolicy = PLATO.createPolicyDefinition(bpnGroupPolicy(Operator.IS_ANY_OF, "test-group1")); - var contractPolicy = PLATO.createPolicyDefinition(bpnGroupPolicy(Operator.IS_ALL_OF, "test-group1", "test-group2")); - PLATO.createContractDefinition(assetId, "def-1", accessPolicy, contractPolicy); - - var callbacks = Json.createArrayBuilder() - .add(createCallback(eventsUrl.toString(), true, Set.of("transfer.process.started"))) - .build(); - - // response to callback - server.enqueue(new MockResponse()); - - SOKRATES.edrs().negotiateEdr(PLATO, assetId, callbacks); - - var transferEvent = waitForTransferCompletion(); - - await().pollInterval(ASYNC_POLL_INTERVAL) - .atMost(ASYNC_TIMEOUT) - .untilAsserted(() -> { - var edrCaches = SOKRATES.edrs().getEdrEntriesByAssetId(assetId); - assertThat(edrCaches).hasSize(1); - }); - - var body = "{\"response\": \"ok\"}"; - - server.enqueue(new MockResponse().setBody(body)); - var data = SOKRATES.data().pullProxyDataByAssetId(PLATO, assetId); - assertThat(data).isEqualTo(body); - - server.enqueue(new MockResponse().setBody(body)); - data = SOKRATES.data().pullProxyDataByTransferProcessId(PLATO, transferEvent.getPayload().getTransferProcessId()); - assertThat(data).isEqualTo(body); - } - - @Test - @DisplayName("Verify E2E flow with Data Plane proxies fails when EDR is not found") - void httpPullDataTransfer_withoutEdr() throws IOException { - - var eventsUrl = server.url(PLATO.backendProviderProxy().getPath()); - var assetId = UUID.randomUUID().toString(); - - PLATO.createAsset(assetId, Map.of(), dataAddress(eventsUrl.url().toString())); - - - PLATO.storeBusinessPartner(SOKRATES.getBpn(), "test-group1", "test-group2"); - var accessPolicy = PLATO.createPolicyDefinition(bpnGroupPolicy(Operator.NEQ, "forbidden-policy")); - var contractPolicy = PLATO.createPolicyDefinition(bpnGroupPolicy(Operator.EQ, "test-group1", "test-group2")); - PLATO.createContractDefinition(assetId, "def-1", accessPolicy, contractPolicy); - - - SOKRATES.data().pullProxyDataResponseByAssetId(PLATO, assetId) - .then() - .assertThat().statusCode(400); - - } - - @Test - @DisplayName("Verify E2E flow with Data Plane proxies and Two EDR") - void httpPullDataTransfer_shouldFailForAsset_withTwoEdrAndProxy() throws IOException { - - var eventsUrl = server.url(PLATO.backendProviderProxy().getPath()); - - var assetId = UUID.randomUUID().toString(); - - PLATO.createAsset(assetId, Map.of(), dataAddress(eventsUrl.url().toString())); - - PLATO.storeBusinessPartner(SOKRATES.getBpn(), "test-group1", "test-group2"); - var accessPolicy = PLATO.createPolicyDefinition(bpnGroupPolicy(Operator.IS_NONE_OF, "forbidden-policy")); - var contractPolicy = PLATO.createPolicyDefinition(bpnGroupPolicy(Operator.IS_ALL_OF, "test-group1", "test-group2")); - PLATO.createContractDefinition(assetId, "def-1", accessPolicy, contractPolicy); - - var callbacks = Json.createArrayBuilder() - .add(createCallback(eventsUrl.toString(), true, Set.of("transfer.process.started"))) - .build(); - - // response to callback - server.enqueue(new MockResponse()); - server.enqueue(new MockResponse()); - - SOKRATES.edrs().negotiateEdr(PLATO, assetId, callbacks); - SOKRATES.edrs().negotiateEdr(PLATO, assetId, callbacks); - - var transferEvent1 = waitForTransferCompletion(); - var transferEvent2 = waitForTransferCompletion(); - - await().pollInterval(ASYNC_POLL_INTERVAL) - .atMost(ASYNC_TIMEOUT) - .untilAsserted(() -> { - var edrCaches = SOKRATES.edrs().getEdrEntriesByAssetId(assetId); - assertThat(edrCaches).hasSize(2); - }); - - - var body = "{\"response\": \"ok\"}"; - - server.enqueue(new MockResponse().setBody(body)); - SOKRATES.data().pullProxyDataResponseByAssetId(PLATO, assetId).then() - .assertThat().statusCode(428); - - server.enqueue(new MockResponse().setBody(body)); - var data = SOKRATES.data().pullProxyDataByTransferProcessId(PLATO, transferEvent1.getPayload().getTransferProcessId()); - assertThat(data).isEqualTo(body); - - server.enqueue(new MockResponse().setBody(body)); - data = SOKRATES.data().pullProxyDataByTransferProcessId(PLATO, transferEvent2.getPayload().getTransferProcessId()); - assertThat(data).isEqualTo(body); - } - - @Test - @DisplayName("Verify E2E flow with Data Plane provider and EDR") - void httpPullDataTransfer_withEdrAndProviderDataPlaneProxy() throws IOException { - - var eventsUrl = server.url(PLATO.backendProviderProxy().getPath()); - var assetId = UUID.randomUUID().toString(); - PLATO.createAsset(assetId, Map.of(), dataAddress(eventsUrl.url().toString())); - - PLATO.storeBusinessPartner(SOKRATES.getBpn(), "test-group1", "test-group2"); - var accessPolicy = PLATO.createPolicyDefinition(bpnGroupPolicy(Operator.IS_ANY_OF, "test-group1")); - var contractPolicy = PLATO.createPolicyDefinition(bpnGroupPolicy(Operator.IS_ALL_OF, "test-group1", "test-group2")); - PLATO.createContractDefinition(assetId, "def-1", accessPolicy, contractPolicy); - - var callbacks = Json.createArrayBuilder() - .add(createCallback(eventsUrl.toString(), true, Set.of("transfer.process.started"))) - .build(); - - // response to callback - server.enqueue(new MockResponse()); - - SOKRATES.edrs().negotiateEdr(PLATO, assetId, callbacks); - - var transferEvent = waitForTransferCompletion(); - - await().pollInterval(ASYNC_POLL_INTERVAL) - .atMost(ASYNC_TIMEOUT) - .untilAsserted(() -> { - var edrCaches = SOKRATES.edrs().getEdrEntriesByAssetId(assetId); - assertThat(edrCaches).hasSize(1); - }); - - var body = "{\"response\": \"ok\"}"; - - server.enqueue(new MockResponse().setBody(body)); - var data = SOKRATES.data().pullProviderDataPlaneDataByAssetId(PLATO, assetId); - assertThat(data).isEqualTo(body); - - server.enqueue(new MockResponse().setBody(body)); - data = SOKRATES.data().pullProviderDataPlaneDataByTransferProcessId(PLATO, transferEvent.getPayload().getTransferProcessId()); - assertThat(data).isEqualTo(body); - } - - @Test - @DisplayName("Verify E2E flow with Data Plane provider and EDR") - void httpPullDataTransfer_withEdrAndProviderDataPlaneProxyAndCustomProperties() throws IOException { - - var eventsPath = PLATO.backendProviderProxy().getPath(); - var eventsUrl = server.url(eventsPath); - - var customUrl = server.url(CUSTOM_BASE_PATH); - - var body = "{\"response\": \"ok\"}"; - - server.setDispatcher(new Dispatcher() { - @NotNull - @Override - public MockResponse dispatch(@NotNull RecordedRequest recordedRequest) throws InterruptedException { - var path = recordedRequest.getPath(); - if (PLATO.backendProviderProxy().getPath().equals(path)) { - return new MockResponse(); - } else if (CUSTOM_FULL_PATH.equals(path)) { - return new MockResponse().setBody(body); - } else { - return new MockResponse().setResponseCode(404); - } - } - }); - - var assetId = UUID.randomUUID().toString(); - PLATO.createAsset(assetId, Map.of(), dataAddress(customUrl.url().toString())); - - PLATO.storeBusinessPartner(SOKRATES.getBpn(), "test-group1", "test-group2"); - var accessPolicy = PLATO.createPolicyDefinition(bpnGroupPolicy(Operator.NEQ, "forbidden-policy")); - var contractPolicy = PLATO.createPolicyDefinition(bpnGroupPolicy(Operator.EQ, "test-group1", "test-group2")); - PLATO.createContractDefinition(assetId, "def-1", accessPolicy, contractPolicy); - - var callbacks = Json.createArrayBuilder() - .add(createCallback(eventsUrl.toString(), true, Set.of("transfer.process.started"))) - .build(); - - SOKRATES.edrs().negotiateEdr(PLATO, assetId, callbacks); - - waitForTransferCompletion(); - - await().pollInterval(ASYNC_POLL_INTERVAL) - .atMost(ASYNC_TIMEOUT) - .untilAsserted(() -> { - var edrCaches = SOKRATES.edrs().getEdrEntriesByAssetId(assetId); - assertThat(edrCaches).hasSize(1); - }); - - var data = SOKRATES.data().pullProviderDataPlaneDataByAssetIdAndCustomProperties(PLATO, assetId, CUSTOM_SUB_PATH, CUSTOM_QUERY_PARAMS); - assertThat(data).isEqualTo(body); - - } - - @BeforeEach - void setup() throws IOException { - server = new MockWebServer(); - server.start(PLATO.backendProviderProxy().getPort()); - } - - @AfterEach - void teardown() throws IOException { - server.shutdown(); - } - - private EventEnvelope waitForTransferCompletion() { - try { - var request = server.takeRequest(60, TimeUnit.SECONDS); - if (request != null) { - return mapper.readValue(request.getBody().inputStream(), new TypeReference<>() { - }); - } else { - throw new RuntimeException("Timeout exceeded waiting for events"); - } - } catch (Exception e) { - throw new RuntimeException(e); - } - } - -} diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/proxy/DataPlaneProxyInMemoryTest.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/proxy/DataPlaneProxyInMemoryTest.java deleted file mode 100644 index 66f959807..000000000 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/proxy/DataPlaneProxyInMemoryTest.java +++ /dev/null @@ -1,62 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.tests.proxy; - -import com.nimbusds.jose.util.Base64; -import org.eclipse.edc.junit.annotations.EndToEndTest; -import org.eclipse.edc.spi.security.Vault; -import org.eclipse.tractusx.edc.lifecycle.ParticipantRuntime; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.extension.RegisterExtension; - -import java.security.SecureRandom; - -@EndToEndTest -public class DataPlaneProxyInMemoryTest extends AbstractDataPlaneProxyTest { - - @RegisterExtension - protected static final ParticipantRuntime SOKRATES_RUNTIME = new ParticipantRuntime( - ":edc-tests:runtime:runtime-memory", - SOKRATES.getName(), - SOKRATES.getBpn(), - SOKRATES.getConfiguration() - ); - - @RegisterExtension - protected static final ParticipantRuntime PLATO_RUNTIME = new ParticipantRuntime( - ":edc-tests:runtime:runtime-memory", - PLATO.getName(), - PLATO.getBpn(), - PLATO.getConfiguration() - ); - - @BeforeAll - static void prepare() { - var bytes = new byte[32]; - - new SecureRandom().nextBytes(bytes); - var value = Base64.encode(bytes).toString(); - var vault = SOKRATES_RUNTIME.getContext().getService(Vault.class); - vault.storeSecret("test-alias", value); - vault = PLATO_RUNTIME.getContext().getService(Vault.class); - vault.storeSecret("test-alias", value); - - } -} diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/proxy/DataPlaneProxyPostgresqlTest.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/proxy/DataPlaneProxyPostgresqlTest.java deleted file mode 100644 index 9d70e013e..000000000 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/proxy/DataPlaneProxyPostgresqlTest.java +++ /dev/null @@ -1,43 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.tests.proxy; - -import org.eclipse.edc.junit.annotations.PostgresqlIntegrationTest; -import org.eclipse.tractusx.edc.lifecycle.PgParticipantRuntime; -import org.junit.jupiter.api.extension.RegisterExtension; - -@PostgresqlIntegrationTest -public class DataPlaneProxyPostgresqlTest extends AbstractDataPlaneProxyTest { - - @RegisterExtension - protected static final PgParticipantRuntime SOKRATES_RUNTIME = new PgParticipantRuntime( - ":edc-tests:runtime:runtime-postgresql", - SOKRATES.getName(), - SOKRATES.getBpn(), - SOKRATES.getConfiguration() - ); - @RegisterExtension - protected static final PgParticipantRuntime PLATO_RUNTIME = new PgParticipantRuntime( - ":edc-tests:runtime:runtime-postgresql", - PLATO.getName(), - PLATO.getBpn(), - PLATO.getConfiguration() - ); -} diff --git a/edc-extensions/data-encryption/build.gradle.kts b/edc-tests/edc-controlplane/catalog-tests/build.gradle.kts similarity index 74% rename from edc-extensions/data-encryption/build.gradle.kts rename to edc-tests/edc-controlplane/catalog-tests/build.gradle.kts index 0e2e546dc..d0de250c2 100644 --- a/edc-extensions/data-encryption/build.gradle.kts +++ b/edc-tests/edc-controlplane/catalog-tests/build.gradle.kts @@ -19,11 +19,20 @@ plugins { `java-library` + `java-test-fixtures` } dependencies { - api(libs.edc.spi.core) - implementation(libs.edc.spi.dataplane.transfer) - implementation(libs.edc.dpf.transfer) + testImplementation(testFixtures(project(":edc-tests:edc-controlplane:fixtures"))) + + testImplementation(libs.netty.mockserver) testImplementation(libs.edc.junit) + testImplementation(libs.restAssured) + testImplementation(libs.awaitility) + testImplementation(libs.okhttp.mockwebserver) +} + +// do not publish +edcBuild { + publish.set(false) } diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/catalog/AbstractCatalogTest.java b/edc-tests/edc-controlplane/catalog-tests/src/test/java/org/eclipse/tractusx/edc/tests/catalog/AbstractCatalogTest.java similarity index 88% rename from edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/catalog/AbstractCatalogTest.java rename to edc-tests/edc-controlplane/catalog-tests/src/test/java/org/eclipse/tractusx/edc/tests/catalog/AbstractCatalogTest.java index 497d021ee..063c16439 100644 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/catalog/AbstractCatalogTest.java +++ b/edc-tests/edc-controlplane/catalog-tests/src/test/java/org/eclipse/tractusx/edc/tests/catalog/AbstractCatalogTest.java @@ -21,7 +21,7 @@ import org.eclipse.edc.policy.model.Operator; -import org.eclipse.tractusx.edc.lifecycle.tx.TxParticipant; +import org.eclipse.tractusx.edc.tests.TxParticipant; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -30,17 +30,17 @@ import static java.util.stream.IntStream.range; import static org.assertj.core.api.Assertions.assertThat; import static org.eclipse.edc.test.system.utils.PolicyFixtures.noConstraintPolicy; -import static org.eclipse.tractusx.edc.helpers.CatalogHelperFunctions.getDatasetAssetId; -import static org.eclipse.tractusx.edc.helpers.CatalogHelperFunctions.getDatasetPolicies; -import static org.eclipse.tractusx.edc.helpers.PolicyHelperFunctions.BUSINESS_PARTNER_LEGACY_EVALUATION_KEY; -import static org.eclipse.tractusx.edc.helpers.PolicyHelperFunctions.bnpPolicy; -import static org.eclipse.tractusx.edc.helpers.PolicyHelperFunctions.bpnGroupPolicy; -import static org.eclipse.tractusx.edc.helpers.PolicyHelperFunctions.frameworkPolicy; -import static org.eclipse.tractusx.edc.helpers.QueryHelperFunctions.createQuery; -import static org.eclipse.tractusx.edc.lifecycle.TestRuntimeConfiguration.PLATO_BPN; -import static org.eclipse.tractusx.edc.lifecycle.TestRuntimeConfiguration.PLATO_NAME; -import static org.eclipse.tractusx.edc.lifecycle.TestRuntimeConfiguration.SOKRATES_BPN; -import static org.eclipse.tractusx.edc.lifecycle.TestRuntimeConfiguration.SOKRATES_NAME; +import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.PLATO_BPN; +import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.PLATO_NAME; +import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.SOKRATES_BPN; +import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.SOKRATES_NAME; +import static org.eclipse.tractusx.edc.tests.helpers.CatalogHelperFunctions.getDatasetAssetId; +import static org.eclipse.tractusx.edc.tests.helpers.CatalogHelperFunctions.getDatasetPolicies; +import static org.eclipse.tractusx.edc.tests.helpers.PolicyHelperFunctions.BUSINESS_PARTNER_LEGACY_EVALUATION_KEY; +import static org.eclipse.tractusx.edc.tests.helpers.PolicyHelperFunctions.bnpPolicy; +import static org.eclipse.tractusx.edc.tests.helpers.PolicyHelperFunctions.bpnGroupPolicy; +import static org.eclipse.tractusx.edc.tests.helpers.PolicyHelperFunctions.frameworkPolicy; +import static org.eclipse.tractusx.edc.tests.helpers.QueryHelperFunctions.createQuery; public abstract class AbstractCatalogTest { diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/catalog/CatalogInMemoryTest.java b/edc-tests/edc-controlplane/catalog-tests/src/test/java/org/eclipse/tractusx/edc/tests/catalog/CatalogInMemoryTest.java similarity index 96% rename from edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/catalog/CatalogInMemoryTest.java rename to edc-tests/edc-controlplane/catalog-tests/src/test/java/org/eclipse/tractusx/edc/tests/catalog/CatalogInMemoryTest.java index 1f93986a5..17e3496cd 100644 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/catalog/CatalogInMemoryTest.java +++ b/edc-tests/edc-controlplane/catalog-tests/src/test/java/org/eclipse/tractusx/edc/tests/catalog/CatalogInMemoryTest.java @@ -20,7 +20,7 @@ package org.eclipse.tractusx.edc.tests.catalog; import org.eclipse.edc.junit.annotations.EndToEndTest; -import org.eclipse.tractusx.edc.lifecycle.ParticipantRuntime; +import org.eclipse.tractusx.edc.tests.runtimes.ParticipantRuntime; import org.junit.jupiter.api.extension.RegisterExtension; @EndToEndTest diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/catalog/CatalogPostgresqlTest.java b/edc-tests/edc-controlplane/catalog-tests/src/test/java/org/eclipse/tractusx/edc/tests/catalog/CatalogPostgresqlTest.java similarity index 96% rename from edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/catalog/CatalogPostgresqlTest.java rename to edc-tests/edc-controlplane/catalog-tests/src/test/java/org/eclipse/tractusx/edc/tests/catalog/CatalogPostgresqlTest.java index 8c9a11e7b..a7a8cb0bf 100644 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/catalog/CatalogPostgresqlTest.java +++ b/edc-tests/edc-controlplane/catalog-tests/src/test/java/org/eclipse/tractusx/edc/tests/catalog/CatalogPostgresqlTest.java @@ -20,7 +20,7 @@ package org.eclipse.tractusx.edc.tests.catalog; import org.eclipse.edc.junit.annotations.PostgresqlIntegrationTest; -import org.eclipse.tractusx.edc.lifecycle.PgParticipantRuntime; +import org.eclipse.tractusx.edc.tests.runtimes.PgParticipantRuntime; import org.junit.jupiter.api.extension.RegisterExtension; @PostgresqlIntegrationTest diff --git a/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-spi/build.gradle.kts b/edc-tests/edc-controlplane/edr-api-tests/build.gradle.kts similarity index 71% rename from edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-spi/build.gradle.kts rename to edc-tests/edc-controlplane/edr-api-tests/build.gradle.kts index e010535f9..d0de250c2 100644 --- a/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-spi/build.gradle.kts +++ b/edc-tests/edc-controlplane/edr-api-tests/build.gradle.kts @@ -19,9 +19,20 @@ plugins { `java-library` + `java-test-fixtures` } dependencies { - implementation(libs.edc.spi.core) + testImplementation(testFixtures(project(":edc-tests:edc-controlplane:fixtures"))) + + testImplementation(libs.netty.mockserver) + testImplementation(libs.edc.junit) + testImplementation(libs.restAssured) + testImplementation(libs.awaitility) + testImplementation(libs.okhttp.mockwebserver) } +// do not publish +edcBuild { + publish.set(false) +} diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/edr/AbstractNegotiateEdrTest.java b/edc-tests/edc-controlplane/edr-api-tests/src/test/java/org/eclipse/tractusx/edc/tests/edrv2/AbstractNegotiateEdrTest.java similarity index 74% rename from edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/edr/AbstractNegotiateEdrTest.java rename to edc-tests/edc-controlplane/edr-api-tests/src/test/java/org/eclipse/tractusx/edc/tests/edrv2/AbstractNegotiateEdrTest.java index 1756a1f82..824c2f891 100644 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/edr/AbstractNegotiateEdrTest.java +++ b/edc-tests/edc-controlplane/edr-api-tests/src/test/java/org/eclipse/tractusx/edc/tests/edrv2/AbstractNegotiateEdrTest.java @@ -1,5 +1,5 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +/* + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft * * See the NOTICE file(s) distributed with this work for additional * information regarding copyright ownership. @@ -15,9 +15,9 @@ * under the License. * * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ + */ -package org.eclipse.tractusx.edc.tests.edr; +package org.eclipse.tractusx.edc.tests.edrv2; import jakarta.json.Json; import okhttp3.mockwebserver.MockResponse; @@ -32,7 +32,10 @@ import org.eclipse.edc.connector.transfer.spi.event.TransferProcessRequested; import org.eclipse.edc.connector.transfer.spi.event.TransferProcessStarted; import org.eclipse.edc.policy.model.Operator; -import org.eclipse.tractusx.edc.lifecycle.tx.TxParticipant; +import org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration; +import org.eclipse.tractusx.edc.tests.TxParticipant; +import org.eclipse.tractusx.edc.tests.helpers.EdrNegotiationHelperFunctions; +import org.eclipse.tractusx.edc.tests.helpers.PolicyHelperFunctions; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; @@ -46,28 +49,21 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.awaitility.Awaitility.await; -import static org.eclipse.edc.spi.types.domain.edr.EndpointDataReference.EDR_SIMPLE_TYPE; -import static org.eclipse.tractusx.edc.helpers.EdrNegotiationHelperFunctions.createCallback; -import static org.eclipse.tractusx.edc.helpers.EdrNegotiationHelperFunctions.createEvent; -import static org.eclipse.tractusx.edc.helpers.PolicyHelperFunctions.bpnGroupPolicy; -import static org.eclipse.tractusx.edc.lifecycle.TestRuntimeConfiguration.PLATO_BPN; -import static org.eclipse.tractusx.edc.lifecycle.TestRuntimeConfiguration.PLATO_NAME; -import static org.eclipse.tractusx.edc.lifecycle.TestRuntimeConfiguration.SOKRATES_BPN; -import static org.eclipse.tractusx.edc.lifecycle.TestRuntimeConfiguration.SOKRATES_NAME; -import static org.eclipse.tractusx.edc.tests.TestCommon.ASYNC_POLL_INTERVAL; -import static org.eclipse.tractusx.edc.tests.TestCommon.ASYNC_TIMEOUT; -import static org.eclipse.tractusx.edc.tests.edr.TestFunctions.waitForEvent; +import static org.eclipse.tractusx.edc.tests.TxParticipant.ASYNC_POLL_INTERVAL; +import static org.eclipse.tractusx.edc.tests.TxParticipant.ASYNC_TIMEOUT; +import static org.eclipse.tractusx.edc.tests.helpers.EdrNegotiationHelperFunctions.createEvent; +import static org.eclipse.tractusx.edc.tests.helpers.Functions.waitForEvent; public abstract class AbstractNegotiateEdrTest { protected static final TxParticipant SOKRATES = TxParticipant.Builder.newInstance() - .name(SOKRATES_NAME) - .id(SOKRATES_BPN) + .name(TestRuntimeConfiguration.SOKRATES_NAME) + .id(TestRuntimeConfiguration.SOKRATES_BPN) .build(); protected static final TxParticipant PLATO = TxParticipant.Builder.newInstance() - .name(PLATO_NAME) - .id(PLATO_BPN) + .name(TestRuntimeConfiguration.PLATO_NAME) + .id(TestRuntimeConfiguration.PLATO_BPN) .build(); MockWebServer server; @@ -110,15 +106,15 @@ void negotiateEdr_shouldInvokeCallbacks() throws IOException { PLATO.createAsset(assetId, Map.of(), dataAddress); PLATO.storeBusinessPartner(SOKRATES.getBpn(), "test-group1", "test-group2"); - var accessPolicy = PLATO.createPolicyDefinition(bpnGroupPolicy(Operator.IS_NONE_OF, "forbidden-policy")); - var contractPolicy = PLATO.createPolicyDefinition(bpnGroupPolicy(Operator.IS_ALL_OF, "test-group1", "test-group2")); + var accessPolicy = PLATO.createPolicyDefinition(PolicyHelperFunctions.bpnGroupPolicy(Operator.IS_NONE_OF, "forbidden-policy")); + var contractPolicy = PLATO.createPolicyDefinition(PolicyHelperFunctions.bpnGroupPolicy(Operator.IS_ALL_OF, "test-group1", "test-group2")); PLATO.createContractDefinition(assetId, "def-1", accessPolicy, contractPolicy); expectedEvents.forEach(event -> server.enqueue(new MockResponse())); var callbacks = Json.createArrayBuilder() - .add(createCallback(url.toString(), true, Set.of("contract.negotiation", "transfer.process"))) + .add(EdrNegotiationHelperFunctions.createCallback(url.toString(), true, Set.of("contract.negotiation", "transfer.process"))) .build(); var contractNegotiationId = SOKRATES.edrs().negotiateEdr(PLATO, assetId, callbacks); @@ -155,11 +151,10 @@ void negotiateEdr_shouldInvokeCallbacks() throws IOException { var edr = SOKRATES.edrs().getEdr(transferProcessId); - assertThat(edr.getJsonString("type").getString()).isEqualTo(EDR_SIMPLE_TYPE); - assertThat(edr.getJsonString("authCode").getString()).isNotNull(); - assertThat(edr.getJsonString("authKey").getString()).isNotNull(); + assertThat(edr.getJsonString("type").getString()).isEqualTo("https://w3id.org/idsa/v4.1/HTTP"); assertThat(edr.getJsonString("endpoint").getString()).isNotNull(); - assertThat(edr.getJsonString("id").getString()).isEqualTo(transferProcessId); + assertThat(edr.getJsonString("endpointType").getString()).isEqualTo(edr.getJsonString("type").getString()); + assertThat(edr.getJsonString("authorization").getString()).isNotNull(); } diff --git a/edc-tests/edc-controlplane/edr-tests/src/test/java/org/eclipse/tractusx/edc/tests/edrv2/EdrCacheApiEndToEndTest.java b/edc-tests/edc-controlplane/edr-api-tests/src/test/java/org/eclipse/tractusx/edc/tests/edrv2/EdrCacheApiEndToEndTest.java similarity index 97% rename from edc-tests/edc-controlplane/edr-tests/src/test/java/org/eclipse/tractusx/edc/tests/edrv2/EdrCacheApiEndToEndTest.java rename to edc-tests/edc-controlplane/edr-api-tests/src/test/java/org/eclipse/tractusx/edc/tests/edrv2/EdrCacheApiEndToEndTest.java index 11a408fe9..af7f92dbf 100644 --- a/edc-tests/edc-controlplane/edr-tests/src/test/java/org/eclipse/tractusx/edc/tests/edrv2/EdrCacheApiEndToEndTest.java +++ b/edc-tests/edc-controlplane/edr-api-tests/src/test/java/org/eclipse/tractusx/edc/tests/edrv2/EdrCacheApiEndToEndTest.java @@ -37,8 +37,8 @@ import org.eclipse.edc.junit.annotations.EndToEndTest; import org.eclipse.edc.spi.types.domain.DataAddress; import org.eclipse.tractusx.edc.spi.tokenrefresh.dataplane.model.TokenResponse; -import org.eclipse.tractusx.edc.tests.ParticipantRuntime; import org.eclipse.tractusx.edc.tests.TxParticipant; +import org.eclipse.tractusx.edc.tests.runtimes.ParticipantRuntime; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; @@ -77,7 +77,7 @@ public class EdrCacheApiEndToEndTest { .build(); @RegisterExtension protected static final ParticipantRuntime SOKRATES_RUNTIME = new ParticipantRuntime( - ":edc-tests:runtime:runtime-memory-signaling", + ":edc-tests:runtime:runtime-memory", SOKRATES.getName(), SOKRATES.getId(), with(SOKRATES.getConfiguration(), Map.of("edc.iam.issuer.id", "did:web:sokrates"))); @@ -122,7 +122,7 @@ void getEdrWithRefresh_success() { ); storeEdr("test-id", true); - var edr = SOKRATES.edrs().getEdrRequestV2("test-id", true) + var edr = SOKRATES.edrs().getEdrWithRefresh("test-id", true) .statusCode(200) .extract().body().as(JsonObject.class); assertThat(edr).isNotNull(); @@ -146,7 +146,7 @@ void getEdrWithRefresh_notExpired_shouldNotCallEndpoint() { // mock the provider dataplane's refresh endpoint storeEdr("test-id", false); - var edr = SOKRATES.edrs().getEdrRequestV2("test-id", true) + var edr = SOKRATES.edrs().getEdrWithRefresh("test-id", true) .statusCode(200) .extract().body().as(JsonObject.class); assertThat(edr).isNotNull(); @@ -170,7 +170,7 @@ void getEdrWithRefresh_whenNotAutorefresh_shouldNotCallEndpoint() { storeEdr("test-id", true); var edr = SOKRATES.edrs() - .getEdrRequestV2("test-id", false) + .getEdrWithRefresh("test-id", false) .statusCode(200) .extract().body().as(JsonObject.class); assertThat(edr).isNotNull(); @@ -202,7 +202,7 @@ void getEdrWithRefresh_unauthorized() { ); storeEdr("test-id", true); - SOKRATES.edrs().getEdrRequestV2("test-id", true) + SOKRATES.edrs().getEdrWithRefresh("test-id", true) .statusCode(403); // assert the correct endpoint was called diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/edr/NegotiateEdrInMemoryTest.java b/edc-tests/edc-controlplane/edr-api-tests/src/test/java/org/eclipse/tractusx/edc/tests/edrv2/NegotiateEdrInMemoryTest.java similarity index 85% rename from edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/edr/NegotiateEdrInMemoryTest.java rename to edc-tests/edc-controlplane/edr-api-tests/src/test/java/org/eclipse/tractusx/edc/tests/edrv2/NegotiateEdrInMemoryTest.java index 8f7dd70a7..974969b0f 100644 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/edr/NegotiateEdrInMemoryTest.java +++ b/edc-tests/edc-controlplane/edr-api-tests/src/test/java/org/eclipse/tractusx/edc/tests/edrv2/NegotiateEdrInMemoryTest.java @@ -1,5 +1,5 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +/* + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft * * See the NOTICE file(s) distributed with this work for additional * information regarding copyright ownership. @@ -15,15 +15,15 @@ * under the License. * * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ + */ -package org.eclipse.tractusx.edc.tests.edr; +package org.eclipse.tractusx.edc.tests.edrv2; import com.nimbusds.jose.util.Base64; import org.eclipse.edc.junit.annotations.EndToEndTest; import org.eclipse.edc.spi.security.Vault; -import org.eclipse.tractusx.edc.lifecycle.ParticipantRuntime; +import org.eclipse.tractusx.edc.tests.runtimes.ParticipantRuntime; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.extension.RegisterExtension; diff --git a/edc-tests/edc-controlplane/fixtures/build.gradle.kts b/edc-tests/edc-controlplane/fixtures/build.gradle.kts new file mode 100644 index 000000000..f6742a42f --- /dev/null +++ b/edc-tests/edc-controlplane/fixtures/build.gradle.kts @@ -0,0 +1,63 @@ +/******************************************************************************** + * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +plugins { + `java-library` + `java-test-fixtures` +} + +dependencies { + // api modules that the test classes may need + testFixturesApi(project(":spi:edr-spi")) + testFixturesApi(project(":edc-extensions:edr:edr-api-v2")) + testFixturesApi(project(":spi:core-spi")) + testFixturesApi(project(":spi:tokenrefresh-spi")) + + testFixturesApi(libs.edc.spi.core) + testFixturesApi(libs.edc.spi.policy) + testFixturesApi(libs.edc.spi.contract) + testFixturesApi(testFixtures(libs.edc.api.management.test.fixtures)) + testFixturesApi(libs.edc.spi.edrstore) + testFixturesApi(libs.edc.common.crypto) + + // api modules for some test utils + testFixturesApi(libs.netty.mockserver) + testFixturesApi(libs.edc.junit) + testFixturesApi(libs.restAssured) + testFixturesApi(libs.awaitility) + + testFixturesImplementation(libs.edc.identity.trust.sts.embedded) + testFixturesImplementation(libs.edc.core.token) + testFixturesImplementation(libs.edc.spi.identity.did) + testFixturesImplementation(testFixtures(libs.edc.sql.core)) + testFixturesImplementation(libs.okhttp.mockwebserver) + testFixturesImplementation(libs.testcontainers.postgres) + + testCompileOnly(project(":edc-tests:runtime:runtime-memory")) + + testFixturesImplementation(libs.assertj) + testFixturesImplementation(libs.junit.jupiter.api) + testFixturesImplementation(project(":edc-extensions:bpn-validation:bpn-validation-spi")) + +} + +// do not publish +edcBuild { + publish.set(false) +} diff --git a/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/IdentityParticipant.java b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/IdentityParticipant.java new file mode 100644 index 000000000..c396cd47c --- /dev/null +++ b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/IdentityParticipant.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.eclipse.tractusx.edc.tests; + +import com.nimbusds.jose.jwk.JWK; +import org.eclipse.edc.security.token.jwt.CryptoConverter; +import org.eclipse.edc.test.system.utils.Participant; + +import java.security.KeyPair; + +import static org.eclipse.tractusx.edc.tests.helpers.Functions.generateKeyPair; + +public abstract class IdentityParticipant extends Participant { + private final KeyPair keyPair; + private JWK keyPairJwk; + + public IdentityParticipant() { + keyPair = generateKeyPair(); + } + + public KeyPair getKeyPair() { + return keyPair; + } + + public JWK getKeyPairAsJwk() { + if (keyPairJwk == null) { + var jwk = CryptoConverter.createJwk(keyPair).toJSONObject(); + jwk.put("kid", getFullKeyId()); + keyPairJwk = CryptoConverter.create(jwk); + } + return keyPairJwk; + } + + public String getPrivateKeyAsString() { + return CryptoConverter.createJwk(keyPair).toJSONString(); + } + + public String getPublicKeyAsString() { + return CryptoConverter.createJwk(keyPair).toJSONString(); + } + + public String getPrivateKeyAlias() { + return "private." + getFullKeyId(); + } + + public abstract String getFullKeyId(); + + public String getKeyId() { + return "key-1"; + } +} diff --git a/edc-tests/edc-controlplane/edr-tests/src/test/java/org/eclipse/tractusx/edc/tests/MockBpnIdentityService.java b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/MockBpnIdentityService.java similarity index 100% rename from edc-tests/edc-controlplane/edr-tests/src/test/java/org/eclipse/tractusx/edc/tests/MockBpnIdentityService.java rename to edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/MockBpnIdentityService.java diff --git a/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/ParticipantDataApi.java b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/ParticipantDataApi.java new file mode 100644 index 000000000..1d3e4935e --- /dev/null +++ b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/ParticipantDataApi.java @@ -0,0 +1,56 @@ +/******************************************************************************** + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +package org.eclipse.tractusx.edc.tests; + +import jakarta.json.JsonObject; +import org.eclipse.edc.spi.types.domain.edr.EndpointDataReference; + +import java.util.Map; + +import static io.restassured.RestAssured.given; +import static org.assertj.core.api.Assertions.assertThat; + + +/** + * E2E test helper for fetching the data + */ +public class ParticipantDataApi { + + /** + * Pull the data with an {@link EndpointDataReference} + * + * @param edr The edr + * @param queryParams additional params + * @return the data + */ + public String pullData(JsonObject edr, Map queryParams) { + + var endpoint = edr.getString("endpoint"); + var token = edr.getString("authorization"); + var response = given() + .baseUri(endpoint) + .header("Authorization", token) + .queryParams(queryParams) + .when() + .get(); + assertThat(response.statusCode()).isBetween(200, 300); + return response.body().asString(); + } +} diff --git a/edc-tests/edc-controlplane/edr-tests/src/test/java/org/eclipse/tractusx/edc/tests/ParticipantEdrApi.java b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/ParticipantEdrApi.java similarity index 88% rename from edc-tests/edc-controlplane/edr-tests/src/test/java/org/eclipse/tractusx/edc/tests/ParticipantEdrApi.java rename to edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/ParticipantEdrApi.java index 8b9ce4212..48b4f6576 100644 --- a/edc-tests/edc-controlplane/edr-tests/src/test/java/org/eclipse/tractusx/edc/tests/ParticipantEdrApi.java +++ b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/ParticipantEdrApi.java @@ -35,9 +35,9 @@ import static org.eclipse.edc.jsonld.spi.PropertyAndTypeNames.ODRL_ASSIGNER_ATTRIBUTE; import static org.eclipse.edc.jsonld.spi.PropertyAndTypeNames.ODRL_TARGET_ATTRIBUTE; import static org.eclipse.edc.spi.CoreConstants.EDC_NAMESPACE; -import static org.eclipse.tractusx.edc.tests.CatalogHelperFunctions.getDatasetContractId; -import static org.eclipse.tractusx.edc.tests.CatalogHelperFunctions.getDatasetFirstPolicy; -import static org.eclipse.tractusx.edc.tests.EdrNegotiationHelperFunctions.createEdrNegotiationRequest; +import static org.eclipse.tractusx.edc.tests.helpers.CatalogHelperFunctions.getDatasetContractId; +import static org.eclipse.tractusx.edc.tests.helpers.CatalogHelperFunctions.getDatasetFirstPolicy; +import static org.eclipse.tractusx.edc.tests.helpers.EdrNegotiationHelperFunctions.createEdrNegotiationRequest; /** * E2E test helper for the EDR APIs @@ -71,7 +71,7 @@ public JsonObject getEdr(String transferProcessId) { * @return The {@link ValidatableResponse} */ public ValidatableResponse getEdrRequest(String transferProcessId) { - return getEdrRequestV2(transferProcessId, false); + return getEdrWithRefresh(transferProcessId, false); } /** @@ -80,7 +80,7 @@ public ValidatableResponse getEdrRequest(String transferProcessId) { * @param transferProcessId The transfer process id * @return The {@link ValidatableResponse} */ - public ValidatableResponse getEdrRequestV2(String transferProcessId, boolean autoRefresh) { + public ValidatableResponse getEdrWithRefresh(String transferProcessId, boolean autoRefresh) { return baseEdrRequest() .when() .get("/v2/edrs/{id}/dataaddress?auto_refresh={auto_refresh}", transferProcessId, autoRefresh) @@ -124,7 +124,7 @@ public String negotiateEdr(TxParticipant other, String assetId, JsonArray callba var response = baseEdrRequest() .when() .body(requestBody) - .post("/edrs") + .post("/v2/edrs") .then(); var body = response.extract().body().asString(); @@ -140,9 +140,11 @@ public String negotiateEdr(TxParticipant other, String assetId, JsonArray callba * @return The EDRs */ public JsonArray getEdrEntriesByContractNegotiationId(String contractNegotiationId) { + var query = createQuery("contractNegotiationId", "=", contractNegotiationId); return baseEdrRequest() .when() - .get("/edrs?contractNegotiationId={contractNegotiationId}", contractNegotiationId) + .body(query) + .post("/v2/edrs/request") .then() .statusCode(200) .extract() @@ -157,9 +159,11 @@ public JsonArray getEdrEntriesByContractNegotiationId(String contractNegotiation * @return The EDRs */ public JsonArray getEdrEntriesByAgreementId(String agreementId) { + var query = createQuery("agreementId", "=", agreementId); return baseEdrRequest() .when() - .get("/edrs?agreementId={agreementId}", agreementId) + .body(query) + .post("/v2/edrs/request") .then() .statusCode(200) .extract() @@ -174,9 +178,11 @@ public JsonArray getEdrEntriesByAgreementId(String agreementId) { * @return The EDRs */ public JsonArray getEdrEntriesByAssetId(String assetId) { + var query = createQuery("assetId", "=", assetId); return baseEdrRequest() .when() - .get("/edrs?assetId={assetId}", assetId) + .body(query) + .post("/v2/edrs/request") .then() .statusCode(200) .extract() diff --git a/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-spi/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/spi/provider/gateway/authorization/AuthorizationHandlerRegistry.java b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/TestRuntimeConfiguration.java similarity index 64% rename from edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-spi/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/spi/provider/gateway/authorization/AuthorizationHandlerRegistry.java rename to edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/TestRuntimeConfiguration.java index b402430c4..db5f1178f 100644 --- a/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-spi/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/spi/provider/gateway/authorization/AuthorizationHandlerRegistry.java +++ b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/TestRuntimeConfiguration.java @@ -17,24 +17,15 @@ * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ -package org.eclipse.tractusx.edc.dataplane.proxy.spi.provider.gateway.authorization; +package org.eclipse.tractusx.edc.tests; -import org.jetbrains.annotations.Nullable; +public class TestRuntimeConfiguration { -/** - * Manages {@link AuthorizationHandler}s. - */ -public interface AuthorizationHandlerRegistry { - - /** - * Returns a handler for the alias or null if not found. - */ - @Nullable - AuthorizationHandler getHandler(String alias); - - /** - * Registers a handler for the given alias. - */ - void register(String alias, AuthorizationHandler handler); + public static final String BPN_SUFFIX = "-BPN"; + public static final String SOKRATES_NAME = "SOKRATES"; + public static final String SOKRATES_BPN = SOKRATES_NAME + BPN_SUFFIX; + public static final String PLATO_NAME = "PLATO"; + public static final String PLATO_BPN = PLATO_NAME + BPN_SUFFIX; + public static final String DB_SCHEMA_NAME = "testschema"; } diff --git a/edc-tests/edc-controlplane/edr-tests/src/test/java/org/eclipse/tractusx/edc/tests/TxParticipant.java b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/TxParticipant.java similarity index 72% rename from edc-tests/edc-controlplane/edr-tests/src/test/java/org/eclipse/tractusx/edc/tests/TxParticipant.java rename to edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/TxParticipant.java index 7dc118c70..691437380 100644 --- a/edc-tests/edc-controlplane/edr-tests/src/test/java/org/eclipse/tractusx/edc/tests/TxParticipant.java +++ b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/TxParticipant.java @@ -20,20 +20,27 @@ package org.eclipse.tractusx.edc.tests; import com.fasterxml.jackson.annotation.JsonCreator; +import jakarta.json.Json; import org.eclipse.edc.test.system.utils.Participant; +import org.jetbrains.annotations.NotNull; import java.net.URI; import java.time.Duration; +import java.util.Arrays; import java.util.HashMap; import java.util.Map; +import static io.restassured.http.ContentType.JSON; +import static jakarta.json.Json.createObjectBuilder; import static java.time.Duration.ofSeconds; +import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.ID; import static org.eclipse.edc.junit.testfixtures.TestUtils.getFreePort; +import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.TX_NAMESPACE; -public class TxParticipant extends Participant { +public class TxParticipant extends IdentityParticipant { public static final String API_KEY = "testkey"; - private static final Duration ASYNC_TIMEOUT = ofSeconds(60); - private static final Duration ASYNC_POLL_INTERVAL = ofSeconds(1); + public static final Duration ASYNC_TIMEOUT = ofSeconds(60); + public static final Duration ASYNC_POLL_INTERVAL = ofSeconds(1); private final URI controlPlaneDefault = URI.create("http://localhost:" + getFreePort()); private final URI controlPlaneControl = URI.create("http://localhost:" + getFreePort() + "/control"); @@ -42,6 +49,11 @@ public class TxParticipant extends Participant { private final URI dataPlanePublic = URI.create("http://localhost:" + getFreePort() + "/public"); private ParticipantEdrApi edrs; + private ParticipantDataApi data; + + public void createAsset(String id) { + createAsset(id, new HashMap<>(), Map.of("type", "test-type")); + } public String getBpn() { return getId(); @@ -67,8 +79,8 @@ public Map getConfiguration() { put("edc.api.auth.key", "testkey"); put("web.http.public.path", "/api/public"); put("web.http.public.port", String.valueOf(dataPlanePublic.getPort())); - put("edc.transfer.proxy.token.signer.privatekey.alias", "private-key"); - put("edc.transfer.proxy.token.verifier.publickey.alias", "public-key"); + put("edc.transfer.proxy.token.signer.privatekey.alias", getPrivateKeyAlias()); + put("edc.transfer.proxy.token.verifier.publickey.alias", getFullKeyId()); put("edc.transfer.send.retry.limit", "1"); put("edc.transfer.send.retry.base-delay.ms", "100"); put("tx.dpf.consumer.proxy.port", String.valueOf(dataPlaneProxy.getPort())); @@ -76,13 +88,16 @@ public Map getConfiguration() { put("edc.dataplane.selector.httpplane.url", controlPlaneControl.toString()); put("edc.dataplane.selector.httpplane.sourcetypes", "HttpData"); put("edc.dataplane.selector.httpplane.destinationtypes", "HttpProxy"); - put("edc.dataplane.selector.httpplane.properties", "{\"publicApiUrl\":\"http://localhost:" + dataPlanePublic.getPort() + "/api/public\"}"); + put("edc.dataplane.selector.httpplane.transfertypes", "HttpProxy-PULL"); + put("edc.dataplane.selector.httpplane.properties", "{\"publicApiUrl\":\"http://localhost:" + dataPlanePublic.getPort() + "/api/public/v2\"}"); put("edc.receiver.http.dynamic.endpoint", "http://localhost:" + controlPlaneDefault.getPort() + "/api/consumer/datareference"); put("tractusx.businesspartnervalidation.log.agreement.validation", "true"); put("edc.agent.identity.key", "BusinessPartnerNumber"); put("edc.data.encryption.keys.alias", "test-alias"); put("tx.dpf.proxy.gateway.aas.proxied.path", backendProviderProxy.toString()); put("tx.dpf.proxy.gateway.aas.authorization.type", "none"); + put("edc.iam.issuer.id", getDid()); + put("edc.dataplane.api.public.baseurl", "http://localhost:%d/api/public/v2/data".formatted(dataPlanePublic.getPort())); } }; } @@ -91,6 +106,40 @@ public ParticipantEdrApi edrs() { return edrs; } + /** + * Returns the client API for fetching data + */ + public ParticipantDataApi data() { + return data; + } + + /** + * Stores BPN groups + */ + public void storeBusinessPartner(String bpn, String... groups) { + var body = createObjectBuilder() + .add(ID, bpn) + .add(TX_NAMESPACE + "groups", Json.createArrayBuilder(Arrays.asList(groups))) + .build(); + managementEndpoint.baseRequest() + .contentType(JSON) + .body(body) + .when() + .post("/business-partner-groups") + .then() + .statusCode(204); + } + + @Override + public String getFullKeyId() { + return getDid() + "#" + getKeyId(); + } + + @NotNull + private String getDid() { + return "did:web:" + name.toLowerCase(); + } + public static final class Builder extends Participant.Builder { private Builder() { @@ -110,6 +159,7 @@ public TxParticipant build() { super.build(); this.participant.edrs = new ParticipantEdrApi(participant); + this.participant.data = new ParticipantDataApi(); return participant; } } diff --git a/edc-tests/edc-controlplane/edr-tests/src/test/java/org/eclipse/tractusx/edc/tests/CatalogHelperFunctions.java b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/helpers/CatalogHelperFunctions.java similarity index 91% rename from edc-tests/edc-controlplane/edr-tests/src/test/java/org/eclipse/tractusx/edc/tests/CatalogHelperFunctions.java rename to edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/helpers/CatalogHelperFunctions.java index 45563f1a0..e52880858 100644 --- a/edc-tests/edc-controlplane/edr-tests/src/test/java/org/eclipse/tractusx/edc/tests/CatalogHelperFunctions.java +++ b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/helpers/CatalogHelperFunctions.java @@ -1,5 +1,5 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +/* + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft * * See the NOTICE file(s) distributed with this work for additional * information regarding copyright ownership. @@ -15,9 +15,9 @@ * under the License. * * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ + */ -package org.eclipse.tractusx.edc.tests; +package org.eclipse.tractusx.edc.tests.helpers; import jakarta.json.Json; import jakarta.json.JsonArray; diff --git a/edc-tests/edc-controlplane/edr-tests/src/test/java/org/eclipse/tractusx/edc/tests/EdrNegotiationHelperFunctions.java b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/helpers/EdrNegotiationHelperFunctions.java similarity index 83% rename from edc-tests/edc-controlplane/edr-tests/src/test/java/org/eclipse/tractusx/edc/tests/EdrNegotiationHelperFunctions.java rename to edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/helpers/EdrNegotiationHelperFunctions.java index 642584ae9..34fe19c6f 100644 --- a/edc-tests/edc-controlplane/edr-tests/src/test/java/org/eclipse/tractusx/edc/tests/EdrNegotiationHelperFunctions.java +++ b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/helpers/EdrNegotiationHelperFunctions.java @@ -1,5 +1,5 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +/* + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft * * See the NOTICE file(s) distributed with this work for additional * information regarding copyright ownership. @@ -15,9 +15,9 @@ * under the License. * * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ + */ -package org.eclipse.tractusx.edc.tests; +package org.eclipse.tractusx.edc.tests.helpers; import jakarta.json.Json; import jakarta.json.JsonArray; @@ -25,18 +25,18 @@ import jakarta.json.JsonObject; import org.eclipse.edc.jsonld.TitaniumJsonLd; import org.eclipse.edc.jsonld.spi.JsonLd; -import org.eclipse.edc.spi.monitor.Monitor; -import org.eclipse.tractusx.edc.api.edr.dto.NegotiateEdrRequestDto; +import org.eclipse.edc.spi.event.Event; +import org.eclipse.edc.spi.monitor.ConsoleMonitor; +import org.eclipse.tractusx.edc.api.edr.v2.dto.NegotiateEdrRequestDto; import java.util.Set; import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.TYPE; import static org.eclipse.edc.spi.CoreConstants.EDC_NAMESPACE; -import static org.mockito.Mockito.mock; public class EdrNegotiationHelperFunctions { - private static final JsonLd JSON_LD = new TitaniumJsonLd(mock(Monitor.class)); + private static final JsonLd JSON_LD = new TitaniumJsonLd(new ConsoleMonitor()); public static JsonObject createEdrNegotiationRequest(String connectorAddress, String providerId, String offerId, String assetId, JsonObject policy, JsonArray callbacks) { return Json.createObjectBuilder() @@ -65,4 +65,9 @@ public static JsonObject createCallback(String url, boolean transactional, Set ReceivedEvent createEvent(Class klass) { + return ReceivedEvent.Builder.newInstance().type(klass.getSimpleName()).build(); + } } diff --git a/edc-tests/edc-controlplane/edr-tests/src/test/java/org/eclipse/tractusx/edc/tests/Functions.java b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/helpers/Functions.java similarity index 67% rename from edc-tests/edc-controlplane/edr-tests/src/test/java/org/eclipse/tractusx/edc/tests/Functions.java rename to edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/helpers/Functions.java index 1e20076d2..11b7b0409 100644 --- a/edc-tests/edc-controlplane/edr-tests/src/test/java/org/eclipse/tractusx/edc/tests/Functions.java +++ b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/helpers/Functions.java @@ -17,40 +17,36 @@ * SPDX-License-Identifier: Apache-2.0 */ -package org.eclipse.tractusx.edc.tests; +package org.eclipse.tractusx.edc.tests.helpers; +import com.fasterxml.jackson.databind.ObjectMapper; +import okhttp3.mockwebserver.MockWebServer; import org.bouncycastle.jce.provider.BouncyCastleProvider; -import org.bouncycastle.openssl.jcajce.JcaPEMWriter; -import org.eclipse.edc.spi.EdcException; -import java.io.IOException; -import java.io.StringWriter; import java.security.InvalidAlgorithmParameterException; -import java.security.Key; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.NoSuchAlgorithmException; import java.security.spec.ECGenParameterSpec; +import java.util.concurrent.TimeUnit; public class Functions { - /** - * Returns the Pem representation of a {@link Key} - * - * @param key The input key - * @return The pem encoded key - */ - public static String toPemEncoded(Key key) { - var writer = new StringWriter(); - try (var jcaPEMWriter = new JcaPEMWriter(writer)) { - jcaPEMWriter.writeObject(key); - } catch (IOException e) { - throw new EdcException("Unable to convert private in PEM format ", e); + private static final ObjectMapper MAPPER = new ObjectMapper(); + + public static ReceivedEvent waitForEvent(MockWebServer server) { + try { + var request = server.takeRequest(60, TimeUnit.SECONDS); + if (request != null) { + return MAPPER.readValue(request.getBody().inputStream(), ReceivedEvent.class); + } else { + throw new RuntimeException("Timeout exceeded waiting for events"); + } + } catch (Exception e) { + throw new RuntimeException(e); } - return writer.toString(); } - public static KeyPair generateKeyPair() { try { KeyPairGenerator gen = KeyPairGenerator.getInstance("EC", new BouncyCastleProvider()); diff --git a/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/helpers/PolicyHelperFunctions.java b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/helpers/PolicyHelperFunctions.java new file mode 100644 index 000000000..d545b4f86 --- /dev/null +++ b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/helpers/PolicyHelperFunctions.java @@ -0,0 +1,205 @@ +/******************************************************************************** + * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +package org.eclipse.tractusx.edc.tests.helpers; + + +import com.fasterxml.jackson.databind.ObjectMapper; +import jakarta.json.Json; +import jakarta.json.JsonArrayBuilder; +import jakarta.json.JsonObject; +import jakarta.json.JsonObjectBuilder; +import org.eclipse.edc.connector.policy.spi.PolicyDefinition; +import org.eclipse.edc.jsonld.util.JacksonJsonLd; +import org.eclipse.edc.policy.model.AtomicConstraint; +import org.eclipse.edc.policy.model.Operator; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.Arrays; +import java.util.Collection; +import java.util.Map; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.CONTEXT; +import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.ID; +import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.TYPE; +import static org.eclipse.edc.jsonld.spi.PropertyAndTypeNames.ODRL_CONSTRAINT_TYPE; +import static org.eclipse.edc.jsonld.spi.PropertyAndTypeNames.ODRL_LOGICAL_CONSTRAINT_TYPE; +import static org.eclipse.edc.spi.CoreConstants.EDC_NAMESPACE; + +public class PolicyHelperFunctions { + + public static final String TX_NAMESPACE = "https://w3id.org/tractusx/v0.0.1/ns/"; + private static final String ODRL_JSONLD = "http://www.w3.org/ns/odrl.jsonld"; + private static final String BUSINESS_PARTNER_EVALUATION_KEY = "BusinessPartnerNumber"; + + public static final String BUSINESS_PARTNER_LEGACY_EVALUATION_KEY = TX_NAMESPACE + BUSINESS_PARTNER_EVALUATION_KEY; + + private static final String BUSINESS_PARTNER_CONSTRAINT_KEY = TX_NAMESPACE + "BusinessPartnerGroup"; + + private static final ObjectMapper MAPPER = JacksonJsonLd.createObjectMapper(); + + public static JsonObject bpnGroupPolicy(Operator operator, String... allowedGroups) { + return bpnGroupPolicy(operator.getOdrlRepresentation(), allowedGroups); + } + + /** + * Creates a {@link PolicyDefinition} using the given ID, that contains equality constraints for each of the given BusinessPartnerNumbers: + * each BPN is converted into an {@link AtomicConstraint} {@code BusinessPartnerNumber EQ [BPN]}. + */ + public static JsonObject frameworkPolicy(String id, Map permissions) { + return policyDefinitionBuilder(frameworkPolicy(permissions)) + .add(ID, id) + .build(); + } + + public static JsonObject frameworkPolicy(Map permissions) { + return Json.createObjectBuilder() + .add(CONTEXT, ODRL_JSONLD) + .add(TYPE, "Set") + .add("permission", Json.createArrayBuilder() + .add(frameworkPermission(permissions))) + .build(); + } + + public static JsonObject frameworkPolicy(String leftOperand, Operator operator, Object rightOperand) { + var constraint = atomicConstraint(leftOperand, operator.getOdrlRepresentation(), rightOperand); + + var permission = Json.createObjectBuilder() + .add("action", "use") + .add("constraint", Json.createObjectBuilder() + .add(TYPE, ODRL_LOGICAL_CONSTRAINT_TYPE) + .add("or", constraint) + .build()) + .build(); + + return Json.createObjectBuilder() + .add(CONTEXT, ODRL_JSONLD) + .add(TYPE, "Set") + .add("permission", Json.createArrayBuilder().add(permission)) + .build(); + } + + /** + * Creates a {@link PolicyDefinition} using the given ID, that contains equality constraints for each of the given BusinessPartnerNumbers: + * each BPN is converted into an {@link AtomicConstraint} {@code BusinessPartnerNumber EQ [BPN]}. + */ + public static JsonObject frameworkTemplatePolicy(String id, String frameworkKind) { + var template = fetchFrameworkTemplate().replace("${POLICY_ID}", id).replace("${FRAMEWORK_CREDENTIAL}", frameworkKind); + try { + return MAPPER.readValue(template, JsonObject.class); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public static JsonObjectBuilder policyDefinitionBuilder() { + return Json.createObjectBuilder() + .add(TYPE, EDC_NAMESPACE + "PolicyDefinitionDto"); + } + + public static JsonObjectBuilder policyDefinitionBuilder(JsonObject policy) { + return policyDefinitionBuilder() + .add(EDC_NAMESPACE + "policy", policy); + } + + public static JsonObject bnpPolicy(String... bnps) { + return Json.createObjectBuilder() + .add(CONTEXT, ODRL_JSONLD) + .add(TYPE, "Set") + .add("permission", Json.createArrayBuilder() + .add(permission(bnps))) + .build(); + } + + + private static JsonObject bpnGroupPolicy(String operator, String... allowedGroups) { + + var groupConstraint = atomicConstraint(BUSINESS_PARTNER_CONSTRAINT_KEY, operator, Arrays.asList(allowedGroups)); + + var permission = Json.createObjectBuilder() + .add("action", "use") + .add("constraint", Json.createObjectBuilder() + .add(TYPE, ODRL_LOGICAL_CONSTRAINT_TYPE) + .add("or", groupConstraint) + .build()) + .build(); + + return Json.createObjectBuilder() + .add(CONTEXT, ODRL_JSONLD) + .add(TYPE, "Set") + .add("permission", permission) + .build(); + } + + private static String fetchFrameworkTemplate() { + try (var stream = PolicyHelperFunctions.class.getClassLoader().getResourceAsStream("framework-policy.json")) { + return new String(stream.readAllBytes(), StandardCharsets.UTF_8); + } catch (IOException e) { + throw new RuntimeException(e); + } + + } + + private static JsonObject permission(String... bpns) { + + var bpnConstraints = Stream.of(bpns) + .map(bpn -> atomicConstraint(TX_NAMESPACE + BUSINESS_PARTNER_EVALUATION_KEY, "eq", bpn)) + .collect(Json::createArrayBuilder, JsonArrayBuilder::add, JsonArrayBuilder::add); + + return Json.createObjectBuilder() + .add("action", "use") + .add("constraint", Json.createObjectBuilder() + .add(TYPE, ODRL_LOGICAL_CONSTRAINT_TYPE) + .add("or", bpnConstraints) + .build()) + .build(); + } + + private static JsonObject frameworkPermission(Map permissions) { + + var constraints = permissions.entrySet().stream() + .map(permission -> atomicConstraint(permission.getKey(), "eq", permission.getValue())) + .collect(Json::createArrayBuilder, JsonArrayBuilder::add, JsonArrayBuilder::add); + + return Json.createObjectBuilder() + .add("action", "use") + .add("constraint", Json.createObjectBuilder() + .add(TYPE, ODRL_LOGICAL_CONSTRAINT_TYPE) + .add("or", constraints) + .build()) + .build(); + } + + private static JsonObject atomicConstraint(String leftOperand, String operator, Object rightOperand) { + var builder = Json.createObjectBuilder() + .add(TYPE, ODRL_CONSTRAINT_TYPE) + .add("leftOperand", leftOperand) + .add("operator", operator); + + if (rightOperand instanceof Collection coll) { + builder.add("rightOperand", coll.stream().map(Object::toString).collect(Collectors.joining(","))); + } else { + builder.add("rightOperand", rightOperand.toString()); + } + return builder.build(); + } +} diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/helpers/QueryHelperFunctions.java b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/helpers/QueryHelperFunctions.java similarity index 97% rename from edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/helpers/QueryHelperFunctions.java rename to edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/helpers/QueryHelperFunctions.java index 3c7ab0347..f55667839 100644 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/helpers/QueryHelperFunctions.java +++ b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/helpers/QueryHelperFunctions.java @@ -17,7 +17,7 @@ * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ -package org.eclipse.tractusx.edc.helpers; +package org.eclipse.tractusx.edc.tests.helpers; import jakarta.json.Json; import jakarta.json.JsonObject; diff --git a/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-core/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/core/gateway/configuration/GatewayConfigurationRegistryImpl.java b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/helpers/ReceivedEvent.java similarity index 52% rename from edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-core/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/core/gateway/configuration/GatewayConfigurationRegistryImpl.java rename to edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/helpers/ReceivedEvent.java index c7584107a..4cf374222 100644 --- a/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-core/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/core/gateway/configuration/GatewayConfigurationRegistryImpl.java +++ b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/helpers/ReceivedEvent.java @@ -17,28 +17,45 @@ * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ -package org.eclipse.tractusx.edc.dataplane.proxy.provider.core.gateway.configuration; +package org.eclipse.tractusx.edc.tests.helpers; -import org.eclipse.tractusx.edc.dataplane.proxy.spi.provider.gateway.configuration.GatewayConfiguration; -import org.eclipse.tractusx.edc.dataplane.proxy.spi.provider.gateway.configuration.GatewayConfigurationRegistry; -import org.jetbrains.annotations.Nullable; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import java.util.HashMap; -import java.util.Map; -/** - * Default implementation. - */ -public class GatewayConfigurationRegistryImpl implements GatewayConfigurationRegistry { - private final Map configurations = new HashMap<>(); +@JsonIgnoreProperties(ignoreUnknown = true) +public class ReceivedEvent { + private String type; - @Override - public @Nullable GatewayConfiguration getConfiguration(String alias) { - return configurations.get(alias); + public String getType() { + return type; } @Override - public void register(GatewayConfiguration configuration) { - configurations.put(configuration.getAlias(), configuration); + public String toString() { + return "ReceivedEvent{" + + "type='" + type + '\'' + + '}'; + } + + public static class Builder { + private final ReceivedEvent event; + + private Builder(ReceivedEvent event) { + this.event = event; + } + + public static Builder newInstance() { + return new Builder(new ReceivedEvent()); + } + + public Builder type(String type) { + this.event.type = type; + return this; + } + + public ReceivedEvent build() { + return event; + } } } + diff --git a/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/runtimes/DataWiper.java b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/runtimes/DataWiper.java new file mode 100644 index 000000000..c97acd08f --- /dev/null +++ b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/runtimes/DataWiper.java @@ -0,0 +1,84 @@ +/******************************************************************************** + * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +package org.eclipse.tractusx.edc.tests.runtimes; + +import org.eclipse.edc.connector.contract.spi.offer.store.ContractDefinitionStore; +import org.eclipse.edc.connector.policy.spi.store.PolicyDefinitionStore; +import org.eclipse.edc.spi.asset.AssetIndex; +import org.eclipse.edc.spi.query.QuerySpec; +import org.eclipse.edc.spi.system.ServiceExtensionContext; +import org.eclipse.tractusx.edc.edr.spi.store.EndpointDataReferenceCache; +import org.eclipse.tractusx.edc.validation.businesspartner.spi.BusinessPartnerStore; + +import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.PLATO_BPN; +import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.SOKRATES_BPN; + +/** + * Helper class to delete all objects from a runtime's data stores. + */ +public class DataWiper { + + private final ServiceExtensionContext context; + + public DataWiper(ServiceExtensionContext context) { + this.context = context; + } + + public void clearPersistence() { + clearAssetIndex(); + clearPolicies(); + clearContractDefinitions(); + clearEdrCache(); + clearBusinessPartnerStore(); + } + + public void clearBusinessPartnerStore() { + var bps = context.getService(BusinessPartnerStore.class); + bps.delete(SOKRATES_BPN); + bps.delete(PLATO_BPN); + } + + public void clearContractDefinitions() { + var cds = context.getService(ContractDefinitionStore.class); + cds.findAll(QuerySpec.max()).forEach(cd -> cds.deleteById(cd.getId())); + } + + public void clearPolicies() { + var ps = context.getService(PolicyDefinitionStore.class); + // must .collect() here, otherwise we'll get a ConcurrentModificationException + ps.findAll(QuerySpec.max()).toList().forEach(p -> ps.delete(p.getId())); + } + + public void clearAssetIndex() { + var index = context.getService(AssetIndex.class); + index.queryAssets(QuerySpec.max()).forEach(asset -> index.deleteById(asset.getId())); + } + + public void clearEdrCache() { + var edrCache = context.getService(EndpointDataReferenceCache.class); + edrCache.queryForEntries(QuerySpec.max()).forEach(entry -> { + try { + edrCache.deleteByTransferProcessId(entry.getTransferProcessId()); + } catch (Exception e) { + context.getMonitor().warning("Failed to clean up the cache", e); + } + }); + } +} diff --git a/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/runtimes/KeyPool.java b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/runtimes/KeyPool.java new file mode 100644 index 000000000..184c3314a --- /dev/null +++ b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/runtimes/KeyPool.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.eclipse.tractusx.edc.tests.runtimes; + +import java.security.KeyPair; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +public class KeyPool { + private static final Map KEYS = new ConcurrentHashMap<>(); + + public static void register(String keyId, KeyPair keypair) { + KEYS.put(keyId, keypair); + } + + public static KeyPair forId(String keyId) { + return KEYS.get(keyId); + } +} diff --git a/edc-tests/edc-controlplane/edr-tests/src/test/java/org/eclipse/tractusx/edc/tests/ParticipantRuntime.java b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/runtimes/ParticipantRuntime.java similarity index 74% rename from edc-tests/edc-controlplane/edr-tests/src/test/java/org/eclipse/tractusx/edc/tests/ParticipantRuntime.java rename to edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/runtimes/ParticipantRuntime.java index 7c4a56628..653524236 100644 --- a/edc-tests/edc-controlplane/edr-tests/src/test/java/org/eclipse/tractusx/edc/tests/ParticipantRuntime.java +++ b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/runtimes/ParticipantRuntime.java @@ -1,5 +1,5 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +/* + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft * * See the NOTICE file(s) distributed with this work for additional * information regarding copyright ownership. @@ -15,24 +15,28 @@ * under the License. * * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ + */ -package org.eclipse.tractusx.edc.tests; +package org.eclipse.tractusx.edc.tests.runtimes; import com.nimbusds.jose.JOSEException; import com.nimbusds.jose.jwk.Curve; +import com.nimbusds.jose.jwk.ECKey; import com.nimbusds.jose.jwk.gen.ECKeyGenerator; +import org.eclipse.edc.iam.did.spi.resolution.DidPublicKeyResolver; import org.eclipse.edc.iam.identitytrust.sts.embedded.EmbeddedSecureTokenService; import org.eclipse.edc.identitytrust.SecureTokenService; import org.eclipse.edc.junit.extensions.EdcRuntimeExtension; import org.eclipse.edc.spi.iam.AudienceResolver; import org.eclipse.edc.spi.iam.IdentityService; +import org.eclipse.edc.spi.result.Result; import org.eclipse.edc.spi.security.Vault; import org.eclipse.edc.spi.system.ServiceExtension; import org.eclipse.edc.spi.system.ServiceExtensionContext; import org.eclipse.edc.spi.system.injection.InjectionContainer; import org.eclipse.edc.spi.types.domain.message.RemoteMessage; import org.eclipse.edc.token.JwtGenerationService; +import org.eclipse.tractusx.edc.tests.MockBpnIdentityService; import org.junit.jupiter.api.extension.AfterAllCallback; import org.junit.jupiter.api.extension.BeforeAllCallback; import org.junit.jupiter.api.extension.ExtensionContext; @@ -42,26 +46,28 @@ import java.util.List; import java.util.Map; -import static org.eclipse.tractusx.edc.tests.Functions.generateKeyPair; -import static org.eclipse.tractusx.edc.tests.Functions.toPemEncoded; - public class ParticipantRuntime extends EdcRuntimeExtension implements BeforeAllCallback, AfterAllCallback { - private final Map properties; + private final ECKey runtimeKeyPair; + private DataWiper wiper; public ParticipantRuntime(String moduleName, String runtimeName, String bpn, Map properties) { super(moduleName, runtimeName, properties); this.properties = properties; - this.registerServiceMock(IdentityService.class, new MockBpnIdentityService(bpn)); - this.registerServiceMock(AudienceResolver.class, RemoteMessage::getCounterPartyAddress); + if (!properties.containsKey("tx.ssi.miw.url")) { + this.registerServiceMock(IdentityService.class, new MockBpnIdentityService(bpn)); + this.registerServiceMock(AudienceResolver.class, RemoteMessage::getCounterPartyAddress); + } var kid = properties.get("edc.iam.issuer.id") + "#key-1"; try { - var runtimeKeyPair = new ECKeyGenerator(Curve.P_256).keyID(kid).generate(); + runtimeKeyPair = new ECKeyGenerator(Curve.P_256).keyID(kid).generate(); + KeyPool.register(kid, runtimeKeyPair.toKeyPair()); var privateKey = runtimeKeyPair.toPrivateKey(); registerServiceMock(SecureTokenService.class, new EmbeddedSecureTokenService(new JwtGenerationService(), () -> privateKey, () -> kid, Clock.systemUTC(), Duration.ofMinutes(10).toMillis())); + registerServiceMock(DidPublicKeyResolver.class, keyId -> Result.success(KeyPool.forId(keyId).getPublic())); } catch (JOSEException e) { throw new RuntimeException(e); } @@ -70,6 +76,7 @@ public ParticipantRuntime(String moduleName, String runtimeName, String bpn, Map @Override public void beforeTestExecution(ExtensionContext extensionContext) { //do nothing - we only want to start the runtime once + wiper.clearPersistence(); } @Override @@ -90,18 +97,18 @@ public void afterAll(ExtensionContext context) throws Exception { @Override protected void bootExtensions(ServiceExtensionContext context, List> serviceExtensions) { super.bootExtensions(context, serviceExtensions); - registerConsumerPullKeys(properties); + wiper = new DataWiper(context); + registerConsumerPullKeys(runtimeKeyPair); } - private void registerConsumerPullKeys(Map properties) { + private void registerConsumerPullKeys(ECKey ecKey) { var privateAlias = properties.get("edc.transfer.proxy.token.signer.privatekey.alias"); var publicAlias = properties.get("edc.transfer.proxy.token.verifier.publickey.alias"); if (privateAlias != null && publicAlias != null) { - var keyPair = generateKeyPair(); var vault = getContext().getService(Vault.class); - vault.storeSecret(privateAlias, toPemEncoded(keyPair.getPrivate())); - vault.storeSecret(publicAlias, toPemEncoded(keyPair.getPublic())); + vault.storeSecret(privateAlias, ecKey.toJSONString()); + vault.storeSecret(publicAlias, ecKey.toPublicJWK().toJSONString()); } } diff --git a/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/runtimes/PgParticipantRuntime.java b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/runtimes/PgParticipantRuntime.java new file mode 100644 index 000000000..5088e942c --- /dev/null +++ b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/runtimes/PgParticipantRuntime.java @@ -0,0 +1,130 @@ +/******************************************************************************** + * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +package org.eclipse.tractusx.edc.tests.runtimes; + +import org.eclipse.edc.connector.core.vault.InMemoryVault; +import org.eclipse.edc.spi.monitor.ConsoleMonitor; +import org.eclipse.edc.spi.monitor.Monitor; +import org.eclipse.edc.spi.result.Result; +import org.eclipse.edc.spi.security.Vault; +import org.eclipse.edc.spi.system.ServiceExtension; +import org.eclipse.edc.spi.system.ServiceExtensionContext; +import org.eclipse.edc.spi.system.injection.InjectionContainer; +import org.eclipse.edc.sql.testfixtures.PostgresqlLocalInstance; +import org.junit.jupiter.api.extension.AfterAllCallback; +import org.junit.jupiter.api.extension.BeforeAllCallback; +import org.junit.jupiter.api.extension.ExtensionContext; +import org.testcontainers.containers.PostgreSQLContainer; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Stream; + +import static java.lang.String.format; +import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.DB_SCHEMA_NAME; + +public class PgParticipantRuntime extends ParticipantRuntime implements AfterAllCallback, BeforeAllCallback { + + private static final String POSTGRES_IMAGE_NAME = "postgres:14.2"; + private static final String USER = "postgres"; + private static final String PASSWORD = "password"; + private final String dbName; + public PostgreSQLContainer postgreSqlContainer; + + public PgParticipantRuntime(String moduleName, String runtimeName, String bpn, Map properties) { + super(moduleName, runtimeName, bpn, properties); + this.dbName = runtimeName.toLowerCase(); + mockVault(); + + postgreSqlContainer = new PostgreSQLContainer<>(POSTGRES_IMAGE_NAME) + .withLabel("runtime", dbName) + .withExposedPorts(5432) + .withUsername(USER) + .withPassword(PASSWORD) + .withDatabaseName(dbName); + } + + @Override + public void beforeAll(ExtensionContext context) throws Exception { + postgreSqlContainer.start(); + var config = postgresqlConfiguration(dbName); + config.forEach(System::setProperty); + super.beforeAll(context); + } + + @Override + public void afterAll(ExtensionContext context) throws Exception { + super.afterAll(context); + postgreSqlContainer.stop(); + postgreSqlContainer.close(); + } + + public Map postgresqlConfiguration(String name) { + var jdbcUrl = jdbcUrl(name); + return new HashMap<>() { + { + Stream.of("asset", "contractdefinition", "contractnegotiation", "policy", "transferprocess", "edr", "bpn", "policy-monitor") + .forEach(context -> { + var group = "edc.datasource." + context; + put(group + ".name", context); + put(group + ".url", jdbcUrl); + put(group + ".user", USER); + put(group + ".password", PASSWORD); + }); + // use non-default schema name to test usage of non-default schema + put("org.eclipse.tractusx.edc.postgresql.migration.schema", DB_SCHEMA_NAME); + } + }; + } + + public String jdbcUrl(String name) { + return baseJdbcUrl() + name + "?currentSchema=" + DB_SCHEMA_NAME; + } + + public String baseJdbcUrl() { + return format("jdbc:postgresql://%s:%s/", postgreSqlContainer.getHost(), postgreSqlContainer.getFirstMappedPort()); + } + + @Override + protected void bootExtensions(ServiceExtensionContext context, List> serviceExtensions) { + PostgresqlLocalInstance helper = new PostgresqlLocalInstance(postgreSqlContainer.getUsername(), postgreSqlContainer.getPassword(), baseJdbcUrl(), postgreSqlContainer.getDatabaseName()); + helper.createDatabase(); + super.bootExtensions(context, serviceExtensions); + } + + protected void mockVault() { + this.registerServiceMock(Vault.class, new InMemoryVaultOverride(new ConsoleMonitor())); + } + + private static class InMemoryVaultOverride extends InMemoryVault { + + InMemoryVaultOverride(Monitor monitor) { + super(monitor); + } + + @Override + public Result deleteSecret(String s) { + super.deleteSecret(s); + return Result.success(); + } + } + +} diff --git a/edc-tests/edc-controlplane/edr-tests/build.gradle.kts b/edc-tests/edc-controlplane/iatp-tests/build.gradle.kts similarity index 65% rename from edc-tests/edc-controlplane/edr-tests/build.gradle.kts rename to edc-tests/edc-controlplane/iatp-tests/build.gradle.kts index 1f8de78d9..d2bbaad5a 100644 --- a/edc-tests/edc-controlplane/edr-tests/build.gradle.kts +++ b/edc-tests/edc-controlplane/iatp-tests/build.gradle.kts @@ -23,26 +23,21 @@ plugins { } dependencies { - testImplementation(project(":spi:edr-spi")) - testImplementation(project(":edc-extensions:edr:edr-api")) - testImplementation(project(":spi:core-spi")) - testImplementation(project(":spi:tokenrefresh-spi")) - - testImplementation(testFixtures(libs.edc.api.management.test.fixtures)) - testImplementation(libs.edc.spi.edrstore) + testImplementation(testFixtures(project(":edc-tests:edc-controlplane:fixtures"))) testImplementation(libs.edc.identity.trust.sts.embedded) - testImplementation(libs.netty.mockserver) - testImplementation(libs.edc.core.token) + testImplementation(libs.edc.ih.did) + testImplementation(libs.edc.ih.spi) + testImplementation(libs.edc.ih.spi.store) testImplementation(libs.edc.junit) + testImplementation(libs.edc.core.token) + testImplementation(libs.edc.identity.vc.ldp) + testImplementation(libs.edc.identity.jws2020) + // 3rd party libs + testImplementation(libs.netty.mockserver) testImplementation(libs.restAssured) - - testCompileOnly(project(":edc-tests:runtime:runtime-memory")) - - testFixturesImplementation(libs.junit.jupiter.api) - testFixturesImplementation(libs.edc.spi.core) - testFixturesImplementation(libs.edc.junit) - testFixturesImplementation(libs.edc.spi.policy) - testFixturesImplementation(libs.edc.spi.contract) + testImplementation(libs.awaitility) + testImplementation(libs.okhttp.mockwebserver) + testImplementation(libs.bouncyCastle.bcpkixJdk18on) } // do not publish diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/AbstractHttpConsumerPullWithProxyTest.java b/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/AbstractHttpConsumerPullWithProxyTest.java similarity index 77% rename from edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/AbstractHttpConsumerPullWithProxyTest.java rename to edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/AbstractHttpConsumerPullWithProxyTest.java index 27043b3ea..d6e53441d 100644 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/AbstractHttpConsumerPullWithProxyTest.java +++ b/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/AbstractHttpConsumerPullWithProxyTest.java @@ -24,8 +24,7 @@ import okhttp3.mockwebserver.MockResponse; import okhttp3.mockwebserver.MockWebServer; import org.eclipse.edc.connector.transfer.spi.types.TransferProcessStates; -import org.eclipse.edc.spi.types.domain.edr.EndpointDataReference; -import org.eclipse.tractusx.edc.lifecycle.tx.TxParticipant; +import org.eclipse.tractusx.edc.tests.TxParticipant; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -37,13 +36,14 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.awaitility.Awaitility.await; import static org.awaitility.pollinterval.FibonacciPollInterval.fibonacci; -import static org.eclipse.tractusx.edc.helpers.PolicyHelperFunctions.bnpPolicy; -import static org.eclipse.tractusx.edc.helpers.TransferProcessHelperFunctions.createProxyRequest; -import static org.eclipse.tractusx.edc.lifecycle.TestRuntimeConfiguration.PLATO_BPN; -import static org.eclipse.tractusx.edc.lifecycle.TestRuntimeConfiguration.PLATO_NAME; -import static org.eclipse.tractusx.edc.lifecycle.TestRuntimeConfiguration.SOKRATES_BPN; -import static org.eclipse.tractusx.edc.lifecycle.TestRuntimeConfiguration.SOKRATES_NAME; -import static org.eclipse.tractusx.edc.tests.TestCommon.ASYNC_TIMEOUT; +import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.TYPE; +import static org.eclipse.edc.spi.CoreConstants.EDC_NAMESPACE; +import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.PLATO_BPN; +import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.PLATO_NAME; +import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.SOKRATES_BPN; +import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.SOKRATES_NAME; +import static org.eclipse.tractusx.edc.tests.TxParticipant.ASYNC_TIMEOUT; +import static org.eclipse.tractusx.edc.tests.helpers.PolicyHelperFunctions.bnpPolicy; public abstract class AbstractHttpConsumerPullWithProxyTest { @@ -59,6 +59,14 @@ public abstract class AbstractHttpConsumerPullWithProxyTest { protected MockWebServer server; + public static JsonObject createProxyRequest() { + return Json.createObjectBuilder() + .add(TYPE, EDC_NAMESPACE + "DataAddress") + .add(EDC_NAMESPACE + "type", "HttpProxy-PULL") + .build(); + + } + @BeforeEach void setup() throws IOException { server = new MockWebServer(); @@ -70,15 +78,11 @@ void transferData_privateBackend() throws IOException, InterruptedException { var url = server.url("/mock/api"); server.start(); - var authCodeHeaderName = "test-authkey"; - var authCode = "test-authcode"; Map dataAddress = Map.of( "baseUrl", url.toString(), "type", "HttpData", - "contentType", "application/json", - "authKey", authCodeHeaderName, - "authCode", authCode + "contentType", "application/json" ); PLATO.createAsset(assetId, Map.of(), dataAddress); @@ -89,7 +93,7 @@ void transferData_privateBackend() throws IOException, InterruptedException { var transferProcessId = SOKRATES.requestAsset(PLATO, assetId, Json.createObjectBuilder().build(), createProxyRequest()); var contractAgreementId = new AtomicReference(); - var edr = new AtomicReference(); + var edr = new AtomicReference(); // wait until transfer process completes await().pollInterval(fibonacci()) @@ -104,16 +108,15 @@ void transferData_privateBackend() throws IOException, InterruptedException { await().pollInterval(fibonacci()) .atMost(ASYNC_TIMEOUT) .untilAsserted(() -> { - edr.set(SOKRATES.edrs().getDataReferenceFromBackend(transferProcessId)); + edr.set(SOKRATES.edrs().getEdr(transferProcessId)); assertThat(edr).isNotNull(); }); // pull data out of provider's backend service: - // Cons-DP -> Prov-DP -> Prov-backend + // Prov-DP -> Prov-backend assertThat(SOKRATES.data().pullData(edr.get(), Map.of())).isEqualTo("test response"); var rq = server.takeRequest(); - assertThat(rq.getHeader(authCodeHeaderName)).isEqualTo(authCode); - assertThat(rq.getHeader("Edc-Contract-Agreement-Id")).isEqualTo(edr.get().getContractId()); + assertThat(rq.getHeader("Edc-Contract-Agreement-Id")).isNotNull(); assertThat(rq.getHeader("Edc-Bpn")).isEqualTo(SOKRATES.getBpn()); assertThat(rq.getMethod()).isEqualToIgnoringCase("GET"); } diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/DimHttpConsumerPullWithProxyInMemoryTest.java b/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/DimHttpConsumerPullWithProxyInMemoryTest.java similarity index 82% rename from edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/DimHttpConsumerPullWithProxyInMemoryTest.java rename to edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/DimHttpConsumerPullWithProxyInMemoryTest.java index 98c938079..91eaee3cc 100644 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/DimHttpConsumerPullWithProxyInMemoryTest.java +++ b/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/DimHttpConsumerPullWithProxyInMemoryTest.java @@ -26,15 +26,14 @@ import org.eclipse.edc.junit.annotations.EndToEndTest; import org.eclipse.edc.token.JwtGenerationService; import org.eclipse.edc.token.spi.TokenGenerationService; -import org.eclipse.tractusx.edc.lifecycle.ParticipantRuntime; -import org.eclipse.tractusx.edc.lifecycle.tx.iatp.DataspaceIssuer; -import org.eclipse.tractusx.edc.lifecycle.tx.iatp.IatpDimParticipant; -import org.eclipse.tractusx.edc.lifecycle.tx.iatp.SecureTokenService; -import org.eclipse.tractusx.edc.token.DimDispatcher; -import org.eclipse.tractusx.edc.token.KeycloakDispatcher; +import org.eclipse.tractusx.edc.tests.transfer.iatp.IatpDimParticipant; +import org.eclipse.tractusx.edc.tests.transfer.iatp.dispatchers.DimDispatcher; +import org.eclipse.tractusx.edc.tests.transfer.iatp.dispatchers.KeycloakDispatcher; +import org.eclipse.tractusx.edc.tests.transfer.iatp.harness.DataspaceIssuer; +import org.eclipse.tractusx.edc.tests.transfer.iatp.harness.SecureTokenService; +import org.eclipse.tractusx.edc.tests.transfer.iatp.runtime.IatpParticipantRuntime; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.extension.RegisterExtension; import java.io.IOException; @@ -47,8 +46,8 @@ import static org.eclipse.edc.junit.testfixtures.TestUtils.getFreePort; import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.CX_CREDENTIAL_NS; -import static org.eclipse.tractusx.edc.helpers.IatpHelperFunctions.configureParticipant; -import static org.eclipse.tractusx.edc.helpers.PolicyHelperFunctions.frameworkPolicy; +import static org.eclipse.tractusx.edc.tests.helpers.PolicyHelperFunctions.frameworkPolicy; +import static org.eclipse.tractusx.edc.tests.transfer.iatp.harness.IatpHelperFunctions.configureParticipant; @EndToEndTest public class DimHttpConsumerPullWithProxyInMemoryTest extends AbstractHttpConsumerPullWithProxyTest { @@ -59,20 +58,20 @@ public class DimHttpConsumerPullWithProxyInMemoryTest extends AbstractHttpConsum protected static final IatpDimParticipant PLATO_IATP = new IatpDimParticipant(PLATO, STS_PARTICIPANT.stsUri(), DIM_URI); @RegisterExtension - protected static final ParticipantRuntime PLATO_RUNTIME = new ParticipantRuntime( + protected static final IatpParticipantRuntime PLATO_RUNTIME = new IatpParticipantRuntime( ":edc-tests:runtime:iatp:runtime-memory-iatp-dim-ih", PLATO.getName(), - PLATO.getBpn(), - PLATO_IATP.iatpConfiguration(SOKRATES) + PLATO_IATP.iatpConfiguration(SOKRATES), + PLATO_IATP.getKeyPair() ); protected static final IatpDimParticipant SOKRATES_IATP = new IatpDimParticipant(SOKRATES, STS_PARTICIPANT.stsUri(), DIM_URI); @RegisterExtension - protected static final ParticipantRuntime SOKRATES_RUNTIME = new ParticipantRuntime( + protected static final IatpParticipantRuntime SOKRATES_RUNTIME = new IatpParticipantRuntime( ":edc-tests:runtime:iatp:runtime-memory-iatp-dim-ih", SOKRATES.getName(), - SOKRATES.getBpn(), - SOKRATES_IATP.iatpConfiguration(PLATO) + SOKRATES_IATP.iatpConfiguration(PLATO), + SOKRATES_IATP.getKeyPair() ); private static MockWebServer oauthServer; private static MockWebServer dimDispatcher; @@ -123,10 +122,6 @@ private static Supplier publicIdSupplier(IatpDimParticipant participant) return participant::verificationId; } - @BeforeEach - void setup() throws IOException { - super.setup(); - } @Override protected JsonObject createContractPolicy(String bpn) { diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/IatpHttpConsumerPullWithProxyInMemoryTest.java b/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/IatpHttpConsumerPullWithProxyInMemoryTest.java similarity index 86% rename from edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/IatpHttpConsumerPullWithProxyInMemoryTest.java rename to edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/IatpHttpConsumerPullWithProxyInMemoryTest.java index e87631e18..73b2993ec 100644 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/IatpHttpConsumerPullWithProxyInMemoryTest.java +++ b/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/IatpHttpConsumerPullWithProxyInMemoryTest.java @@ -26,13 +26,11 @@ import org.eclipse.edc.iam.did.spi.document.DidDocument; import org.eclipse.edc.junit.annotations.EndToEndTest; import org.eclipse.edc.policy.model.Operator; -import org.eclipse.edc.spi.types.domain.edr.EndpointDataReference; -import org.eclipse.tractusx.edc.lifecycle.ParticipantRuntime; -import org.eclipse.tractusx.edc.lifecycle.tx.iatp.DataspaceIssuer; -import org.eclipse.tractusx.edc.lifecycle.tx.iatp.IatpParticipant; -import org.eclipse.tractusx.edc.lifecycle.tx.iatp.SecureTokenService; +import org.eclipse.tractusx.edc.tests.transfer.iatp.IatpParticipant; +import org.eclipse.tractusx.edc.tests.transfer.iatp.harness.DataspaceIssuer; +import org.eclipse.tractusx.edc.tests.transfer.iatp.harness.SecureTokenService; +import org.eclipse.tractusx.edc.tests.transfer.iatp.runtime.IatpParticipantRuntime; import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.RegisterExtension; @@ -53,44 +51,36 @@ import static org.awaitility.pollinterval.FibonacciPollInterval.fibonacci; import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.CX_CREDENTIAL_NS; import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.CX_POLICY_NS; -import static org.eclipse.tractusx.edc.helpers.IatpHelperFunctions.configureParticipant; -import static org.eclipse.tractusx.edc.helpers.PolicyHelperFunctions.frameworkPolicy; -import static org.eclipse.tractusx.edc.helpers.TransferProcessHelperFunctions.createProxyRequest; -import static org.eclipse.tractusx.edc.tests.TestCommon.ASYNC_TIMEOUT; +import static org.eclipse.tractusx.edc.tests.TxParticipant.ASYNC_TIMEOUT; +import static org.eclipse.tractusx.edc.tests.helpers.PolicyHelperFunctions.frameworkPolicy; +import static org.eclipse.tractusx.edc.tests.transfer.iatp.harness.IatpHelperFunctions.configureParticipant; @EndToEndTest public class IatpHttpConsumerPullWithProxyInMemoryTest extends AbstractHttpConsumerPullWithProxyTest { protected static final DataspaceIssuer DATASPACE_ISSUER_PARTICIPANT = new DataspaceIssuer(); protected static final SecureTokenService STS_PARTICIPANT = new SecureTokenService(); - protected static final IatpParticipant PLATO_IATP = new IatpParticipant(PLATO, STS_PARTICIPANT.stsUri()); - @RegisterExtension - protected static final ParticipantRuntime PLATO_RUNTIME = new ParticipantRuntime( + protected static final IatpParticipantRuntime PLATO_RUNTIME = new IatpParticipantRuntime( ":edc-tests:runtime:iatp:runtime-memory-iatp-ih", PLATO.getName(), - PLATO.getBpn(), - PLATO_IATP.iatpConfiguration(SOKRATES) - ); - + PLATO_IATP.iatpConfiguration(SOKRATES), + PLATO_IATP.getKeyPair()); protected static final IatpParticipant SOKRATES_IATP = new IatpParticipant(SOKRATES, STS_PARTICIPANT.stsUri()); - @RegisterExtension - protected static final ParticipantRuntime SOKRATES_RUNTIME = new ParticipantRuntime( + protected static final IatpParticipantRuntime SOKRATES_RUNTIME = new IatpParticipantRuntime( ":edc-tests:runtime:iatp:runtime-memory-iatp-ih", SOKRATES.getName(), - SOKRATES.getBpn(), - SOKRATES_IATP.iatpConfiguration(PLATO) - ); + SOKRATES_IATP.iatpConfiguration(PLATO), + SOKRATES_IATP.getKeyPair()); @RegisterExtension - protected static final ParticipantRuntime STS_RUNTIME = new ParticipantRuntime( + protected static final IatpParticipantRuntime STS_RUNTIME = new IatpParticipantRuntime( ":edc-tests:runtime:iatp:runtime-memory-sts", STS_PARTICIPANT.getName(), - STS_PARTICIPANT.getBpn(), - STS_PARTICIPANT.stsConfiguration(SOKRATES_IATP, PLATO_IATP) - ); + STS_PARTICIPANT.stsConfiguration(SOKRATES_IATP, PLATO_IATP), + STS_PARTICIPANT.getKeyPair()); @BeforeAll static void prepare() { @@ -106,17 +96,6 @@ static void prepare() { } - - @BeforeEach - void setup() throws IOException { - super.setup(); - } - - @Override - protected JsonObject createContractPolicy(String bpn) { - return frameworkPolicy(Map.of(CX_CREDENTIAL_NS + "Membership", "active")); - } - @DisplayName("Contract policy is fulfilled") @ParameterizedTest(name = "{1}") @ArgumentsSource(ValidContractPolicyProvider.class) @@ -143,7 +122,7 @@ void transferData_whenContractPolicyFulfilled(JsonObject contractPolicy, String PLATO.createContractDefinition(assetId, "def-1", accessPolicyId, contractPolicyId); var transferProcessId = SOKRATES.requestAsset(PLATO, assetId, Json.createObjectBuilder().build(), createProxyRequest()); - var edr = new AtomicReference(); + var edr = new AtomicReference(); // wait until transfer process completes await().pollInterval(fibonacci()) @@ -158,7 +137,7 @@ void transferData_whenContractPolicyFulfilled(JsonObject contractPolicy, String await().pollInterval(fibonacci()) .atMost(ASYNC_TIMEOUT) .untilAsserted(() -> { - edr.set(SOKRATES.edrs().getDataReferenceFromBackend(transferProcessId)); + edr.set(SOKRATES.edrs().getEdr(transferProcessId)); assertThat(edr).isNotNull(); }); @@ -167,7 +146,7 @@ void transferData_whenContractPolicyFulfilled(JsonObject contractPolicy, String assertThat(SOKRATES.data().pullData(edr.get(), Map.of())).isEqualTo("test response"); var rq = server.takeRequest(); assertThat(rq.getHeader(authCodeHeaderName)).isEqualTo(authCode); - assertThat(rq.getHeader("Edc-Contract-Agreement-Id")).isEqualTo(edr.get().getContractId()); + assertThat(rq.getHeader("Edc-Contract-Agreement-Id")).isNotNull(); assertThat(rq.getHeader("Edc-Bpn")).isEqualTo(SOKRATES.getBpn()); assertThat(rq.getMethod()).isEqualToIgnoringCase("GET"); } @@ -175,7 +154,7 @@ void transferData_whenContractPolicyFulfilled(JsonObject contractPolicy, String @DisplayName("Contract policy is NOT fulfilled") @ParameterizedTest(name = "{1}") @ArgumentsSource(InvalidContractPolicyProvider.class) - void transferData_whenContractPolicyNotFulfilled(JsonObject contractPolicy, String description) throws IOException, InterruptedException { + void transferData_whenContractPolicyNotFulfilled(JsonObject contractPolicy, String description) throws IOException { var assetId = "api-asset-1"; var url = server.url("/mock/api"); server.start(); @@ -201,10 +180,16 @@ void transferData_whenContractPolicyNotFulfilled(JsonObject contractPolicy, Stri await().pollInterval(fibonacci()) .atMost(ASYNC_TIMEOUT) .untilAsserted(() -> { - assertThat(SOKRATES.getContractNegotiationError(negotiationId)).isNotNull(); + var contractNegotiationState = SOKRATES.getContractNegotiationState(negotiationId); + assertThat(contractNegotiationState).isEqualTo("TERMINATED"); }); } + @Override + protected JsonObject createContractPolicy(String bpn) { + return frameworkPolicy(Map.of(CX_CREDENTIAL_NS + "Membership", "active")); + } + private static class ValidContractPolicyProvider implements ArgumentsProvider { @Override public Stream provideArguments(ExtensionContext extensionContext) { diff --git a/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-core/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/core/gateway/auth/AuthorizationHandlerRegistryImpl.java b/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/iatp/IatpDimParticipant.java similarity index 52% rename from edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-core/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/core/gateway/auth/AuthorizationHandlerRegistryImpl.java rename to edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/iatp/IatpDimParticipant.java index 79c344695..28bebf2ec 100644 --- a/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-core/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/provider/core/gateway/auth/AuthorizationHandlerRegistryImpl.java +++ b/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/iatp/IatpDimParticipant.java @@ -1,5 +1,5 @@ /******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) * * See the NOTICE file(s) distributed with this work for additional * information regarding copyright ownership. @@ -17,28 +17,30 @@ * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ -package org.eclipse.tractusx.edc.dataplane.proxy.provider.core.gateway.auth; +package org.eclipse.tractusx.edc.tests.transfer.iatp; -import org.eclipse.tractusx.edc.dataplane.proxy.spi.provider.gateway.authorization.AuthorizationHandler; -import org.eclipse.tractusx.edc.dataplane.proxy.spi.provider.gateway.authorization.AuthorizationHandlerRegistry; -import org.jetbrains.annotations.Nullable; +import org.eclipse.tractusx.edc.tests.TxParticipant; + +import java.net.URI; import java.util.HashMap; import java.util.Map; /** - * Default implementation of the registry. + * Extension of {@link IatpParticipant} with DIM specific configuration */ -public class AuthorizationHandlerRegistryImpl implements AuthorizationHandlerRegistry { - private final Map handlers = new HashMap<>(); +public class IatpDimParticipant extends IatpParticipant { + private final URI dimUri; - @Override - public @Nullable AuthorizationHandler getHandler(String alias) { - return handlers.get(alias); + public IatpDimParticipant(TxParticipant participant, URI stsUri, URI dimUri) { + super(participant, stsUri); + this.dimUri = dimUri; } @Override - public void register(String alias, AuthorizationHandler handler) { - handlers.put(alias, handler); + public Map iatpConfiguration(TxParticipant... others) { + var config = new HashMap<>(super.iatpConfiguration(others)); + config.put("edc.iam.sts.dim.url", dimUri.toString()); + return config; } } diff --git a/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/iatp/IatpParticipant.java b/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/iatp/IatpParticipant.java new file mode 100644 index 000000000..fcaea780b --- /dev/null +++ b/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/iatp/IatpParticipant.java @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.eclipse.tractusx.edc.tests.transfer.iatp; + +import org.eclipse.edc.iam.did.spi.document.DidDocument; +import org.eclipse.edc.iam.did.spi.document.Service; +import org.eclipse.edc.iam.did.spi.document.VerificationMethod; +import org.eclipse.tractusx.edc.tests.IdentityParticipant; +import org.eclipse.tractusx.edc.tests.TxParticipant; + +import java.net.URI; +import java.util.Arrays; +import java.util.Base64; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Stream; + +import static org.eclipse.edc.junit.testfixtures.TestUtils.getFreePort; +import static org.eclipse.tractusx.edc.tests.transfer.iatp.harness.DataspaceIssuer.DATASPACE_ISSUER; + +/** + * Wrapper of {@link TxParticipant} with IATP specific configurations + */ +public class IatpParticipant extends IdentityParticipant { + + public static final String DID_EXAMPLE = "did:example:"; + protected final URI csService = URI.create("http://localhost:" + getFreePort() + "/api/resolution"); + private final TxParticipant participant; + private final URI stsUri; + private final DidDocument didDocument; + + public IatpParticipant(TxParticipant participant, URI stsUri) { + this.participant = participant; + this.stsUri = stsUri; + this.didDocument = generateDidDocument(); + } + + public String getBpn() { + return participant.getBpn(); + } + + public String getName() { + return participant.getName(); + } + + public Map iatpConfiguration(TxParticipant... others) { + var did = DID_EXAMPLE + participant.getName().toLowerCase(); + var iatpConfiguration = new HashMap<>(participant.getConfiguration()) { + { + + put("edc.iam.sts.oauth.token.url", stsUri + "/token"); + put("edc.iam.sts.oauth.client.id", getBpn()); + put("edc.iam.sts.oauth.client.secret.alias", "client_secret_alias"); + put("edc.iam.issuer.id", did); + put("edc.ih.iam.id", participant.getBpn()); + put("tx.vault.seed.secrets", "client_secret_alias:client_secret"); + put("edc.ih.iam.publickey.alias", getFullKeyId()); + put("web.http.resolution.port", String.valueOf(csService.getPort())); + put("web.http.resolution.path", csService.getPath()); + put("edc.agent.identity.key", "client_id"); + put("edc.iam.trusted-issuer.issuer.id", DATASPACE_ISSUER); + + put("edc.transfer.proxy.token.signer.privatekey.alias", getPrivateKeyAlias()); + put("edc.transfer.proxy.token.verifier.publickey.alias", getFullKeyId()); + } + }; + + Stream.concat(Stream.of(participant), Arrays.stream(others)).forEach(p -> { + var prefix = "tx.iam.iatp.audiences.%s".formatted(p.getName().toLowerCase()); + var participantDid = DID_EXAMPLE + p.getName().toLowerCase(); + iatpConfiguration.put("%s_endpoint.from".formatted(prefix), p.getProtocolEndpoint().getUrl().toString()); + iatpConfiguration.put("%s_endpoint.to".formatted(prefix), participantDid); + iatpConfiguration.put("%s_id.from".formatted(prefix), p.getBpn()); + iatpConfiguration.put("%s_id.to".formatted(prefix), participantDid); + }); + return iatpConfiguration; + } + + public String didUrl() { + return DID_EXAMPLE + participant.getName().toLowerCase(); + } + + public String verificationId() { + return didUrl() + "#" + getKeyId(); + } + + public DidDocument didDocument() { + return didDocument; + } + + @Override + public String getFullKeyId() { + return verificationId(); + } + + + private DidDocument generateDidDocument() { + var service = new Service(); + service.setId("#credential-service"); + service.setType("CredentialService"); + service.setServiceEndpoint(csService + "/v1/participants/" + toBase64(didUrl())); + + var ecKey = getKeyPairAsJwk(); + + var verificationMethod = VerificationMethod.Builder.newInstance() + .id(verificationId()) + .controller(didUrl()) + .type("JsonWebKey2020") + .publicKeyJwk(ecKey.toPublicJWK().toJSONObject()) + .build(); + + return DidDocument.Builder.newInstance() + .id(didUrl()) + .service(List.of(service)) + .authentication(List.of("#key1")) + .verificationMethod(List.of(verificationMethod)) + .build(); + } + + private String toBase64(String s) { + return Base64.getUrlEncoder().encodeToString(s.getBytes()); + } +} diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/token/DimDispatcher.java b/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/iatp/dispatchers/DimDispatcher.java similarity index 95% rename from edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/token/DimDispatcher.java rename to edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/iatp/dispatchers/DimDispatcher.java index f79d39d9b..7193d0793 100644 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/token/DimDispatcher.java +++ b/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/iatp/dispatchers/DimDispatcher.java @@ -1,5 +1,5 @@ -/******************************************************************************** - * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +/* + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft * * See the NOTICE file(s) distributed with this work for additional * information regarding copyright ownership. @@ -15,9 +15,9 @@ * under the License. * * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ + */ -package org.eclipse.tractusx.edc.token; +package org.eclipse.tractusx.edc.tests.transfer.iatp.dispatchers; import okhttp3.mockwebserver.Dispatcher; import okhttp3.mockwebserver.MockResponse; diff --git a/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/iatp/dispatchers/KeycloakDispatcher.java b/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/iatp/dispatchers/KeycloakDispatcher.java new file mode 100644 index 000000000..6861f3a30 --- /dev/null +++ b/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/iatp/dispatchers/KeycloakDispatcher.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.eclipse.tractusx.edc.tests.transfer.iatp.dispatchers; + +import okhttp3.mockwebserver.Dispatcher; +import okhttp3.mockwebserver.MockResponse; +import okhttp3.mockwebserver.RecordedRequest; +import org.eclipse.edc.spi.types.TypeManager; +import org.jetbrains.annotations.NotNull; + +import java.util.Map; + +public class KeycloakDispatcher extends Dispatcher { + + private static final TypeManager MAPPER = new TypeManager(); + private final String path; + + public KeycloakDispatcher(String path) { + this.path = path; + } + + public KeycloakDispatcher() { + this("/"); + } + + @NotNull + @Override + public MockResponse dispatch(@NotNull RecordedRequest recordedRequest) { + if (recordedRequest.getPath().split("\\?")[0].equals(path)) { + return createTokenResponse(); + } + return new MockResponse().setResponseCode(404); + } + + private MockResponse createTokenResponse() { + return new MockResponse().setBody(MAPPER.writeValueAsString(Map.of("access_token", "token"))); + } + +} diff --git a/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/iatp/harness/DataspaceIssuer.java b/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/iatp/harness/DataspaceIssuer.java new file mode 100644 index 000000000..56fa04427 --- /dev/null +++ b/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/iatp/harness/DataspaceIssuer.java @@ -0,0 +1,180 @@ +/* + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.eclipse.tractusx.edc.tests.transfer.iatp.harness; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.nimbusds.jose.jwk.JWK; +import jakarta.json.Json; +import jakarta.json.JsonObject; +import org.eclipse.edc.iam.did.spi.document.DidDocument; +import org.eclipse.edc.iam.did.spi.document.VerificationMethod; +import org.eclipse.edc.identityhub.spi.model.VerifiableCredentialResource; +import org.eclipse.edc.identitytrust.model.CredentialFormat; +import org.eclipse.edc.identitytrust.model.CredentialSubject; +import org.eclipse.edc.identitytrust.model.Issuer; +import org.eclipse.edc.identitytrust.model.VerifiableCredential; +import org.eclipse.edc.identitytrust.model.VerifiableCredentialContainer; +import org.eclipse.edc.jsonld.spi.JsonLd; +import org.eclipse.edc.security.signature.jws2020.JwkMethod; +import org.eclipse.edc.security.signature.jws2020.JwsSignature2020Suite; +import org.eclipse.edc.verifiablecredentials.linkeddata.LdpIssuer; +import org.eclipse.tractusx.edc.tests.IdentityParticipant; +import org.eclipse.tractusx.edc.tests.transfer.iatp.IatpParticipant; + +import java.net.URI; +import java.time.Instant; +import java.util.List; +import java.util.Map; +import java.util.function.Supplier; + +import static org.eclipse.edc.jsonld.util.JacksonJsonLd.createObjectMapper; +import static org.eclipse.tractusx.edc.tests.transfer.iatp.harness.IatpHelperFunctions.createVc; +import static org.eclipse.tractusx.edc.tests.transfer.iatp.harness.IatpHelperFunctions.frameworkAgreementSubject; +import static org.eclipse.tractusx.edc.tests.transfer.iatp.harness.IatpHelperFunctions.membershipSubject; +import static org.mockito.Mockito.mock; + +/** + * Dataspace issuer configurations + */ +public class DataspaceIssuer extends IdentityParticipant { + + public static final String DATASPACE_ISSUER = "did:example:dataspace_issuer"; + private static final ObjectMapper MAPPER = createObjectMapper(); + private static final String KEY_ID = "#key1"; + private final JwsSignature2020Suite jws2020suite = new JwsSignature2020Suite(MAPPER); + private final DidDocument didDocument; + + public DataspaceIssuer() { + didDocument = generateDidDocument(); + } + + public String didUrl() { + return DATASPACE_ISSUER; + } + + public DidDocument didDocument() { + return didDocument; + } + + public String verificationId() { + return DATASPACE_ISSUER + "#" + getKeyId(); + } + + public VerifiableCredentialResource issueCredential(IatpParticipant participant, JsonLd jsonLd, String type, Supplier credentialSubjectSupplier, Supplier subjectSupplier) { + var credential = VerifiableCredential.Builder.newInstance() + .type(type) + .credentialSubject(credentialSubjectSupplier.get()) + .issuer(new Issuer(didUrl(), Map.of())) + .issuanceDate(Instant.now()) + .build(); + + var rawVc = createLdpVc(jsonLd, type, subjectSupplier); + return VerifiableCredentialResource.Builder.newInstance() + .issuerId(didUrl()) + .participantId(participant.didUrl()) + .holderId(participant.getBpn()) + .credential(new VerifiableCredentialContainer(rawVc, CredentialFormat.JSON_LD, credential)) + .build(); + + } + + public VerifiableCredentialResource issueMembershipCredential(IatpParticipant participant, JsonLd jsonLd) { + return issueCredential(participant, jsonLd, "MembershipCredential", () -> CredentialSubject.Builder.newInstance() + .claim("holderIdentifier", participant.getBpn()) + .build(), + () -> membershipSubject(participant.didUrl(), participant.getBpn())); + } + + public VerifiableCredentialResource issueDismantlerCredential(IatpParticipant participant, JsonLd jsonLd) { + return issueCredential(participant, jsonLd, "DismantlerCredential", () -> CredentialSubject.Builder.newInstance() + .claim("holderIdentifier", participant.didUrl()) + .claim("activityType", "vehicleDismantle") + .claim("allowedVehicleBrands", List.of("Moskvich", "Lada")) + .build(), + () -> Json.createObjectBuilder() + .add("type", "MembershipCredential") + .add("holderIdentifier", participant.didUrl()) + .add("activityType", "vehicleDismantle") + .add("allowedVehicleBrands", Json.createArrayBuilder().add("Moskvich").add("Lada").build()) + .add("id", participant.didUrl()) + .build()); + } + + public VerifiableCredentialResource issueFrameworkCredential(IatpParticipant participant, JsonLd jsonLd, String credentialType) { + return issueCredential(participant, jsonLd, credentialType, () -> CredentialSubject.Builder.newInstance() + .claim("holderIdentifier", participant.getBpn()) + .build(), + () -> frameworkAgreementSubject(participant.didUrl(), participant.getBpn(), credentialType)); + + } + + @Override + public String getFullKeyId() { + return verificationId(); + } + + private String createLdpVc(JsonLd jsonLd, String type, Supplier subjectSupplier) { + var issuer = LdpIssuer.Builder.newInstance() + .jsonLd(jsonLd) + .monitor(mock()) + .build(); + + var proofOptions = jws2020suite.createOptions() + .created(Instant.now()) + .verificationMethod(new JwkMethod(URI.create(verificationId()), null, null, null)) + .purpose(URI.create("https://w3id.org/security#assertionMethod")); + + var key = getKeyPairAsJwk(); + + var vc = createVc(didUrl(), type, subjectSupplier); + var result = issuer.signDocument(vc, createKeyPair(key, verificationId()), proofOptions).orElseThrow(err -> new RuntimeException(err.getFailureDetail())); + + try { + return MAPPER.writeValueAsString(result); + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + } + + private com.apicatalog.ld.signature.key.KeyPair createKeyPair(JWK jwk, String id) { + var type = URI.create("https://w3id.org/security#JsonWebKey2020"); + return new JwkMethod(URI.create(id), type, null, jwk); + } + + private DidDocument generateDidDocument() { + + + var jwk = getKeyPairAsJwk(); + var verificationMethod = VerificationMethod.Builder.newInstance() + .id(verificationId()) + .controller(didUrl()) + .type("JsonWebKey2020") + .publicKeyJwk(jwk.toPublicJWK().toJSONObject()) + .build(); + + return DidDocument.Builder.newInstance() + .id(didUrl()) + .authentication(List.of(KEY_ID)) + .verificationMethod(List.of(verificationMethod)) + .build(); + + } +} diff --git a/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/iatp/harness/DidExampleResolver.java b/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/iatp/harness/DidExampleResolver.java new file mode 100644 index 000000000..eee98794e --- /dev/null +++ b/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/iatp/harness/DidExampleResolver.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.eclipse.tractusx.edc.tests.transfer.iatp.harness; + +import org.eclipse.edc.iam.did.spi.document.DidDocument; +import org.eclipse.edc.iam.did.spi.resolution.DidResolver; +import org.eclipse.edc.spi.result.Result; +import org.jetbrains.annotations.NotNull; + +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; + +/** + * Implementation of {@link DidResolver} for `did:example` with local cache (for testing) + */ +public class DidExampleResolver implements DidResolver { + + private final Map cache = new HashMap<>(); + + @Override + public @NotNull String getMethod() { + return "example"; + } + + @Override + public @NotNull Result resolve(String did) { + + var ix = did.indexOf("#"); + if (ix > 0) { + did = did.substring(0, ix); + } + + return Optional.ofNullable(cache.get(did)) + .map(Result::success) + .orElseGet(() -> Result.failure("Failed to fetch did")); + } + + public void addCached(String did, DidDocument document) { + cache.put(did, document); + } +} diff --git a/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/iatp/harness/IatpHelperFunctions.java b/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/iatp/harness/IatpHelperFunctions.java new file mode 100644 index 000000000..f16e88153 --- /dev/null +++ b/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/iatp/harness/IatpHelperFunctions.java @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.eclipse.tractusx.edc.tests.transfer.iatp.harness; + +import jakarta.json.Json; +import jakarta.json.JsonArray; +import jakarta.json.JsonObject; +import org.eclipse.edc.iam.did.spi.document.DidDocument; +import org.eclipse.edc.iam.did.spi.resolution.DidResolverRegistry; +import org.eclipse.edc.identityhub.spi.ParticipantContextService; +import org.eclipse.edc.identityhub.spi.model.VerifiableCredentialResource; +import org.eclipse.edc.identityhub.spi.model.participant.KeyDescriptor; +import org.eclipse.edc.identityhub.spi.model.participant.ParticipantManifest; +import org.eclipse.edc.identityhub.spi.store.CredentialStore; +import org.eclipse.edc.jsonld.spi.JsonLd; +import org.eclipse.edc.junit.extensions.EdcExtension; +import org.eclipse.edc.spi.security.Vault; +import org.eclipse.tractusx.edc.tests.transfer.iatp.IatpParticipant; + +import java.time.Instant; +import java.util.List; +import java.util.Map; +import java.util.function.Supplier; + +public class IatpHelperFunctions { + public static JsonObject createVc(String issuer, String type, Supplier subjectSupplier) { + return Json.createObjectBuilder() + .add("@context", context()) + .add("type", types(type)) + .add("credentialSubject", subjectSupplier.get()) + .add("issuer", issuer) + .add("issuanceDate", Instant.now().toString()) + .build(); + } + + public static JsonObject membershipSubject(String did, String id) { + return Json.createObjectBuilder() + .add("type", "MembershipCredential") + .add("holderIdentifier", id) + .add("id", did) + .build(); + + } + + public static JsonObject frameworkAgreementSubject(String did, String id, String type) { + return Json.createObjectBuilder() + .add("type", type) + .add("holderIdentifier", id) + .add("contractVersion", "1.0.0") + .add("contractTemplate", "https://public.catena-x.org/contracts/traceabilty.v1.pdf") + .add("id", did) + .build(); + + } + + private static JsonArray types(String type) { + return Json.createArrayBuilder() + .add("VerifiableCredential") + .add(type) + .build(); + } + + private static JsonArray context() { + return Json.createArrayBuilder() + .add("https://www.w3.org/2018/credentials/v1") + .add("https://w3id.org/security/suites/jws-2020/v1") + .add("https://w3id.org/catenax/credentials") + .build(); + } + + public static void configureParticipant(DataspaceIssuer issuer, IatpParticipant participant, EdcExtension runtime, Map didDocs, EdcExtension stsRuntime) { + + if (stsRuntime != null) { + stsRuntime.getContext().getService(Vault.class).storeSecret(participant.verificationId(), participant.getPrivateKeyAsString()); + } + var participantContextService = runtime.getContext().getService(ParticipantContextService.class); + var vault = runtime.getContext().getService(Vault.class); + var didResolverRegistry = runtime.getContext().getService(DidResolverRegistry.class); + var didResolver = new DidExampleResolver(); + didDocs.forEach(didResolver::addCached); + didResolverRegistry.register(didResolver); + + var participantKey = participant.getKeyPairAsJwk(); + var key = KeyDescriptor.Builder.newInstance() + .keyId(participant.getKeyId()) + .publicKeyJwk(participantKey.toPublicJWK().toJSONObject()) + .privateKeyAlias(participant.getPrivateKeyAlias()) + .build(); + + var participantManifest = ParticipantManifest.Builder.newInstance() + .participantId(participant.didUrl()) + .did(participant.didUrl()) + .key(key) + .build(); + + participantContextService.createParticipantContext(participantManifest); + vault.storeSecret(participant.getPrivateKeyAlias(), participant.getPrivateKeyAsString()); + + storeCredentials(issuer, participant, runtime); + } + + private static void storeCredentials(DataspaceIssuer issuer, IatpParticipant participant, EdcExtension runtime) { + var credentialStore = runtime.getContext().getService(CredentialStore.class); + var jsonLd = runtime.getContext().getService(JsonLd.class); + issueCredentials(issuer, participant, jsonLd).forEach(credentialStore::create); + } + + private static List issueCredentials(DataspaceIssuer issuer, IatpParticipant participant, JsonLd jsonLd) { + return List.of( + issuer.issueMembershipCredential(participant, jsonLd), + issuer.issueDismantlerCredential(participant, jsonLd), + issuer.issueFrameworkCredential(participant, jsonLd, "PcfCredential")); + + } +} diff --git a/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/iatp/harness/SecureTokenService.java b/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/iatp/harness/SecureTokenService.java new file mode 100644 index 000000000..9e8345ff1 --- /dev/null +++ b/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/iatp/harness/SecureTokenService.java @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.eclipse.tractusx.edc.tests.transfer.iatp.harness; + + +import org.eclipse.tractusx.edc.tests.IdentityParticipant; +import org.eclipse.tractusx.edc.tests.TxParticipant; +import org.eclipse.tractusx.edc.tests.transfer.iatp.IatpParticipant; + +import java.net.URI; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +import static java.lang.String.format; +import static org.eclipse.edc.junit.testfixtures.TestUtils.getFreePort; + +/** + * STS configurations + */ +public class SecureTokenService extends IdentityParticipant { + + protected final URI stsUri = URI.create("http://localhost:" + getFreePort() + "/api/v1/sts"); + protected final TxParticipant stsParticipant = TxParticipant.Builder.newInstance() + .name("STS") + .id("STS") + .build(); + + public Map stsConfiguration(IatpParticipant... participants) { + var stsConfiguration = new HashMap() { + { + put("web.http.sts.port", String.valueOf(stsUri.getPort())); + put("web.http.sts.path", stsUri.getPath()); + put("edc.dataplane.token.validation.endpoint", ""); + put("tx.vault.seed.secrets", "client_secret_alias:client_secret"); + } + }; + + Arrays.stream(participants).forEach(participant -> { + var prefix = format("edc.iam.sts.clients.%s", participant.getName().toLowerCase()); + stsConfiguration.put(prefix + ".name", participant.getName()); + stsConfiguration.put(prefix + ".id", UUID.randomUUID().toString()); + stsConfiguration.put(prefix + ".client_id", participant.getBpn()); + stsConfiguration.put(prefix + ".did", participant.didUrl()); + stsConfiguration.put(prefix + ".secret.alias", "client_secret_alias"); + stsConfiguration.put(prefix + ".private-key.alias", participant.verificationId()); + stsConfiguration.put(prefix + ".public-key.reference", participant.verificationId()); + }); + + var baseConfiguration = stsParticipant.getConfiguration(); + stsConfiguration.putAll(baseConfiguration); + return stsConfiguration; + } + + public String getBpn() { + return stsParticipant.getBpn(); + } + + public String getName() { + return stsParticipant.getName(); + } + + public URI stsUri() { + return stsUri; + } + + @Override + public String getFullKeyId() { + return "sts-" + getKeyId(); + } +} diff --git a/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/iatp/runtime/IatpParticipantRuntime.java b/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/iatp/runtime/IatpParticipantRuntime.java new file mode 100644 index 000000000..ad2d28560 --- /dev/null +++ b/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/iatp/runtime/IatpParticipantRuntime.java @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.eclipse.tractusx.edc.tests.transfer.iatp.runtime; + +import com.nimbusds.jose.jwk.JWK; +import org.eclipse.edc.junit.extensions.EdcRuntimeExtension; +import org.eclipse.edc.security.token.jwt.CryptoConverter; +import org.eclipse.edc.spi.security.Vault; +import org.eclipse.edc.spi.system.ServiceExtension; +import org.eclipse.edc.spi.system.ServiceExtensionContext; +import org.eclipse.edc.spi.system.injection.InjectionContainer; +import org.eclipse.tractusx.edc.tests.runtimes.DataWiper; +import org.junit.jupiter.api.extension.AfterAllCallback; +import org.junit.jupiter.api.extension.BeforeAllCallback; +import org.junit.jupiter.api.extension.ExtensionContext; + +import java.security.KeyPair; +import java.util.List; +import java.util.Map; + + +public class IatpParticipantRuntime extends EdcRuntimeExtension implements BeforeAllCallback, AfterAllCallback { + + private final Map properties; + private final JWK runtimeKeyPair; + private DataWiper wiper; + + public IatpParticipantRuntime(String moduleName, String runtimeName, Map properties, KeyPair runtimeKeypair) { + super(moduleName, runtimeName, properties); + this.properties = properties; + runtimeKeyPair = CryptoConverter.createJwk(runtimeKeypair); + } + + @Override + public void beforeTestExecution(ExtensionContext extensionContext) { + //do nothing - we only want to start the runtime once + wiper.clearPersistence(); + } + + @Override + public void afterTestExecution(ExtensionContext context) { + } + + @Override + public void beforeAll(ExtensionContext context) throws Exception { + //only run this once + super.beforeTestExecution(context); + } + + @Override + public void afterAll(ExtensionContext context) throws Exception { + super.afterTestExecution(context); + } + + @Override + protected void bootExtensions(ServiceExtensionContext context, List> serviceExtensions) { + super.bootExtensions(context, serviceExtensions); + wiper = new DataWiper(context); + registerConsumerPullKeys(runtimeKeyPair); + } + + private void registerConsumerPullKeys(JWK ecKey) { + var privateAlias = properties.get("edc.transfer.proxy.token.signer.privatekey.alias"); + var publicAlias = properties.get("edc.transfer.proxy.token.verifier.publickey.alias"); + + if (privateAlias != null && publicAlias != null) { + var vault = getContext().getService(Vault.class); + vault.storeSecret(privateAlias, ecKey.toJSONString()); + vault.storeSecret(publicAlias, ecKey.toPublicJWK().toJSONString()); + } + } + +} diff --git a/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-core/build.gradle.kts b/edc-tests/edc-controlplane/policy-tests/build.gradle.kts similarity index 70% rename from edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-core/build.gradle.kts rename to edc-tests/edc-controlplane/policy-tests/build.gradle.kts index 7a0d9b578..d0de250c2 100644 --- a/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-core/build.gradle.kts +++ b/edc-tests/edc-controlplane/policy-tests/build.gradle.kts @@ -19,21 +19,20 @@ plugins { `java-library` + `java-test-fixtures` } dependencies { + testImplementation(testFixtures(project(":edc-tests:edc-controlplane:fixtures"))) - implementation(libs.edc.util) - implementation(libs.edc.dpf.util) - implementation(libs.edc.token.core) - implementation(libs.edc.ext.http) - implementation(libs.edc.spi.http) - - implementation(libs.edc.spi.jwt) - - implementation(libs.jakarta.rsApi) - implementation(libs.nimbus.jwt) - - implementation(project(":edc-extensions:dataplane:dataplane-proxy:edc-dataplane-proxy-provider-spi")) + testImplementation(libs.netty.mockserver) + testImplementation(libs.edc.junit) + testImplementation(libs.restAssured) + testImplementation(libs.awaitility) + testImplementation(libs.okhttp.mockwebserver) } +// do not publish +edcBuild { + publish.set(false) +} diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/policy/AbstractPolicyMonitorTest.java b/edc-tests/edc-controlplane/policy-tests/src/test/java/org/eclipse/tractusx/edc/tests/policy/AbstractPolicyMonitorTest.java similarity index 89% rename from edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/policy/AbstractPolicyMonitorTest.java rename to edc-tests/edc-controlplane/policy-tests/src/test/java/org/eclipse/tractusx/edc/tests/policy/AbstractPolicyMonitorTest.java index fbad57b4c..e4dcc0b01 100644 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/policy/AbstractPolicyMonitorTest.java +++ b/edc-tests/edc-controlplane/policy-tests/src/test/java/org/eclipse/tractusx/edc/tests/policy/AbstractPolicyMonitorTest.java @@ -25,7 +25,7 @@ import okhttp3.mockwebserver.MockResponse; import okhttp3.mockwebserver.MockWebServer; import okhttp3.mockwebserver.RecordedRequest; -import org.eclipse.tractusx.edc.lifecycle.tx.TxParticipant; +import org.eclipse.tractusx.edc.tests.TxParticipant; import org.jetbrains.annotations.NotNull; import org.junit.jupiter.api.Test; @@ -41,11 +41,11 @@ import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.TYPE; import static org.eclipse.edc.spi.CoreConstants.EDC_NAMESPACE; import static org.eclipse.edc.test.system.utils.PolicyFixtures.inForceDatePolicy; -import static org.eclipse.tractusx.edc.lifecycle.TestRuntimeConfiguration.PLATO_BPN; -import static org.eclipse.tractusx.edc.lifecycle.TestRuntimeConfiguration.PLATO_NAME; -import static org.eclipse.tractusx.edc.lifecycle.TestRuntimeConfiguration.SOKRATES_BPN; -import static org.eclipse.tractusx.edc.lifecycle.TestRuntimeConfiguration.SOKRATES_NAME; -import static org.eclipse.tractusx.edc.tests.TestCommon.ASYNC_TIMEOUT; +import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.PLATO_BPN; +import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.PLATO_NAME; +import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.SOKRATES_BPN; +import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.SOKRATES_NAME; +import static org.eclipse.tractusx.edc.tests.TxParticipant.ASYNC_TIMEOUT; public abstract class AbstractPolicyMonitorTest { @@ -82,7 +82,7 @@ void shouldTerminateTransfer_whenPolicyExpires() throws IOException { var consumerUrl = server.url("/mock/api/consumer"); var destination = httpDataAddress(consumerUrl.toString()); - var transferProcessId = SOKRATES.requestAsset(PLATO, assetId, Json.createObjectBuilder().build(), destination); + var transferProcessId = SOKRATES.requestAsset(PLATO, assetId, Json.createObjectBuilder().build(), destination, "HttpData-PULL"); await().atMost(ASYNC_TIMEOUT).untilAsserted(() -> { var state = SOKRATES.getTransferProcessState(transferProcessId); assertThat(state).isEqualTo(STARTED.name()); diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/policy/PolicyMonitorInMemoryTest.java b/edc-tests/edc-controlplane/policy-tests/src/test/java/org/eclipse/tractusx/edc/tests/policy/PolicyMonitorInMemoryTest.java similarity index 97% rename from edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/policy/PolicyMonitorInMemoryTest.java rename to edc-tests/edc-controlplane/policy-tests/src/test/java/org/eclipse/tractusx/edc/tests/policy/PolicyMonitorInMemoryTest.java index e1f353b4c..198e4d494 100644 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/policy/PolicyMonitorInMemoryTest.java +++ b/edc-tests/edc-controlplane/policy-tests/src/test/java/org/eclipse/tractusx/edc/tests/policy/PolicyMonitorInMemoryTest.java @@ -22,7 +22,7 @@ import com.nimbusds.jose.util.Base64; import org.eclipse.edc.junit.annotations.EndToEndTest; import org.eclipse.edc.spi.security.Vault; -import org.eclipse.tractusx.edc.lifecycle.ParticipantRuntime; +import org.eclipse.tractusx.edc.tests.runtimes.ParticipantRuntime; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.extension.RegisterExtension; diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/policy/PolicyMonitorPostgresqlTest.java b/edc-tests/edc-controlplane/policy-tests/src/test/java/org/eclipse/tractusx/edc/tests/policy/PolicyMonitorPostgresqlTest.java similarity index 96% rename from edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/policy/PolicyMonitorPostgresqlTest.java rename to edc-tests/edc-controlplane/policy-tests/src/test/java/org/eclipse/tractusx/edc/tests/policy/PolicyMonitorPostgresqlTest.java index 76cd9be67..b8ab7ed2b 100644 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/policy/PolicyMonitorPostgresqlTest.java +++ b/edc-tests/edc-controlplane/policy-tests/src/test/java/org/eclipse/tractusx/edc/tests/policy/PolicyMonitorPostgresqlTest.java @@ -20,7 +20,7 @@ package org.eclipse.tractusx.edc.tests.policy; import org.eclipse.edc.junit.annotations.PostgresqlIntegrationTest; -import org.eclipse.tractusx.edc.lifecycle.PgParticipantRuntime; +import org.eclipse.tractusx.edc.tests.runtimes.PgParticipantRuntime; import org.junit.jupiter.api.extension.RegisterExtension; @PostgresqlIntegrationTest diff --git a/edc-tests/edc-controlplane/ssi-summarycred-tests/build.gradle.kts b/edc-tests/edc-controlplane/ssi-summarycred-tests/build.gradle.kts new file mode 100644 index 000000000..c5d8a88f3 --- /dev/null +++ b/edc-tests/edc-controlplane/ssi-summarycred-tests/build.gradle.kts @@ -0,0 +1,41 @@ +/******************************************************************************** + * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +plugins { + `java-library` + `java-test-fixtures` +} + +dependencies { + testImplementation(testFixtures(project(":edc-tests:edc-controlplane:fixtures"))) + testImplementation(libs.edc.ih.spi) + testImplementation(libs.edc.ih.spi.store) + testImplementation(libs.edc.junit) + testImplementation(libs.edc.core.token) + // 3rd party libs + testImplementation(libs.netty.mockserver) + testImplementation(libs.restAssured) + testImplementation(libs.awaitility) + testImplementation(libs.okhttp.mockwebserver) +} + +// do not publish +edcBuild { + publish.set(false) +} diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/token/KeycloakDispatcher.java b/edc-tests/edc-controlplane/ssi-summarycred-tests/src/test/java/org/eclipse/tractusx/edc/tests/KeycloakDispatcher.java similarity index 95% rename from edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/token/KeycloakDispatcher.java rename to edc-tests/edc-controlplane/ssi-summarycred-tests/src/test/java/org/eclipse/tractusx/edc/tests/KeycloakDispatcher.java index 43e1c3310..ded5051be 100644 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/token/KeycloakDispatcher.java +++ b/edc-tests/edc-controlplane/ssi-summarycred-tests/src/test/java/org/eclipse/tractusx/edc/tests/KeycloakDispatcher.java @@ -17,7 +17,7 @@ * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ -package org.eclipse.tractusx.edc.token; +package org.eclipse.tractusx.edc.tests; import okhttp3.mockwebserver.Dispatcher; import okhttp3.mockwebserver.MockResponse; @@ -42,7 +42,7 @@ public KeycloakDispatcher() { @NotNull @Override - public MockResponse dispatch(@NotNull RecordedRequest recordedRequest) throws InterruptedException { + public MockResponse dispatch(@NotNull RecordedRequest recordedRequest) { if (recordedRequest.getPath().split("\\?")[0].equals(path)) { return createTokenResponse(); } diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/token/MiwDispatcher.java b/edc-tests/edc-controlplane/ssi-summarycred-tests/src/test/java/org/eclipse/tractusx/edc/tests/MiwDispatcher.java similarity index 98% rename from edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/token/MiwDispatcher.java rename to edc-tests/edc-controlplane/ssi-summarycred-tests/src/test/java/org/eclipse/tractusx/edc/tests/MiwDispatcher.java index 11bea53c9..2371ea3e9 100644 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/token/MiwDispatcher.java +++ b/edc-tests/edc-controlplane/ssi-summarycred-tests/src/test/java/org/eclipse/tractusx/edc/tests/MiwDispatcher.java @@ -17,7 +17,7 @@ * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ -package org.eclipse.tractusx.edc.token; +package org.eclipse.tractusx.edc.tests; import com.fasterxml.jackson.core.type.TypeReference; import com.nimbusds.jose.JOSEException; @@ -67,7 +67,7 @@ public MiwDispatcher(String bpn, String vcFile, String credentialSubjectId, Stri @NotNull @Override - public MockResponse dispatch(@NotNull RecordedRequest recordedRequest) throws InterruptedException { + public MockResponse dispatch(@NotNull RecordedRequest recordedRequest) { return switch (recordedRequest.getPath().split("\\?")[0]) { case "/api/credentials" -> credentialResponse(); case "/api/presentations" -> presentationResponse(); diff --git a/edc-tests/edc-controlplane/ssi-summarycred-tests/src/test/java/org/eclipse/tractusx/edc/tests/SsiParticipant.java b/edc-tests/edc-controlplane/ssi-summarycred-tests/src/test/java/org/eclipse/tractusx/edc/tests/SsiParticipant.java new file mode 100644 index 000000000..ee79d84e5 --- /dev/null +++ b/edc-tests/edc-controlplane/ssi-summarycred-tests/src/test/java/org/eclipse/tractusx/edc/tests/SsiParticipant.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.eclipse.tractusx.edc.tests; + +import java.net.URI; +import java.util.HashMap; +import java.util.Map; + +import static org.eclipse.edc.junit.testfixtures.TestUtils.getFreePort; + +public class SsiParticipant { + + private final URI miwUri = URI.create("http://localhost:" + getFreePort()); + private final URI oauthTokenUri = URI.create("http://localhost:" + getFreePort()); + + /** + * Returns the SSI configuration + */ + public Map ssiConfiguration(TxParticipant forParticipant) { + var ssiConfiguration = new HashMap() { + { + put("tx.ssi.miw.url", miwUri.toString()); + put("tx.ssi.oauth.token.url", oauthTokenUri.toString()); + put("tx.ssi.oauth.client.id", "client_id"); + put("tx.ssi.oauth.client.secret.alias", "client_secret_alias"); + put("tx.ssi.miw.authority.id", "authorityId"); + put("tx.ssi.miw.authority.issuer", "did:web:example.com"); + put("tx.vault.seed.secrets", "client_secret_alias:client_secret"); + put("tx.ssi.endpoint.audience", forParticipant.getProtocolEndpoint().getUrl().toString()); + } + }; + var baseConfiguration = forParticipant.getConfiguration(); + ssiConfiguration.putAll(baseConfiguration); + return ssiConfiguration; + } + + /** + * Returns the MIW endpoint + */ + public URI miwEndpoint() { + return miwUri; + } + + /** + * Returns the OAuth2 token endpoint + */ + public URI authTokenEndpoint() { + return oauthTokenUri; + } +} \ No newline at end of file diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/negotiation/AbstractContractNegotiateTest.java b/edc-tests/edc-controlplane/ssi-summarycred-tests/src/test/java/org/eclipse/tractusx/edc/tests/negotiation/AbstractContractNegotiateTest.java similarity index 75% rename from edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/negotiation/AbstractContractNegotiateTest.java rename to edc-tests/edc-controlplane/ssi-summarycred-tests/src/test/java/org/eclipse/tractusx/edc/tests/negotiation/AbstractContractNegotiateTest.java index df1d470f4..59a17559b 100644 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/negotiation/AbstractContractNegotiateTest.java +++ b/edc-tests/edc-controlplane/ssi-summarycred-tests/src/test/java/org/eclipse/tractusx/edc/tests/negotiation/AbstractContractNegotiateTest.java @@ -21,7 +21,8 @@ import org.eclipse.edc.connector.contract.spi.types.negotiation.ContractNegotiationStates; import org.eclipse.edc.policy.model.Operator; -import org.eclipse.tractusx.edc.lifecycle.tx.TxParticipant; +import org.eclipse.tractusx.edc.tests.SsiParticipant; +import org.eclipse.tractusx.edc.tests.TxParticipant; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -29,15 +30,15 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.awaitility.Awaitility.await; -import static org.eclipse.tractusx.edc.helpers.PolicyHelperFunctions.TX_NAMESPACE; -import static org.eclipse.tractusx.edc.helpers.PolicyHelperFunctions.bpnGroupPolicy; -import static org.eclipse.tractusx.edc.helpers.PolicyHelperFunctions.frameworkPolicy; -import static org.eclipse.tractusx.edc.lifecycle.TestRuntimeConfiguration.PLATO_BPN; -import static org.eclipse.tractusx.edc.lifecycle.TestRuntimeConfiguration.PLATO_NAME; -import static org.eclipse.tractusx.edc.lifecycle.TestRuntimeConfiguration.SOKRATES_BPN; -import static org.eclipse.tractusx.edc.lifecycle.TestRuntimeConfiguration.SOKRATES_NAME; -import static org.eclipse.tractusx.edc.tests.TestCommon.ASYNC_POLL_INTERVAL; -import static org.eclipse.tractusx.edc.tests.TestCommon.ASYNC_TIMEOUT; +import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.TX_NAMESPACE; +import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.PLATO_BPN; +import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.PLATO_NAME; +import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.SOKRATES_BPN; +import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.SOKRATES_NAME; +import static org.eclipse.tractusx.edc.tests.TxParticipant.ASYNC_POLL_INTERVAL; +import static org.eclipse.tractusx.edc.tests.TxParticipant.ASYNC_TIMEOUT; +import static org.eclipse.tractusx.edc.tests.helpers.PolicyHelperFunctions.bpnGroupPolicy; +import static org.eclipse.tractusx.edc.tests.helpers.PolicyHelperFunctions.frameworkPolicy; public abstract class AbstractContractNegotiateTest { @@ -50,6 +51,9 @@ public abstract class AbstractContractNegotiateTest { .name(PLATO_NAME) .id(PLATO_BPN) .build(); + protected static final SsiParticipant PLATO_SSI = new SsiParticipant(); + protected static final SsiParticipant SOKRATES_SSI = new SsiParticipant(); + @Test @DisplayName("Verify contract negotiation fails with wrong policy") @@ -82,10 +86,6 @@ void contractNegotiation_shouldFail_whenPolicyEvaluationFails() { .untilAsserted(() -> { var negotiationState = SOKRATES.getContractNegotiationState(negotiationId); assertThat(negotiationState).isEqualTo(ContractNegotiationStates.TERMINATED.toString()); - var error = SOKRATES.getContractNegotiationError(negotiationId); - - assertThat(error).isNotNull(); - assertThat(error).contains("Contract offer is not valid: Policy in scope contract.negotiation not fulfilled"); }); } diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/negotiation/SsiContractNegotiationInMemoryTest.java b/edc-tests/edc-controlplane/ssi-summarycred-tests/src/test/java/org/eclipse/tractusx/edc/tests/negotiation/SsiContractNegotiationInMemoryTest.java similarity index 80% rename from edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/negotiation/SsiContractNegotiationInMemoryTest.java rename to edc-tests/edc-controlplane/ssi-summarycred-tests/src/test/java/org/eclipse/tractusx/edc/tests/negotiation/SsiContractNegotiationInMemoryTest.java index 2fb8a50f2..f28900b7c 100644 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/negotiation/SsiContractNegotiationInMemoryTest.java +++ b/edc-tests/edc-controlplane/ssi-summarycred-tests/src/test/java/org/eclipse/tractusx/edc/tests/negotiation/SsiContractNegotiationInMemoryTest.java @@ -21,17 +21,18 @@ import okhttp3.mockwebserver.MockWebServer; import org.eclipse.edc.junit.annotations.EndToEndTest; -import org.eclipse.tractusx.edc.lifecycle.ParticipantRuntime; -import org.eclipse.tractusx.edc.token.KeycloakDispatcher; -import org.eclipse.tractusx.edc.token.MiwDispatcher; +import org.eclipse.tractusx.edc.tests.KeycloakDispatcher; +import org.eclipse.tractusx.edc.tests.MiwDispatcher; +import org.eclipse.tractusx.edc.tests.runtimes.ParticipantRuntime; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.extension.RegisterExtension; import java.io.IOException; -import static org.eclipse.tractusx.edc.lifecycle.TestRuntimeConfiguration.PLATO_BPN; -import static org.eclipse.tractusx.edc.lifecycle.TestRuntimeConfiguration.SOKRATES_BPN; +import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.PLATO_BPN; +import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.SOKRATES_BPN; + @EndToEndTest public class SsiContractNegotiationInMemoryTest extends AbstractContractNegotiateTest { @@ -42,7 +43,7 @@ public class SsiContractNegotiationInMemoryTest extends AbstractContractNegotiat ":edc-tests:runtime:runtime-memory-ssi", PLATO.getName(), PLATO.getBpn(), - PLATO.ssiConfiguration() + PLATO_SSI.ssiConfiguration(PLATO) ); @RegisterExtension @@ -50,7 +51,7 @@ public class SsiContractNegotiationInMemoryTest extends AbstractContractNegotiat ":edc-tests:runtime:runtime-memory-ssi", SOKRATES.getName(), SOKRATES.getBpn(), - SOKRATES.ssiConfiguration() + SOKRATES_SSI.ssiConfiguration(SOKRATES) ); private static MockWebServer miwSokratesServer; private static MockWebServer miwPlatoServer; @@ -68,16 +69,16 @@ static void setup() throws IOException { var credentialSubjectId = "did:web:example.com"; - miwSokratesServer.start(SOKRATES.miwEndpoint().getPort()); + miwSokratesServer.start(SOKRATES_SSI.miwEndpoint().getPort()); miwSokratesServer.setDispatcher(new MiwDispatcher(SOKRATES_BPN, SUMMARY_VC_TEMPLATE, credentialSubjectId, PLATO.getProtocolEndpoint().getUrl().toString())); - miwPlatoServer.start(PLATO.miwEndpoint().getPort()); + miwPlatoServer.start(PLATO_SSI.miwEndpoint().getPort()); miwPlatoServer.setDispatcher(new MiwDispatcher(PLATO_BPN, SUMMARY_VC_TEMPLATE, credentialSubjectId, SOKRATES.getProtocolEndpoint().getUrl().toString())); - sokratesOauthServer.start(SOKRATES.authTokenEndpoint().getPort()); + sokratesOauthServer.start(SOKRATES_SSI.authTokenEndpoint().getPort()); sokratesOauthServer.setDispatcher(new KeycloakDispatcher()); - platoOauthServer.start(PLATO.authTokenEndpoint().getPort()); + platoOauthServer.start(PLATO_SSI.authTokenEndpoint().getPort()); platoOauthServer.setDispatcher(new KeycloakDispatcher()); } diff --git a/edc-tests/edc-controlplane/ssi-summarycred-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/AbstractHttpConsumerPullWithProxyTest.java b/edc-tests/edc-controlplane/ssi-summarycred-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/AbstractHttpConsumerPullWithProxyTest.java new file mode 100644 index 000000000..7c77cc296 --- /dev/null +++ b/edc-tests/edc-controlplane/ssi-summarycred-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/AbstractHttpConsumerPullWithProxyTest.java @@ -0,0 +1,145 @@ +/******************************************************************************** + * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +package org.eclipse.tractusx.edc.tests.transfer; + +import jakarta.json.Json; +import jakarta.json.JsonObject; +import okhttp3.mockwebserver.MockResponse; +import okhttp3.mockwebserver.MockWebServer; +import org.eclipse.edc.connector.transfer.spi.types.TransferProcessStates; +import org.eclipse.tractusx.edc.tests.SsiParticipant; +import org.eclipse.tractusx.edc.tests.TxParticipant; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.util.Map; +import java.util.concurrent.atomic.AtomicReference; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.awaitility.Awaitility.await; +import static org.awaitility.pollinterval.FibonacciPollInterval.fibonacci; +import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.TYPE; +import static org.eclipse.edc.spi.CoreConstants.EDC_NAMESPACE; +import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.PLATO_BPN; +import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.PLATO_NAME; +import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.SOKRATES_BPN; +import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.SOKRATES_NAME; +import static org.eclipse.tractusx.edc.tests.TxParticipant.ASYNC_TIMEOUT; +import static org.eclipse.tractusx.edc.tests.helpers.PolicyHelperFunctions.bnpPolicy; + +public abstract class AbstractHttpConsumerPullWithProxyTest { + + protected static final TxParticipant SOKRATES = (TxParticipant.Builder.newInstance() + .name(SOKRATES_NAME) + .id(SOKRATES_BPN) + .build()); + + protected static final TxParticipant PLATO = (TxParticipant.Builder.newInstance() + .name(PLATO_NAME) + .id(PLATO_BPN) + .build()); + + protected static final SsiParticipant PLATO_SSI = new SsiParticipant(); + protected static final SsiParticipant SOKRATES_SSI = new SsiParticipant(); + + protected MockWebServer server; + + @BeforeEach + void setup() throws IOException { + server = new MockWebServer(); + } + + @Test + void transferData_privateBackend() throws IOException, InterruptedException { + var assetId = "api-asset-1"; + var url = server.url("/mock/api"); + server.start(); + + var authCodeHeaderName = "test-authkey"; + var authCode = "test-authcode"; + + Map dataAddress = Map.of( + "baseUrl", url.toString(), + "type", "HttpData", + "contentType", "application/json", + "authKey", authCodeHeaderName, + "authCode", authCode + ); + + PLATO.createAsset(assetId, Map.of(), dataAddress); + + var accessPolicyId = PLATO.createPolicyDefinition(createAccessPolicy(SOKRATES.getBpn())); + var contractPolicyId = PLATO.createPolicyDefinition(createContractPolicy(SOKRATES.getBpn())); + PLATO.createContractDefinition(assetId, "def-1", accessPolicyId, contractPolicyId); + var transferProcessId = SOKRATES.requestAsset(PLATO, assetId, Json.createObjectBuilder().build(), createProxyRequest(), "HttpData-PULL"); + + var contractAgreementId = new AtomicReference(); + var edr = new AtomicReference(); + + // wait until transfer process completes + await().pollInterval(fibonacci()) + .atMost(ASYNC_TIMEOUT) + .untilAsserted(() -> { + var tpState = SOKRATES.getTransferProcessState(transferProcessId); + assertThat(tpState).isNotNull().isEqualTo(TransferProcessStates.STARTED.toString()); + }); + + // wait until EDC is available on the consumer side + server.enqueue(new MockResponse().setBody("test response").setResponseCode(200)); + await().pollInterval(fibonacci()) + .atMost(ASYNC_TIMEOUT) + .untilAsserted(() -> { + edr.set(SOKRATES.edrs().getEdr(transferProcessId)); + assertThat(edr).isNotNull(); + }); + + // pull data out of provider's backend service: + // Cons-DP -> Prov-DP -> Prov-backend + assertThat(SOKRATES.data().pullData(edr.get(), Map.of())).isEqualTo("test response"); + var rq = server.takeRequest(); + assertThat(rq.getHeader(authCodeHeaderName)).isEqualTo(authCode); + assertThat(rq.getHeader("Edc-Contract-Agreement-Id")).isNotNull(); + assertThat(rq.getHeader("Edc-Bpn")).isEqualTo(SOKRATES.getBpn()); + assertThat(rq.getMethod()).isEqualToIgnoringCase("GET"); + } + + @AfterEach + void teardown() throws IOException { + server.shutdown(); + } + + protected JsonObject createAccessPolicy(String bpn) { + return bnpPolicy(bpn); + } + + protected JsonObject createContractPolicy(String bpn) { + return bnpPolicy(bpn); + } + + private JsonObject createProxyRequest() { + return Json.createObjectBuilder() + .add(TYPE, EDC_NAMESPACE + "DataAddress") + .add(EDC_NAMESPACE + "type", "HttpProxy") + .build(); + + } +} diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/SsiHttpConsumerPullWithProxyInMemoryTest.java b/edc-tests/edc-controlplane/ssi-summarycred-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/SsiHttpConsumerPullWithProxyInMemoryTest.java similarity index 77% rename from edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/SsiHttpConsumerPullWithProxyInMemoryTest.java rename to edc-tests/edc-controlplane/ssi-summarycred-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/SsiHttpConsumerPullWithProxyInMemoryTest.java index ea0990363..db071c67a 100644 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/SsiHttpConsumerPullWithProxyInMemoryTest.java +++ b/edc-tests/edc-controlplane/ssi-summarycred-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/SsiHttpConsumerPullWithProxyInMemoryTest.java @@ -22,21 +22,21 @@ import jakarta.json.JsonObject; import okhttp3.mockwebserver.MockWebServer; import org.eclipse.edc.junit.annotations.EndToEndTest; -import org.eclipse.tractusx.edc.lifecycle.ParticipantRuntime; -import org.eclipse.tractusx.edc.token.KeycloakDispatcher; -import org.eclipse.tractusx.edc.token.MiwDispatcher; +import org.eclipse.tractusx.edc.tests.KeycloakDispatcher; +import org.eclipse.tractusx.edc.tests.MiwDispatcher; +import org.eclipse.tractusx.edc.tests.runtimes.ParticipantRuntime; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.extension.RegisterExtension; import java.io.IOException; import java.util.Map; -import static org.eclipse.tractusx.edc.helpers.PolicyHelperFunctions.TX_NAMESPACE; -import static org.eclipse.tractusx.edc.helpers.PolicyHelperFunctions.frameworkPolicy; -import static org.eclipse.tractusx.edc.lifecycle.TestRuntimeConfiguration.PLATO_BPN; -import static org.eclipse.tractusx.edc.lifecycle.TestRuntimeConfiguration.SOKRATES_BPN; +import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.TX_NAMESPACE; +import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.PLATO_BPN; +import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.SOKRATES_BPN; +import static org.eclipse.tractusx.edc.tests.helpers.PolicyHelperFunctions.frameworkPolicy; + @EndToEndTest public class SsiHttpConsumerPullWithProxyInMemoryTest extends AbstractHttpConsumerPullWithProxyTest { @@ -47,14 +47,14 @@ public class SsiHttpConsumerPullWithProxyInMemoryTest extends AbstractHttpConsum ":edc-tests:runtime:runtime-memory-ssi", SOKRATES.getName(), SOKRATES.getBpn(), - SOKRATES.ssiConfiguration() + SOKRATES_SSI.ssiConfiguration(SOKRATES) ); @RegisterExtension protected static final ParticipantRuntime PLATO_RUNTIME = new ParticipantRuntime( ":edc-tests:runtime:runtime-memory-ssi", PLATO.getName(), PLATO.getBpn(), - PLATO.ssiConfiguration() + PLATO_SSI.ssiConfiguration(PLATO) ); private static MockWebServer sokratesOauthServer; @@ -71,16 +71,16 @@ static void prepare() throws IOException { var credentialSubjectId = "did:web:example.com"; - miwSokratesServer.start(SOKRATES.miwEndpoint().getPort()); + miwSokratesServer.start(SOKRATES_SSI.miwEndpoint().getPort()); miwSokratesServer.setDispatcher(new MiwDispatcher(SOKRATES_BPN, SUMMARY_VC_TEMPLATE, credentialSubjectId, PLATO.getProtocolEndpoint().getUrl().toString())); - miwPlatoServer.start(PLATO.miwEndpoint().getPort()); + miwPlatoServer.start(PLATO_SSI.miwEndpoint().getPort()); miwPlatoServer.setDispatcher(new MiwDispatcher(PLATO_BPN, SUMMARY_VC_TEMPLATE, credentialSubjectId, SOKRATES.getProtocolEndpoint().getUrl().toString())); - sokratesOauthServer.start(SOKRATES.authTokenEndpoint().getPort()); + sokratesOauthServer.start(SOKRATES_SSI.authTokenEndpoint().getPort()); sokratesOauthServer.setDispatcher(new KeycloakDispatcher()); - platoOauthServer.start(PLATO.authTokenEndpoint().getPort()); + platoOauthServer.start(PLATO_SSI.authTokenEndpoint().getPort()); platoOauthServer.setDispatcher(new KeycloakDispatcher()); } @@ -92,12 +92,6 @@ static void unwind() throws IOException { platoOauthServer.shutdown(); } - @BeforeEach - void setup() throws IOException { - super.setup(); - - } - @Override protected JsonObject createAccessPolicy(String bpn) { return frameworkPolicy(Map.of(TX_NAMESPACE + "Dismantler", "active")); diff --git a/edc-tests/edc-controlplane/ssi-summarycred-tests/src/test/resources/framework-policy.json b/edc-tests/edc-controlplane/ssi-summarycred-tests/src/test/resources/framework-policy.json new file mode 100644 index 000000000..321aecbe5 --- /dev/null +++ b/edc-tests/edc-controlplane/ssi-summarycred-tests/src/test/resources/framework-policy.json @@ -0,0 +1,24 @@ +{ + "@context": [ + "https://w3id.org/edc/v0.0.1", + "https://w3id.org/tractusx/edc/v0.0.1", + "http://www.w3.org/ns/odrl.jsonld" + ], + "@type": "PolicyDefinitionRequest", + "@id": "${POLICY_ID}", + "policy": { + "@type": "Set", + "permission": [ + { + "action": "use", + "constraint": [ + { + "leftOperand": "${FRAMEWORK_CREDENTIAL}", + "operator": "eq", + "rightOperand": "active" + } + ] + } + ] + } +} diff --git a/edc-tests/edc-controlplane/ssi-summarycred-tests/src/test/resources/summary-vc-no-dismantler.json b/edc-tests/edc-controlplane/ssi-summarycred-tests/src/test/resources/summary-vc-no-dismantler.json new file mode 100644 index 000000000..750648f04 --- /dev/null +++ b/edc-tests/edc-controlplane/ssi-summarycred-tests/src/test/resources/summary-vc-no-dismantler.json @@ -0,0 +1,37 @@ +{ + "@context": [ + "https://www.w3.org/2018/credentials/v1", + "https://w3id.org/2023/catenax/credentials/summary/v1" + ], + "id": "urn:uuid:12345678-1234-1234-1234-123456789abc", + "type": [ + "VerifiableCredential", + "SummaryCredential" + ], + "issuer": "did:web:example.com", + "issuanceDate": "2023-06-02T12:00:00Z", + "expirationDate": "2022-06-16T18:56:59Z", + "credentialSubject": { + "id": "did:web:example.com", + "holderIdentifier": "%s", + "type": "Summary-List", + "name": "CX-Credentials", + "items": [ + "MembershipCredential", + "PcfCredential", + "SustainabilityCredential", + "QualityCredential", + "TraceabilityCredential", + "BehaviorTwinCredential", + "BpnCredential" + ], + "contractTemplates": "https://public.catena-x.org/contracts/" + }, + "proof": { + "type": "Ed25519Signature2018", + "created": "2023-06-02T12:00:00Z", + "proofPurpose": "assertionMethod", + "verificationMethod": "did:web:example.com#key-1", + "jws": "xxxx" + } +} \ No newline at end of file diff --git a/edc-tests/edc-controlplane/ssi-summarycred-tests/src/test/resources/summary-vc.json b/edc-tests/edc-controlplane/ssi-summarycred-tests/src/test/resources/summary-vc.json new file mode 100644 index 000000000..01c640a70 --- /dev/null +++ b/edc-tests/edc-controlplane/ssi-summarycred-tests/src/test/resources/summary-vc.json @@ -0,0 +1,38 @@ +{ + "@context": [ + "https://www.w3.org/2018/credentials/v1", + "https://w3id.org/2023/catenax/credentials/summary/v1" + ], + "id": "urn:uuid:12345678-1234-1234-1234-123456789abc", + "type": [ + "VerifiableCredential", + "SummaryCredential" + ], + "issuer": "did:web:example.com", + "issuanceDate": "2023-06-02T12:00:00Z", + "expirationDate": "2022-06-16T18:56:59Z", + "credentialSubject": { + "id": "did:web:example.com", + "holderIdentifier": "%s", + "type": "Summary-List", + "name": "CX-Credentials", + "items": [ + "MembershipCredential", + "DismantlerCredential", + "PcfCredential", + "SustainabilityCredential", + "QualityCredential", + "TraceabilityCredential", + "BehaviorTwinCredential", + "BpnCredential" + ], + "contractTemplates": "https://public.catena-x.org/contracts/" + }, + "proof": { + "type": "Ed25519Signature2018", + "created": "2023-06-02T12:00:00Z", + "proofPurpose": "assertionMethod", + "verificationMethod": "did:web:example.com#key-1", + "jws": "xxxx" + } +} \ No newline at end of file diff --git a/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-api/build.gradle.kts b/edc-tests/edc-controlplane/transfer-tests/build.gradle.kts similarity index 67% rename from edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-api/build.gradle.kts rename to edc-tests/edc-controlplane/transfer-tests/build.gradle.kts index cfaa05daa..d0de250c2 100644 --- a/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-provider-api/build.gradle.kts +++ b/edc-tests/edc-controlplane/transfer-tests/build.gradle.kts @@ -19,25 +19,20 @@ plugins { `java-library` - id("io.swagger.core.v3.swagger-gradle-plugin") + `java-test-fixtures` } dependencies { + testImplementation(testFixtures(project(":edc-tests:edc-controlplane:fixtures"))) - implementation(libs.edc.spi.http) - implementation(libs.edc.util) - implementation(libs.edc.dpf.util) - implementation(libs.edc.ext.http) - implementation(libs.edc.spi.jwt) - implementation(libs.edc.token.core) - implementation(libs.edc.spi.dataplane.http) - - implementation(libs.jakarta.rsApi) - implementation(libs.nimbus.jwt) - - implementation(project(":edc-extensions:dataplane:dataplane-proxy:edc-dataplane-proxy-provider-spi")) - + testImplementation(libs.netty.mockserver) testImplementation(libs.edc.junit) + testImplementation(libs.restAssured) + testImplementation(libs.awaitility) testImplementation(libs.okhttp.mockwebserver) } +// do not publish +edcBuild { + publish.set(false) +} diff --git a/edc-tests/edc-controlplane/transfer-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/AbstractHttpConsumerPullWithProxyTest.java b/edc-tests/edc-controlplane/transfer-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/AbstractHttpConsumerPullWithProxyTest.java new file mode 100644 index 000000000..73b2063ff --- /dev/null +++ b/edc-tests/edc-controlplane/transfer-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/AbstractHttpConsumerPullWithProxyTest.java @@ -0,0 +1,127 @@ +/******************************************************************************** + * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +package org.eclipse.tractusx.edc.tests.transfer; + +import jakarta.json.Json; +import jakarta.json.JsonObject; +import okhttp3.mockwebserver.MockResponse; +import okhttp3.mockwebserver.MockWebServer; +import org.eclipse.edc.connector.transfer.spi.types.TransferProcessStates; +import org.eclipse.tractusx.edc.tests.TxParticipant; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.util.Map; +import java.util.concurrent.atomic.AtomicReference; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.awaitility.Awaitility.await; +import static org.awaitility.pollinterval.FibonacciPollInterval.fibonacci; +import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.PLATO_BPN; +import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.PLATO_NAME; +import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.SOKRATES_BPN; +import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.SOKRATES_NAME; +import static org.eclipse.tractusx.edc.tests.TxParticipant.ASYNC_TIMEOUT; +import static org.eclipse.tractusx.edc.tests.helpers.PolicyHelperFunctions.bnpPolicy; +import static org.eclipse.tractusx.edc.tests.transfer.TransferProcessHelperFunctions.createProxyRequest; + +public abstract class AbstractHttpConsumerPullWithProxyTest { + + protected static final TxParticipant SOKRATES = TxParticipant.Builder.newInstance() + .name(SOKRATES_NAME) + .id(SOKRATES_BPN) + .build(); + + protected static final TxParticipant PLATO = TxParticipant.Builder.newInstance() + .name(PLATO_NAME) + .id(PLATO_BPN) + .build(); + + protected MockWebServer server; + + @BeforeEach + void setup() throws IOException { + server = new MockWebServer(); + } + + @Test + void transferData_privateBackend() throws IOException, InterruptedException { + var assetId = "api-asset-1"; + var url = server.url("/mock/api"); + server.start(); + + + Map dataAddress = Map.of( + "baseUrl", url.toString(), + "type", "HttpData", + "contentType", "application/json" + ); + + PLATO.createAsset(assetId, Map.of(), dataAddress); + + var accessPolicyId = PLATO.createPolicyDefinition(createAccessPolicy(SOKRATES.getBpn())); + var contractPolicyId = PLATO.createPolicyDefinition(createContractPolicy(SOKRATES.getBpn())); + PLATO.createContractDefinition(assetId, "def-1", accessPolicyId, contractPolicyId); + var transferProcessId = SOKRATES.requestAsset(PLATO, assetId, Json.createObjectBuilder().build(), createProxyRequest()); + + var contractAgreementId = new AtomicReference(); + var edr = new AtomicReference(); + + // wait until transfer process completes + await().pollInterval(fibonacci()) + .atMost(ASYNC_TIMEOUT) + .untilAsserted(() -> { + var tpState = SOKRATES.getTransferProcessState(transferProcessId); + assertThat(tpState).isNotNull().isEqualTo(TransferProcessStates.STARTED.toString()); + }); + + // wait until EDC is available on the consumer side + server.enqueue(new MockResponse().setBody("test response").setResponseCode(200)); + await().pollInterval(fibonacci()) + .atMost(ASYNC_TIMEOUT) + .untilAsserted(() -> { + edr.set(SOKRATES.edrs().getEdr(transferProcessId)); + assertThat(edr).isNotNull(); + }); + + // pull data out of provider's backend service: + // Prov-DP -> Prov-backend + assertThat(SOKRATES.data().pullData(edr.get(), Map.of())).isEqualTo("test response"); + var rq = server.takeRequest(); + assertThat(rq.getHeader("Edc-Contract-Agreement-Id")).isNotNull(); + assertThat(rq.getHeader("Edc-Bpn")).isEqualTo(SOKRATES.getBpn()); + assertThat(rq.getMethod()).isEqualToIgnoringCase("GET"); + } + + @AfterEach + void teardown() throws IOException { + server.shutdown(); + } + + protected JsonObject createAccessPolicy(String bpn) { + return bnpPolicy(bpn); + } + + protected JsonObject createContractPolicy(String bpn) { + return bnpPolicy(bpn); + } +} diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/AbstractHttpProviderPushTest.java b/edc-tests/edc-controlplane/transfer-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/AbstractHttpProviderPushTest.java similarity index 87% rename from edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/AbstractHttpProviderPushTest.java rename to edc-tests/edc-controlplane/transfer-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/AbstractHttpProviderPushTest.java index 623d52256..3be0fbbf0 100644 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/AbstractHttpProviderPushTest.java +++ b/edc-tests/edc-controlplane/transfer-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/AbstractHttpProviderPushTest.java @@ -24,7 +24,7 @@ import okhttp3.mockwebserver.MockResponse; import okhttp3.mockwebserver.MockWebServer; import okhttp3.mockwebserver.RecordedRequest; -import org.eclipse.tractusx.edc.lifecycle.tx.TxParticipant; +import org.eclipse.tractusx.edc.tests.TxParticipant; import org.jetbrains.annotations.NotNull; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; @@ -40,12 +40,12 @@ import static org.eclipse.edc.connector.transfer.spi.types.TransferProcessStates.COMPLETED; import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.TYPE; import static org.eclipse.edc.spi.CoreConstants.EDC_NAMESPACE; -import static org.eclipse.tractusx.edc.helpers.PolicyHelperFunctions.bnpPolicy; -import static org.eclipse.tractusx.edc.lifecycle.TestRuntimeConfiguration.PLATO_BPN; -import static org.eclipse.tractusx.edc.lifecycle.TestRuntimeConfiguration.PLATO_NAME; -import static org.eclipse.tractusx.edc.lifecycle.TestRuntimeConfiguration.SOKRATES_BPN; -import static org.eclipse.tractusx.edc.lifecycle.TestRuntimeConfiguration.SOKRATES_NAME; -import static org.eclipse.tractusx.edc.tests.TestCommon.ASYNC_TIMEOUT; +import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.PLATO_BPN; +import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.PLATO_NAME; +import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.SOKRATES_BPN; +import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.SOKRATES_NAME; +import static org.eclipse.tractusx.edc.tests.TxParticipant.ASYNC_TIMEOUT; +import static org.eclipse.tractusx.edc.tests.helpers.PolicyHelperFunctions.bnpPolicy; public abstract class AbstractHttpProviderPushTest { @@ -100,7 +100,7 @@ public MockResponse dispatch(@NotNull RecordedRequest recordedRequest) throws In var destination = httpDataAddress(consumerUrl.toString()); - var transferProcessId = SOKRATES.requestAsset(PLATO, assetId, createObjectBuilder().build(), destination); + var transferProcessId = SOKRATES.requestAsset(PLATO, assetId, createObjectBuilder().build(), destination, "HttpData-PUSH"); await().atMost(ASYNC_TIMEOUT).untilAsserted(() -> { var state = SOKRATES.getTransferProcessState(transferProcessId); assertThat(state).isEqualTo(COMPLETED.name()); diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/HttpConsumerPullWithProxyInMemoryTest.java b/edc-tests/edc-controlplane/transfer-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/HttpConsumerPullWithProxyInMemoryTest.java similarity index 97% rename from edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/HttpConsumerPullWithProxyInMemoryTest.java rename to edc-tests/edc-controlplane/transfer-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/HttpConsumerPullWithProxyInMemoryTest.java index 5f3f0d791..e86b25f23 100644 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/HttpConsumerPullWithProxyInMemoryTest.java +++ b/edc-tests/edc-controlplane/transfer-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/HttpConsumerPullWithProxyInMemoryTest.java @@ -22,7 +22,7 @@ import com.nimbusds.jose.util.Base64; import org.eclipse.edc.junit.annotations.EndToEndTest; import org.eclipse.edc.spi.security.Vault; -import org.eclipse.tractusx.edc.lifecycle.ParticipantRuntime; +import org.eclipse.tractusx.edc.tests.runtimes.ParticipantRuntime; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.extension.RegisterExtension; diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/HttpConsumerPullWithProxyPostgresqlTest.java b/edc-tests/edc-controlplane/transfer-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/HttpConsumerPullWithProxyPostgresqlTest.java similarity index 96% rename from edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/HttpConsumerPullWithProxyPostgresqlTest.java rename to edc-tests/edc-controlplane/transfer-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/HttpConsumerPullWithProxyPostgresqlTest.java index 14b76e8be..d1002cbd8 100644 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/HttpConsumerPullWithProxyPostgresqlTest.java +++ b/edc-tests/edc-controlplane/transfer-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/HttpConsumerPullWithProxyPostgresqlTest.java @@ -20,7 +20,7 @@ package org.eclipse.tractusx.edc.tests.transfer; import org.eclipse.edc.junit.annotations.PostgresqlIntegrationTest; -import org.eclipse.tractusx.edc.lifecycle.PgParticipantRuntime; +import org.eclipse.tractusx.edc.tests.runtimes.PgParticipantRuntime; import org.junit.jupiter.api.extension.RegisterExtension; @PostgresqlIntegrationTest diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/HttpProviderPushInMemoryTest.java b/edc-tests/edc-controlplane/transfer-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/HttpProviderPushInMemoryTest.java similarity index 96% rename from edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/HttpProviderPushInMemoryTest.java rename to edc-tests/edc-controlplane/transfer-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/HttpProviderPushInMemoryTest.java index 037e189b7..dd481bd53 100644 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/HttpProviderPushInMemoryTest.java +++ b/edc-tests/edc-controlplane/transfer-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/HttpProviderPushInMemoryTest.java @@ -20,7 +20,7 @@ package org.eclipse.tractusx.edc.tests.transfer; import org.eclipse.edc.junit.annotations.EndToEndTest; -import org.eclipse.tractusx.edc.lifecycle.ParticipantRuntime; +import org.eclipse.tractusx.edc.tests.runtimes.ParticipantRuntime; import org.junit.jupiter.api.extension.RegisterExtension; @EndToEndTest diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/HttpProviderPushInPostgresqlTest.java b/edc-tests/edc-controlplane/transfer-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/HttpProviderPushInPostgresqlTest.java similarity index 96% rename from edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/HttpProviderPushInPostgresqlTest.java rename to edc-tests/edc-controlplane/transfer-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/HttpProviderPushInPostgresqlTest.java index 11f9a454e..79bd34a2d 100644 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/HttpProviderPushInPostgresqlTest.java +++ b/edc-tests/edc-controlplane/transfer-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/HttpProviderPushInPostgresqlTest.java @@ -20,7 +20,7 @@ package org.eclipse.tractusx.edc.tests.transfer; import org.eclipse.edc.junit.annotations.PostgresqlIntegrationTest; -import org.eclipse.tractusx.edc.lifecycle.PgParticipantRuntime; +import org.eclipse.tractusx.edc.tests.runtimes.PgParticipantRuntime; import org.junit.jupiter.api.extension.RegisterExtension; @PostgresqlIntegrationTest diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/helpers/AssetHelperFunctions.java b/edc-tests/edc-controlplane/transfer-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/TransferProcessHelperFunctions.java similarity index 57% rename from edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/helpers/AssetHelperFunctions.java rename to edc-tests/edc-controlplane/transfer-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/TransferProcessHelperFunctions.java index e9b1224fb..da83d3143 100644 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/helpers/AssetHelperFunctions.java +++ b/edc-tests/edc-controlplane/transfer-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/TransferProcessHelperFunctions.java @@ -17,44 +17,38 @@ * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ -package org.eclipse.tractusx.edc.helpers; +package org.eclipse.tractusx.edc.tests.transfer; import jakarta.json.Json; import jakarta.json.JsonObject; -import jakarta.json.JsonObjectBuilder; -import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.CONTEXT; import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.ID; import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.TYPE; import static org.eclipse.edc.spi.CoreConstants.EDC_NAMESPACE; -import static org.eclipse.edc.spi.CoreConstants.EDC_PREFIX; -public class AssetHelperFunctions { +public class TransferProcessHelperFunctions { - /** - * Creates an asset with the given ID and props using the participant's Data Management API - */ - public static JsonObject createAsset(String id, JsonObject assetProperties, JsonObject dataAddress) { + public static JsonObject createTransferRequest(String dataRequestId, String counterPartyAddress, String contractId, String assetId, boolean managedResources, JsonObject destination) { return Json.createObjectBuilder() - .add(CONTEXT, createContextBuilder()) - .add(TYPE, "Asset") - .add(ID, id) - .add(EDC_NAMESPACE + "properties", assetProperties) - .add(EDC_NAMESPACE + "dataAddress", dataAddress) + .add(TYPE, EDC_NAMESPACE + "TransferRequestDto") + .add(ID, dataRequestId) + .add(EDC_NAMESPACE + "connectorId", "connectorId") + .add(EDC_NAMESPACE + "dataDestination", destination) + .add(EDC_NAMESPACE + "protocol", "dataspace-protocol-http") + .add(EDC_NAMESPACE + "assetId", assetId) + .add(EDC_NAMESPACE + "contractId", contractId) + .add(EDC_NAMESPACE + "counterPartyAddress", counterPartyAddress) + .add(EDC_NAMESPACE + "managedResources", managedResources) .build(); - } - public static JsonObjectBuilder createDataAddressBuilder(String type) { + + public static JsonObject createProxyRequest() { return Json.createObjectBuilder() .add(TYPE, EDC_NAMESPACE + "DataAddress") - .add(EDC_NAMESPACE + "type", type); - } + .add(EDC_NAMESPACE + "type", "HttpProxy-PULL") + .build(); - public static JsonObjectBuilder createContextBuilder() { - return Json.createObjectBuilder() - .add(EDC_PREFIX, EDC_NAMESPACE); } - } diff --git a/edc-tests/edc-dataplane/edc-dataplane-proxy-e2e/build.gradle.kts b/edc-tests/edc-dataplane/edc-dataplane-proxy-e2e/build.gradle.kts deleted file mode 100644 index 94280497f..000000000 --- a/edc-tests/edc-dataplane/edc-dataplane-proxy-e2e/build.gradle.kts +++ /dev/null @@ -1,44 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -plugins { - `java-library` -} - -dependencies { - testImplementation(libs.edc.junit) - testImplementation(libs.restAssured) - testImplementation(libs.okhttp.mockwebserver) - - // test runtime config - testImplementation(libs.edc.config.filesystem) - testImplementation(libs.edc.dpf.http) - testImplementation(libs.edc.auth.tokenbased) - testRuntimeOnly(libs.edc.dpf.core) - testRuntimeOnly(libs.edc.controlplane.apiclient) - testImplementation(project(":spi:edr-spi")) - testImplementation(project(":core:edr-cache-core")) - testImplementation(project(":edc-extensions:dataplane:dataplane-proxy:edc-dataplane-proxy-consumer-api")) - testImplementation(project(":edc-extensions:dataplane:dataplane-proxy:edc-dataplane-proxy-provider-api")) - testImplementation(project(":edc-extensions:dataplane:dataplane-proxy:edc-dataplane-proxy-provider-core")) - -} - - - diff --git a/edc-tests/edc-dataplane/edc-dataplane-proxy-e2e/src/test/java/org/eclipse/tractusx/edc/dataplane/proxy/e2e/DpfProxyEndToEndTest.java b/edc-tests/edc-dataplane/edc-dataplane-proxy-e2e/src/test/java/org/eclipse/tractusx/edc/dataplane/proxy/e2e/DpfProxyEndToEndTest.java deleted file mode 100644 index d98c663c2..000000000 --- a/edc-tests/edc-dataplane/edc-dataplane-proxy-e2e/src/test/java/org/eclipse/tractusx/edc/dataplane/proxy/e2e/DpfProxyEndToEndTest.java +++ /dev/null @@ -1,209 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.dataplane.proxy.e2e; - -import io.restassured.specification.RequestSpecification; -import okhttp3.mockwebserver.MockResponse; -import okhttp3.mockwebserver.MockWebServer; -import org.eclipse.edc.connector.dataplane.http.spi.HttpDataAddress; -import org.eclipse.edc.junit.annotations.EndToEndTest; -import org.eclipse.edc.junit.extensions.EdcRuntimeExtension; -import org.eclipse.edc.spi.types.TypeManager; -import org.eclipse.tractusx.edc.edr.spi.store.EndpointDataReferenceCache; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.RegisterExtension; - -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; - -import static io.restassured.RestAssured.given; -import static java.lang.String.format; -import static java.lang.String.valueOf; -import static org.eclipse.edc.junit.testfixtures.TestUtils.getFreePort; -import static org.eclipse.tractusx.edc.dataplane.proxy.e2e.EdrCacheSetup.createEntries; -import static org.eclipse.tractusx.edc.dataplane.proxy.e2e.KeyStoreSetup.createKeyStore; -import static org.hamcrest.Matchers.is; - - -/** - * Performs end-to-end testing using a consumer data plane, a producer data plane, and a proxied HTTP endpoint. - *

    - * The consumer runtime is configured with three EDRs: - *

      - *
    • One EDR is for the {@link #SINGLE_TRANSFER_ID} transfer process that is associated with a single contract agreement for the {@link #SINGLE_ASSET_ID} - * asset
    • - *
    • Two EDRs for transfer processes that are associated with contract agreements for the same asset, {@link #MULTI_ASSET_ID}
    • - *
    - *

    - * The end-to-end tests verify asset content is correctly proxied from the HTTP endpoint, error messages from the HTTP endpoint are correctly propagated, - * and invalid requests are properly handled. - *

    - * This test can be executed using the Gradle or JUnit test runners. - */ -@EndToEndTest -public class DpfProxyEndToEndTest { - - public static final String KEYSTORE_PASS = "test123"; - private static final String LAUNCHER_MODULE = ":edc-tests:edc-dataplane:edc-dataplane-proxy-e2e"; - private static final int CONSUMER_HTTP_PORT = getFreePort(); - private static final int CONSUMER_PROXY_PORT = getFreePort(); - private static final int PRODUCER_HTTP_PORT = getFreePort(); - private static final int MOCK_ENDPOINT_PORT = getFreePort(); - - private static final int VALIDATION_ENDPOINT_PORT = getFreePort(); - - private static final String PROXY_SUBPATH = "proxy/aas/request"; - private static final String SINGLE_TRANSFER_ID = "5355d524-2616-43df-9096-558afffff659"; - private static final String SINGLE_ASSET_ID = "79f13b89-59a6-4278-8c8e-8540849dbab8"; - private static final String MULTI_ASSET_ID = "9260f395-3d94-4b8b-bdaa-941ead596ce5"; - private static final String REQUEST_TEMPLATE_TP = "{\"transferProcessId\": \"%s\", \"endpointUrl\" : \"http://localhost:%s/api/gateway/aas/test\"}"; - private static final String REQUEST_TEMPLATE_ASSET = "{\"assetId\": \"%s\", \"endpointUrl\" : \"http://localhost:%s/api/gateway/aas/test\"}"; - private static final String MOCK_ENDPOINT_200_BODY = "{\"message\":\"test\"}"; - private static final String API_KEY = "testkey"; - - @RegisterExtension - static EdcRuntimeExtension consumer = new EdcRuntimeExtension( - LAUNCHER_MODULE, - "consumer", - baseConfig(Map.of( - "web.http.port", valueOf(CONSUMER_HTTP_PORT), - "edc.api.auth.key", API_KEY, - "tx.dpf.consumer.proxy.port", valueOf(CONSUMER_PROXY_PORT) - ))); - @RegisterExtension - static EdcRuntimeExtension provider = new EdcRuntimeExtension( - LAUNCHER_MODULE, - "provider", - baseConfig(Map.of( - "web.http.port", valueOf(PRODUCER_HTTP_PORT), - "tx.dpf.proxy.gateway.aas.proxied.path", "http://localhost:" + MOCK_ENDPOINT_PORT - ))); - private static MockWebServer mockEndpoint = new MockWebServer(); - private static MockWebServer mockValidationEndpoint = new MockWebServer(); - private final TypeManager typeManager = new TypeManager(); - - @Test - void verify_end2EndFlows() throws IOException { - - seedEdrCache(); - - var dataAddress = HttpDataAddress.Builder.newInstance().baseUrl("http://localhost:" + MOCK_ENDPOINT_PORT).build(); - - mockValidationEndpoint.start(VALIDATION_ENDPOINT_PORT); - mockValidationEndpoint.enqueue(new MockResponse().setBody(typeManager.writeValueAsString(dataAddress))); - mockValidationEndpoint.enqueue(new MockResponse().setBody(typeManager.writeValueAsString(dataAddress))); - mockValidationEndpoint.enqueue(new MockResponse().setBody(typeManager.writeValueAsString(dataAddress))); - mockValidationEndpoint.enqueue(new MockResponse().setBody(typeManager.writeValueAsString(dataAddress))); - - // set up the HTTP endpoint - mockEndpoint.enqueue(new MockResponse().setBody(MOCK_ENDPOINT_200_BODY)); - mockEndpoint.enqueue(new MockResponse().setBody(MOCK_ENDPOINT_200_BODY)); - mockEndpoint.enqueue(new MockResponse().setResponseCode(404)); - mockEndpoint.enqueue(new MockResponse().setResponseCode(401)); - mockEndpoint.start(MOCK_ENDPOINT_PORT); - - var tpSpec = createSpecification(format(REQUEST_TEMPLATE_TP, SINGLE_TRANSFER_ID, PRODUCER_HTTP_PORT)); - - // verify content successfully proxied using a transfer process id - var rs = tpSpec.with() - .post(PROXY_SUBPATH) - .then() - .log().ifError() - .assertThat().statusCode(200) - .body(is(MOCK_ENDPOINT_200_BODY)); - - var str = rs.extract().body().asString(); - - // verify content successfully proxied using an asset id for the case where only one active transfer process exists for the asset - var assetSpec = createSpecification(format(REQUEST_TEMPLATE_ASSET, SINGLE_ASSET_ID, PRODUCER_HTTP_PORT)); - assetSpec.with() - .post(PROXY_SUBPATH) - .then() - .assertThat().statusCode(200) - .assertThat().body(is(MOCK_ENDPOINT_200_BODY)); - - // verify content not found (404) response at the endpoint is propagated - tpSpec.with() - .post(PROXY_SUBPATH) - .then() - .assertThat().statusCode(404); - - // verify unauthorized response (403) at the endpoint is propagated - tpSpec.with() - .post(PROXY_SUBPATH) - .then() - .assertThat().statusCode(401); - - // verify EDR not found results in a bad request response (400) - var invalidSpec = createSpecification(format(REQUEST_TEMPLATE_TP, "123", PRODUCER_HTTP_PORT)); - invalidSpec.with() - .post(PROXY_SUBPATH) - .then() - .assertThat().statusCode(400); - - // verify more than one contract for the same asset results in a precondition required response (428) - var multiAssetSpec = createSpecification(format(REQUEST_TEMPLATE_ASSET, MULTI_ASSET_ID, PRODUCER_HTTP_PORT)); - multiAssetSpec.with() - .post(PROXY_SUBPATH) - .then() - .assertThat().statusCode(428); - } - - private static Map baseConfig(Map values) { - var map = new HashMap<>(values); - map.put("edc.keystore", createKeyStore(KEYSTORE_PASS)); - map.put("edc.keystore.password", KEYSTORE_PASS); - map.put("edc.dataplane.token.validation.endpoint", "http://localhost:" + VALIDATION_ENDPOINT_PORT); - return map; - } - - private RequestSpecification createSpecification(String body) { - return given() - .baseUri("http://localhost:" + CONSUMER_PROXY_PORT) - .contentType("application/json") - .header("x-api-key", API_KEY) - .body(body); - } - - /** - * Loads the EDR cache. - */ - private void seedEdrCache() { - var edrCache = consumer.getContext().getService(EndpointDataReferenceCache.class); - createEntries().forEach(e -> edrCache.save(e.getEdrEntry(), e.getEdr())); - } - - @AfterAll - static void tearDown() throws IOException { - mockEndpoint.shutdown(); - mockValidationEndpoint.shutdown(); - } - - @BeforeAll - static void setUp() { - mockEndpoint = new MockWebServer(); - mockValidationEndpoint = new MockWebServer(); - } - - -} diff --git a/edc-tests/edc-dataplane/edc-dataplane-proxy-e2e/src/test/java/org/eclipse/tractusx/edc/dataplane/proxy/e2e/EdrCacheSetup.java b/edc-tests/edc-dataplane/edc-dataplane-proxy-e2e/src/test/java/org/eclipse/tractusx/edc/dataplane/proxy/e2e/EdrCacheSetup.java deleted file mode 100644 index 3fcb83976..000000000 --- a/edc-tests/edc-dataplane/edc-dataplane-proxy-e2e/src/test/java/org/eclipse/tractusx/edc/dataplane/proxy/e2e/EdrCacheSetup.java +++ /dev/null @@ -1,110 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.dataplane.proxy.e2e; - -import org.eclipse.edc.spi.types.domain.edr.EndpointDataReference; -import org.eclipse.tractusx.edc.edr.core.defaults.PersistentCacheEntry; -import org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntry; - -import java.util.ArrayList; -import java.util.List; - -/** - * Creates test EDR cache entries. - */ -public class EdrCacheSetup { - - public static final String AUTHENTICATION = "authentication"; - public static final String ENDPOINT = "http://test.com"; - - private static String generateAuthCode() { - //noinspection StringBufferReplaceableByString - return new StringBuilder() - .append("eyJhbGciOiJSUzI1NiIsInZlcn") - .append("Npb24iOnRydWV9.") - .append("eyJpc3MiOiJ0ZXN0LWNvb") - .append("m5lY3RvciIsInN1YiI6ImNvbnN1bW") - .append("VyLWNvbm5lY3RvciIsImF1ZCI6InRlc3Q") - .append("tY29ubmVjdG9yIiwi") - .append("aWF0IjoxNjgxOTEzN") - .append("jM2LCJleHAiOjMzNDU5NzQwNzg4LCJjaWQiOiIzMmE2M") - .append("2E3ZC04MGQ2LTRmMmUtOTBlN") - .append("i04MGJhZjVmYzJiM2MifQ.QAuotoRxpEqfuzkTcTq2w5Tcyy") - .append("3Rc3UzUjjvNc_zwgNROGLe-wO") - .append("9tFET1dJ_I5BttRxkngDS37dS4R6lN5YXaGHgcH2rf_FuVcJUS") - .append("FqTp_usGAcx6m7pQQwqpNdcYgmq0NJp3xP87EFP") - .append("HAy4kBxB5bqpmx4J-zrj9U_gerZ2WlRqpu0SdgP0S5v5D1Gm-v") - .append("YkLqgvsugrAWH3Ti7OjC5UMdj0kDFwro2NpMY8SSNryiVvBEv8hn0KZdhhebIqPd") - .append("hqbEQZ9d8WKzcgoqQ3DBd4ijzkd3Fz7ADD2gy_Hxn8Hi2LcItuB514TjCxYA") - .append("ncTNqZC_JSFEyuxwcGFVz3LdSXgw") - .toString(); - } - - public static List createEntries() { - var list = new ArrayList(); - - var edrEntry = EndpointDataReferenceEntry.Builder.newInstance() - .assetId("79f13b89-59a6-4278-8c8e-8540849dbab8") - .agreementId("a62d02a3-eea5-4852-86d4-5482db4dffe8") - .transferProcessId("5355d524-2616-43df-9096-558afffff659") - .build(); - var edr = EndpointDataReference.Builder.newInstance() - .id("c470e649-5454-4e4d-b065-782752e5d759") - .endpoint(ENDPOINT) - .authKey(AUTHENTICATION) - .authCode(generateAuthCode()) - .contractId("test-contract-id") - .build(); - list.add(new PersistentCacheEntry(edrEntry, edr)); - - var edrEntry2 = EndpointDataReferenceEntry.Builder.newInstance() - .assetId("9260f395-3d94-4b8b-bdaa-941ead596ce5") - .agreementId("d6f73f25-b0aa-4b62-843f-7cfaba532b5b8") - .transferProcessId("b2859c0a-1a4f-4d10-a3fd-9652d7b3469a") - .build(); - var edr2 = EndpointDataReference.Builder.newInstance() - .id("514a4142-3d2a-4936-97c3-7892961c6a58") - .endpoint(ENDPOINT) - .authKey(AUTHENTICATION) - .authCode(generateAuthCode()) - .contractId("test-contract-id") - .build(); - list.add(new PersistentCacheEntry(edrEntry2, edr2)); - - var edrEntry3 = EndpointDataReferenceEntry.Builder.newInstance() - .assetId("9260f395-3d94-4b8b-bdaa-941ead596ce5") - .agreementId("7a23333b-03b5-4547-822b-595a54ad6d38") - .transferProcessId("7a23333b-03b5-4547-822b-595a54ad6d38") - .build(); - var edr3 = EndpointDataReference.Builder.newInstance() - .id("3563c5a1-685d-40e5-a380-0b5761523d2d") - .endpoint(ENDPOINT) - .contractId("test-contract-id") - .authKey(AUTHENTICATION) - .authCode(generateAuthCode()) - .build(); - - list.add(new PersistentCacheEntry(edrEntry3, edr3)); - - - return list; - } -} - diff --git a/edc-tests/edc-dataplane/edc-dataplane-proxy-e2e/src/test/java/org/eclipse/tractusx/edc/dataplane/proxy/e2e/KeyStoreSetup.java b/edc-tests/edc-dataplane/edc-dataplane-proxy-e2e/src/test/java/org/eclipse/tractusx/edc/dataplane/proxy/e2e/KeyStoreSetup.java deleted file mode 100644 index bbddb523b..000000000 --- a/edc-tests/edc-dataplane/edc-dataplane-proxy-e2e/src/test/java/org/eclipse/tractusx/edc/dataplane/proxy/e2e/KeyStoreSetup.java +++ /dev/null @@ -1,50 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.dataplane.proxy.e2e; - -import java.io.File; -import java.io.FileOutputStream; -import java.security.KeyStore; - -/** - * Sets up a test keystore. - */ -public class KeyStoreSetup { - - public static String createKeyStore(String password) { - try { - var ks = KeyStore.getInstance(KeyStore.getDefaultType()); - - ks.load(null, password.toCharArray()); - - var file = File.createTempFile("test", "-keystore.jks"); - try (var fos = new FileOutputStream(file)) { - ks.store(fos, password.toCharArray()); - } - file.deleteOnExit(); - return file.getAbsolutePath(); - } catch (Exception e) { - throw new AssertionError(e); - } - } - - private KeyStoreSetup() { - } -} diff --git a/edc-tests/miw-tests/build.gradle.kts b/edc-tests/miw-tests/build.gradle.kts index 85c1ea822..4f8b2d16a 100644 --- a/edc-tests/miw-tests/build.gradle.kts +++ b/edc-tests/miw-tests/build.gradle.kts @@ -23,7 +23,7 @@ plugins { dependencies { testImplementation(project(":spi:edr-spi")) - testImplementation(project(":edc-extensions:edr:edr-api")) + testImplementation(project(":edc-extensions:edr:edr-api-v2")) testImplementation(libs.okhttp.mockwebserver) testImplementation(libs.restAssured) testImplementation(libs.nimbus.jwt) diff --git a/edc-tests/runtime/extensions/build.gradle.kts b/edc-tests/runtime/extensions/build.gradle.kts index 1a54ff9ca..c877aadd3 100644 --- a/edc-tests/runtime/extensions/build.gradle.kts +++ b/edc-tests/runtime/extensions/build.gradle.kts @@ -27,8 +27,6 @@ dependencies { implementation(libs.edc.core.controlplane) implementation(libs.edc.util) implementation(libs.edc.spi.web) - // for the controller - implementation(libs.jakarta.rsApi) } diff --git a/edc-tests/runtime/extensions/src/main/java/org/eclipse/tractusx/edc/lifecycle/ConsumerEdrHandlerController.java b/edc-tests/runtime/extensions/src/main/java/org/eclipse/tractusx/edc/lifecycle/ConsumerEdrHandlerController.java deleted file mode 100644 index c29c223a6..000000000 --- a/edc-tests/runtime/extensions/src/main/java/org/eclipse/tractusx/edc/lifecycle/ConsumerEdrHandlerController.java +++ /dev/null @@ -1,65 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.lifecycle; - -import jakarta.ws.rs.Consumes; -import jakarta.ws.rs.GET; -import jakarta.ws.rs.POST; -import jakarta.ws.rs.Path; -import jakarta.ws.rs.PathParam; -import jakarta.ws.rs.Produces; -import jakarta.ws.rs.core.MediaType; -import org.eclipse.edc.spi.monitor.Monitor; -import org.eclipse.edc.spi.types.domain.edr.EndpointDataReference; - -import java.util.HashMap; -import java.util.Map; -import java.util.Optional; - -@Path("/consumer") -public class ConsumerEdrHandlerController { - - private final Monitor monitor; - private final Map dataReference; - - public ConsumerEdrHandlerController(Monitor monitor) { - this.monitor = monitor; - dataReference = new HashMap<>(); - } - - @Path("/datareference") - @POST - @Consumes({MediaType.APPLICATION_JSON}) - public void pushDataReference(EndpointDataReference edr) { - monitor.debug("Received new endpoint data reference with url " + edr.getEndpoint()); - dataReference.put(edr.getId(), edr); - } - - @Path("/datareference/{id}") - @GET - @Produces({MediaType.APPLICATION_JSON}) - public EndpointDataReference getDataReference(@PathParam("id") String id) { - return Optional.ofNullable(dataReference.get(id)).orElseGet(() -> { - monitor.warning("No EndpointDataReference found with id " + id); - return null; - }); - } - -} diff --git a/edc-tests/runtime/extensions/src/main/java/org/eclipse/tractusx/edc/lifecycle/ConsumerServicesExtension.java b/edc-tests/runtime/extensions/src/main/java/org/eclipse/tractusx/edc/lifecycle/ConsumerServicesExtension.java deleted file mode 100644 index 8be09e430..000000000 --- a/edc-tests/runtime/extensions/src/main/java/org/eclipse/tractusx/edc/lifecycle/ConsumerServicesExtension.java +++ /dev/null @@ -1,38 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.lifecycle; - -import org.eclipse.edc.runtime.metamodel.annotation.Inject; -import org.eclipse.edc.spi.system.ServiceExtension; -import org.eclipse.edc.spi.system.ServiceExtensionContext; -import org.eclipse.edc.web.spi.WebService; - -public class ConsumerServicesExtension implements ServiceExtension { - - - @Inject - private WebService webService; - - @Override - public void initialize(ServiceExtensionContext context) { - webService.registerResource("default", new ConsumerEdrHandlerController(context.getMonitor())); - } - -} diff --git a/edc-tests/runtime/extensions/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension b/edc-tests/runtime/extensions/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension index 1db031d31..4e2b9da92 100644 --- a/edc-tests/runtime/extensions/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension +++ b/edc-tests/runtime/extensions/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension @@ -17,5 +17,4 @@ # SPDX-License-Identifier: Apache-2.0 ################################################################################# -org.eclipse.tractusx.edc.lifecycle.ConsumerServicesExtension org.eclipse.tractusx.edc.lifecycle.VaultSeedExtension diff --git a/edc-tests/runtime/iatp/runtime-memory-iatp-ih/build.gradle.kts b/edc-tests/runtime/iatp/runtime-memory-iatp-ih/build.gradle.kts index ae572775d..e09deca89 100644 --- a/edc-tests/runtime/iatp/runtime-memory-iatp-ih/build.gradle.kts +++ b/edc-tests/runtime/iatp/runtime-memory-iatp-ih/build.gradle.kts @@ -31,6 +31,7 @@ dependencies { exclude(module = "ssi-miw-credential-client") exclude(module = "ssi-identity-extractor") exclude(module = "cx-policy-legacy") + exclude(module = "tx-iatp-sts-dim") } implementation(project(":edc-extensions:cx-policy")) implementation(project(":core:json-ld-core")) diff --git a/edc-tests/runtime/iatp/runtime-memory-sts/build.gradle.kts b/edc-tests/runtime/iatp/runtime-memory-sts/build.gradle.kts index 88dcebd26..fa7db7bb0 100644 --- a/edc-tests/runtime/iatp/runtime-memory-sts/build.gradle.kts +++ b/edc-tests/runtime/iatp/runtime-memory-sts/build.gradle.kts @@ -31,6 +31,7 @@ dependencies { exclude(module = "ssi-miw-credential-client") exclude(module = "ssi-identity-extractor") exclude(module = "cx-policy-legacy") + exclude(module = "tx-iatp-sts-dim") } implementation(project(":core:json-ld-core")) implementation(project(":edc-tests:runtime:extensions")) @@ -40,6 +41,8 @@ dependencies { implementation(libs.jakarta.rsApi) implementation(libs.bundles.edc.sts) + implementation(libs.edc.identity.trust.sts.embedded) + implementation(libs.edc.core.token) } application { diff --git a/edc-tests/runtime/iatp/runtime-memory-sts/src/main/java/org/eclipse/tractusx/edc/lifecycle/SecureTokenServiceExtension.java b/edc-tests/runtime/iatp/runtime-memory-sts/src/main/java/org/eclipse/tractusx/edc/lifecycle/SecureTokenServiceExtension.java new file mode 100644 index 000000000..0cf88e4b0 --- /dev/null +++ b/edc-tests/runtime/iatp/runtime-memory-sts/src/main/java/org/eclipse/tractusx/edc/lifecycle/SecureTokenServiceExtension.java @@ -0,0 +1,57 @@ +/******************************************************************************** + * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +package org.eclipse.tractusx.edc.lifecycle; + +import org.eclipse.edc.iam.identitytrust.sts.embedded.EmbeddedSecureTokenService; +import org.eclipse.edc.identitytrust.SecureTokenService; +import org.eclipse.edc.runtime.metamodel.annotation.Inject; +import org.eclipse.edc.runtime.metamodel.annotation.Provider; +import org.eclipse.edc.spi.EdcException; +import org.eclipse.edc.spi.security.PrivateKeyResolver; +import org.eclipse.edc.spi.system.ServiceExtension; +import org.eclipse.edc.spi.system.ServiceExtensionContext; +import org.eclipse.edc.token.JwtGenerationService; + +import java.security.PrivateKey; +import java.time.Clock; +import java.util.concurrent.TimeUnit; +import java.util.function.Supplier; + +public class SecureTokenServiceExtension implements ServiceExtension { + public static final String STS_PRIVATE_KEY_ALIAS = "edc.iam.sts.privatekey.alias"; + public static final String STS_PUBLIC_KEY_ID = "edc.iam.sts.publickey.id"; + private static final String STS_TOKEN_EXPIRATION = "edc.iam.sts.token.expiration"; // in minutes + private static final int DEFAULT_STS_TOKEN_EXPIRATION_MIN = 5; + @Inject + private PrivateKeyResolver privateKeyResolver; + + @Inject + private Clock clock; + + @Provider + public SecureTokenService createEmbeddedSts(ServiceExtensionContext context) { + var tokenExpiration = context.getSetting(STS_TOKEN_EXPIRATION, DEFAULT_STS_TOKEN_EXPIRATION_MIN); + var publicKeyId = context.getSetting(STS_PUBLIC_KEY_ID, null); + var privKeyAlias = context.getSetting(STS_PRIVATE_KEY_ALIAS, null); + + Supplier supplier = () -> privateKeyResolver.resolvePrivateKey(privKeyAlias).orElseThrow(f -> new EdcException("This EDC instance is not operational due to the following error: %s".formatted(f.getFailureDetail()))); + return new EmbeddedSecureTokenService(new JwtGenerationService(), supplier, () -> publicKeyId, clock, TimeUnit.MINUTES.toSeconds(tokenExpiration)); + } +} diff --git a/edc-extensions/data-encryption/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension b/edc-tests/runtime/iatp/runtime-memory-sts/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension similarity index 93% rename from edc-extensions/data-encryption/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension rename to edc-tests/runtime/iatp/runtime-memory-sts/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension index 13333ee69..bb3dc7fbb 100644 --- a/edc-extensions/data-encryption/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension +++ b/edc-tests/runtime/iatp/runtime-memory-sts/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension @@ -17,5 +17,4 @@ # SPDX-License-Identifier: Apache-2.0 ################################################################################# -org.eclipse.tractusx.edc.data.encryption.TxEncryptorExtension - +org.eclipse.tractusx.edc.lifecycle.SecureTokenServiceExtension diff --git a/edc-tests/runtime/runtime-memory-signaling/build.gradle.kts b/edc-tests/runtime/runtime-memory-signaling/build.gradle.kts index 816fe647f..518aabfcd 100644 --- a/edc-tests/runtime/runtime-memory-signaling/build.gradle.kts +++ b/edc-tests/runtime/runtime-memory-signaling/build.gradle.kts @@ -27,13 +27,6 @@ dependencies { // use basic (all in-mem) control plane implementation(project(":edc-tests:runtime:runtime-memory")) - - // these extensions are used for DataPlane Signaling + Token Refresh - runtimeOnly(project(":edc-extensions:edr:edr-api-v2")) - runtimeOnly(project((":edc-extensions:tokenrefresh-handler"))) - runtimeOnly(libs.edc.edr.store.receiver) - runtimeOnly(libs.edc.core.edrstore) - } application { diff --git a/edc-tests/runtime/runtime-memory-ssi/build.gradle.kts b/edc-tests/runtime/runtime-memory-ssi/build.gradle.kts index 7d8b69ae3..97ea2f255 100644 --- a/edc-tests/runtime/runtime-memory-ssi/build.gradle.kts +++ b/edc-tests/runtime/runtime-memory-ssi/build.gradle.kts @@ -33,7 +33,7 @@ dependencies { implementation(project(":edc-extensions:ssi:ssi-identity-core")) - implementation(project(":edc-extensions:ssi:ssi-miw-credential-client")); + implementation(project(":edc-extensions:ssi:ssi-miw-credential-client")) implementation(project(":edc-extensions:ssi:ssi-identity-extractor")) implementation(project(":edc-extensions:cx-policy-legacy")) diff --git a/edc-tests/runtime/runtime-memory/build.gradle.kts b/edc-tests/runtime/runtime-memory/build.gradle.kts index 7a389a698..6cb248998 100644 --- a/edc-tests/runtime/runtime-memory/build.gradle.kts +++ b/edc-tests/runtime/runtime-memory/build.gradle.kts @@ -32,8 +32,12 @@ dependencies { exclude(module = "ssi-miw-credential-client") exclude(module = "ssi-identity-extractor") exclude(module = "cx-policy-legacy") + exclude(module = "tx-iatp-sts-dim") } + // use an embedded STS + runtimeOnly(libs.edc.identity.trust.sts.embedded) + implementation(project(":edc-tests:runtime:extensions")) // use basic (all in-mem) data plane diff --git a/edc-tests/runtime/runtime-postgresql/build.gradle.kts b/edc-tests/runtime/runtime-postgresql/build.gradle.kts index 4eb0ef35c..944ede37c 100644 --- a/edc-tests/runtime/runtime-postgresql/build.gradle.kts +++ b/edc-tests/runtime/runtime-postgresql/build.gradle.kts @@ -33,6 +33,7 @@ dependencies { exclude(module = "ssi-miw-credential-client") exclude(module = "ssi-identity-extractor") exclude(module = "cx-policy-legacy") + exclude(module = "tx-iatp-sts-dim") exclude(group = "org.eclipse.edc", "vault-hashicorp") } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index bb21333d1..6276cee7b 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -143,6 +143,7 @@ edc-identity-trust-sts-client-configuration = { module = "org.eclipse.edc:identi edc-ih-api = { module = "org.eclipse.edc:identity-hub-api", version.ref = "edc" } edc-ih-credentials = { module = "org.eclipse.edc:identity-hub-credentials", version.ref = "edc" } edc-ih-spi-store = { module = "org.eclipse.edc:identity-hub-store-spi", version.ref = "edc" } +edc-ih-spi = { module = "org.eclipse.edc:identity-hub-spi", version.ref = "edc" } edc-ih-keypairs = { module = "org.eclipse.edc:identity-hub-keypairs", version.ref = "edc" } edc-ih-participants = { module = "org.eclipse.edc:identity-hub-participants", version.ref = "edc" } edc-ih-did = { module = "org.eclipse.edc:identity-hub-did", version.ref = "edc" } @@ -155,7 +156,6 @@ edc-spi-dataplane-http = { module = "org.eclipse.edc:data-plane-http-spi", versi edc-dpf-transferclient = { module = "org.eclipse.edc:data-plane-transfer-client", version.ref = "edc" } edc-dpf-selector-spi = { module = "org.eclipse.edc:data-plane-selector-spi", version.ref = "edc" } edc-dpf-selector-core = { module = "org.eclipse.edc:data-plane-selector-core", version.ref = "edc" } -edc-dpf-transfer = { module = "org.eclipse.edc:transfer-data-plane", version.ref = "edc" } edc-dpf-transfer-signaling = { module = "org.eclipse.edc:transfer-data-plane-signaling", version.ref = "edc" } edc-dpf-core = { module = "org.eclipse.edc:data-plane-core", version.ref = "edc" } edc-dpf-util = { module = "org.eclipse.edc:data-plane-util", version.ref = "edc" } @@ -164,7 +164,6 @@ edc-dpf-azblob = { module = "org.eclipse.edc:data-plane-azure-storage", version. edc-dpf-http = { module = "org.eclipse.edc:data-plane-http", version.ref = "edc" } edc-dpf-oauth2 = { module = "org.eclipse.edc:data-plane-http-oauth2", version.ref = "edc" } edc-dpf-api-control = { module = "org.eclipse.edc:data-plane-control-api", version.ref = "edc" } -edc-dpf-api-public-v1 = { module = "org.eclipse.edc:data-plane-public-api", version.ref = "edc" } edc-dpf-api-public-v2 = { module = "org.eclipse.edc:data-plane-public-api-v2", version.ref = "edc" } edc-dpf-api-signaling = { module = "org.eclipse.edc:data-plane-signaling-api", version.ref = "edc" } @@ -210,7 +209,7 @@ titaniumJsonLd = { module = "com.apicatalog:titanium-json-ld", version.ref = "ti [bundles] edc-connector = ["edc.boot", "edc.core-connector", "edc.core-controlplane", "edc.api-observability"] -edc-dpf = ["edc.dpf-transfer", "edc.dpf-selector-core", "edc.spi-dataplane-selector"] +edc-dpf = ["edc.dpf-transfer-signaling", "edc.dpf-selector-core", "edc.spi-dataplane-selector"] edc-sqlstores = ["edc.sql-assetindex", "edc.sql-contract-definition", "edc.sql-contract-negotiation", "edc.sql-transferprocess", "edc.sql-policydef", "edc.sql-policy-monitor"] edc-monitoring = ["edc.micrometer-core", "edc.micrometer-jersey", "edc.micrometer-jetty"] edc-sts = ["edc-identity-trust-sts-core", "edc-identity-trust-sts-api", "edc-identity-trust-sts-client-configuration"] diff --git a/samples/multi-tenancy/build.gradle.kts b/samples/multi-tenancy/build.gradle.kts index 31239069d..336bebe19 100644 --- a/samples/multi-tenancy/build.gradle.kts +++ b/samples/multi-tenancy/build.gradle.kts @@ -32,8 +32,14 @@ dependencies { exclude(module = "ssi-miw-credential-client") exclude(module = "ssi-identity-core") exclude(module = "auth-tokenbased") + // the token refresh extension is not needed + exclude(module = "tx-iatp-sts-dim") + exclude(module = "tokenrefresh-handler") + exclude(module = "edr-api-v2") + exclude(module = "edr-callback") } implementation(libs.edc.core.controlplane) + implementation(libs.jakarta.rsApi) } application { diff --git a/settings.gradle.kts b/settings.gradle.kts index 379f7a43f..846584b6b 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -39,17 +39,14 @@ include(":edc-extensions:bpn-validation:bpn-validation-api") include(":edc-extensions:bpn-validation:bpn-validation-spi") include(":edc-extensions:bpn-validation:bpn-validation-core") include(":edc-extensions:bpn-validation:business-partner-store-sql") -include(":edc-extensions:data-encryption") include(":edc-extensions:postgresql-migration") include(":edc-extensions:tokenrefresh-handler") include(":edc-extensions:provision-additional-headers") include(":edc-extensions:transferprocess-sftp-client") include(":edc-extensions:transferprocess-sftp-common") include(":edc-extensions:transferprocess-sftp-provisioner") -include(":edc-extensions:edr:edr-api") include(":edc-extensions:edr:edr-api-v2") include(":edc-extensions:edr:edr-callback") -include(":edc-extensions:edr:edr-cache-sql") include(":edc-extensions:cx-policy") include(":edc-extensions:cx-policy-legacy") include(":edc-extensions:ssi:ssi-identity-core") @@ -60,20 +57,22 @@ include(":edc-extensions:iatp:tx-iatp-sts-dim") // extensions - data plane include(":edc-extensions:dataplane:dataplane-proxy:edc-dataplane-proxy-consumer-api") -include(":edc-extensions:dataplane:dataplane-proxy:edc-dataplane-proxy-provider-spi") -include(":edc-extensions:dataplane:dataplane-proxy:edc-dataplane-proxy-provider-core") -include(":edc-extensions:dataplane:dataplane-proxy:edc-dataplane-proxy-provider-api") include(":edc-extensions:dataplane:dataplane-selector-configuration") include(":edc-extensions:dataplane:dataplane-token-refresh:token-refresh-core") include(":edc-extensions:dataplane:dataplane-token-refresh:token-refresh-api") // test modules include(":edc-tests:e2e-tests") -include(":edc-tests:edc-controlplane:edr-tests") +include(":edc-tests:edc-controlplane:edr-api-tests") +include(":edc-tests:edc-controlplane:catalog-tests") +include(":edc-tests:edc-controlplane:transfer-tests") +include(":edc-tests:edc-controlplane:iatp-tests") +include(":edc-tests:edc-controlplane:policy-tests") +include(":edc-tests:edc-controlplane:ssi-summarycred-tests") +include(":edc-tests:edc-controlplane:fixtures") include(":edc-tests:miw-tests") include(":edc-tests:runtime:extensions") include(":edc-tests:runtime:runtime-memory") -include(":edc-tests:runtime:runtime-memory-signaling") include(":edc-tests:runtime:dataplane-cloud") include(":edc-tests:runtime:runtime-memory-ssi") include(":edc-tests:runtime:runtime-postgresql") @@ -82,7 +81,6 @@ include(":edc-tests:runtime:iatp:runtime-memory-iatp-ih") include(":edc-tests:runtime:iatp:runtime-memory-iatp-dim-ih") include(":edc-tests:runtime:iatp:runtime-memory-sts") include(":edc-tests:runtime:iatp:iatp-extensions") -include(":edc-tests:edc-dataplane:edc-dataplane-proxy-e2e") include(":edc-tests:edc-dataplane:edc-dataplane-tokenrefresh-tests") include(":edc-tests:edc-dataplane:cloud-transfer-tests") From 3967480949027580f83ebae3177c0c7884d6cec9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 21 Mar 2024 09:44:54 +0100 Subject: [PATCH 061/100] chore(deps): bump testcontainers from 1.19.6 to 1.19.7 (#1133) * chore(deps): bump testcontainers from 1.19.6 to 1.19.7 Bumps `testcontainers` from 1.19.6 to 1.19.7. Updates `org.testcontainers:junit-jupiter` from 1.19.6 to 1.19.7 - [Release notes](https://github.com/testcontainers/testcontainers-java/releases) - [Changelog](https://github.com/testcontainers/testcontainers-java/blob/main/CHANGELOG.md) - [Commits](https://github.com/testcontainers/testcontainers-java/compare/1.19.6...1.19.7) Updates `org.testcontainers:postgresql` from 1.19.6 to 1.19.7 - [Release notes](https://github.com/testcontainers/testcontainers-java/releases) - [Changelog](https://github.com/testcontainers/testcontainers-java/blob/main/CHANGELOG.md) - [Commits](https://github.com/testcontainers/testcontainers-java/compare/1.19.6...1.19.7) Updates `org.testcontainers:vault` from 1.19.6 to 1.19.7 - [Release notes](https://github.com/testcontainers/testcontainers-java/releases) - [Changelog](https://github.com/testcontainers/testcontainers-java/blob/main/CHANGELOG.md) - [Commits](https://github.com/testcontainers/testcontainers-java/compare/1.19.6...1.19.7) --- updated-dependencies: - dependency-name: org.testcontainers:junit-jupiter dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.testcontainers:postgresql dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.testcontainers:vault dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] * chore: dependencies file --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Enrico Risa --- DEPENDENCIES | 9 +-------- gradle/libs.versions.toml | 2 +- 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/DEPENDENCIES b/DEPENDENCIES index 09628486e..0819cde8f 100644 --- a/DEPENDENCIES +++ b/DEPENDENCIES @@ -72,11 +72,8 @@ maven/mavencentral/com.fasterxml.jackson/jackson-bom/2.16.2, Apache-2.0, approve maven/mavencentral/com.fasterxml.uuid/java-uuid-generator/4.1.0, Apache-2.0, approved, clearlydefined maven/mavencentral/com.fasterxml.woodstox/woodstox-core/6.5.1, Apache-2.0, approved, #7950 maven/mavencentral/com.github.cliftonlabs/json-simple/3.0.2, Apache-2.0, approved, clearlydefined -maven/mavencentral/com.github.docker-java/docker-java-api/3.3.5, Apache-2.0, approved, #10346 maven/mavencentral/com.github.docker-java/docker-java-api/3.3.6, Apache-2.0, approved, #10346 -maven/mavencentral/com.github.docker-java/docker-java-transport-zerodep/3.3.5, Apache-2.0 AND (Apache-2.0 AND BSD-3-Clause), approved, #7946 maven/mavencentral/com.github.docker-java/docker-java-transport-zerodep/3.3.6, Apache-2.0 AND (Apache-2.0 AND BSD-3-Clause), approved, #7946 -maven/mavencentral/com.github.docker-java/docker-java-transport/3.3.5, Apache-2.0, approved, #7942 maven/mavencentral/com.github.docker-java/docker-java-transport/3.3.6, Apache-2.0, approved, #7942 maven/mavencentral/com.github.java-json-tools/btf/1.3, Apache-2.0 OR LGPL-3.0-or-later, approved, #2721 maven/mavencentral/com.github.java-json-tools/jackson-coreutils-equivalence/1.0, LGPL-3.0 OR Apache-2.0, approved, clearlydefined @@ -603,17 +600,13 @@ maven/mavencentral/org.slf4j/slf4j-api/1.7.7, MIT, approved, CQ9827 maven/mavencentral/org.slf4j/slf4j-api/2.0.12, MIT, approved, #5915 maven/mavencentral/org.slf4j/slf4j-api/2.0.6, MIT, approved, #5915 maven/mavencentral/org.slf4j/slf4j-api/2.0.9, MIT, approved, #5915 -maven/mavencentral/org.testcontainers/database-commons/1.19.6, Apache-2.0, approved, #10345 maven/mavencentral/org.testcontainers/database-commons/1.19.7, Apache-2.0, approved, #10345 -maven/mavencentral/org.testcontainers/jdbc/1.19.6, Apache-2.0, approved, #10348 maven/mavencentral/org.testcontainers/jdbc/1.19.7, Apache-2.0, approved, #10348 maven/mavencentral/org.testcontainers/junit-jupiter/1.19.6, MIT, approved, #10344 maven/mavencentral/org.testcontainers/junit-jupiter/1.19.7, MIT, approved, #10344 -maven/mavencentral/org.testcontainers/postgresql/1.19.6, MIT, approved, #10350 maven/mavencentral/org.testcontainers/postgresql/1.19.7, MIT, approved, #10350 -maven/mavencentral/org.testcontainers/testcontainers/1.19.6, Apache-2.0 AND MIT, approved, #10347 maven/mavencentral/org.testcontainers/testcontainers/1.19.7, Apache-2.0 AND MIT, approved, #10347 -maven/mavencentral/org.testcontainers/vault/1.19.6, MIT, approved, #10852 +maven/mavencentral/org.testcontainers/vault/1.19.7, MIT, approved, #10852 maven/mavencentral/org.xmlresolver/xmlresolver/5.2.2, Apache-2.0, approved, clearlydefined maven/mavencentral/org.xmlunit/xmlunit-core/2.9.1, Apache-2.0, approved, #6272 maven/mavencentral/org.xmlunit/xmlunit-placeholders/2.9.1, Apache-2.0, approved, clearlydefined diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 6276cee7b..8cf2cf851 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -22,7 +22,7 @@ postgres = "42.7.2" restAssured = "5.4.0" rsApi = "3.1.0" slf4j = "2.0.12" -testcontainers = "1.19.6" +testcontainers = "1.19.7" tink = "1.12.0" titanium = "1.4.0" From ef2fbf13a0d0da6be413f6c701ed441a1df8829e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 21 Mar 2024 09:59:12 +0100 Subject: [PATCH 062/100] chore(deps): bump jackson from 2.16.1 to 2.17.0 (#1132) * chore(deps): bump jackson from 2.16.1 to 2.17.0 Bumps `jackson` from 2.16.1 to 2.17.0. Updates `com.fasterxml.jackson.datatype:jackson-datatype-jsr310` from 2.16.1 to 2.17.0 Updates `com.fasterxml.jackson.datatype:jackson-datatype-jakarta-jsonp` from 2.16.1 to 2.17.0 - [Commits](https://github.com/FasterXML/jackson-datatypes-misc/compare/jackson-datatypes-misc-parent-2.16.1...jackson-datatypes-misc-parent-2.17.0) --- updated-dependencies: - dependency-name: com.fasterxml.jackson.datatype:jackson-datatype-jsr310 dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: com.fasterxml.jackson.datatype:jackson-datatype-jakarta-jsonp dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * chore: dependencies file --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Enrico Risa --- DEPENDENCIES | 14 ++++++++------ gradle/libs.versions.toml | 2 +- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/DEPENDENCIES b/DEPENDENCIES index 0819cde8f..2cda9e992 100644 --- a/DEPENDENCIES +++ b/DEPENDENCIES @@ -26,13 +26,13 @@ maven/mavencentral/com.fasterxml.jackson.core/jackson-annotations/2.14.1, Apache maven/mavencentral/com.fasterxml.jackson.core/jackson-annotations/2.15.1, Apache-2.0, approved, #7947 maven/mavencentral/com.fasterxml.jackson.core/jackson-annotations/2.15.2, Apache-2.0, approved, #7947 maven/mavencentral/com.fasterxml.jackson.core/jackson-annotations/2.15.3, Apache-2.0, approved, #7947 -maven/mavencentral/com.fasterxml.jackson.core/jackson-annotations/2.16.1, Apache-2.0, approved, #11606 maven/mavencentral/com.fasterxml.jackson.core/jackson-annotations/2.16.2, Apache-2.0, approved, #11606 +maven/mavencentral/com.fasterxml.jackson.core/jackson-annotations/2.17.0, Apache-2.0, approved, #13672 maven/mavencentral/com.fasterxml.jackson.core/jackson-core/2.13.5, Apache-2.0, approved, #2133 maven/mavencentral/com.fasterxml.jackson.core/jackson-core/2.14.1, Apache-2.0 AND MIT, approved, #4303 maven/mavencentral/com.fasterxml.jackson.core/jackson-core/2.15.1, MIT AND Apache-2.0, approved, #7932 -maven/mavencentral/com.fasterxml.jackson.core/jackson-core/2.16.1, Apache-2.0 AND MIT, approved, #11602 maven/mavencentral/com.fasterxml.jackson.core/jackson-core/2.16.2, Apache-2.0 AND MIT, approved, #11602 +maven/mavencentral/com.fasterxml.jackson.core/jackson-core/2.17.0, , approved, #13665 maven/mavencentral/com.fasterxml.jackson.core/jackson-databind/2.11.0, Apache-2.0, approved, CQ23093 maven/mavencentral/com.fasterxml.jackson.core/jackson-databind/2.13.4.2, Apache-2.0, approved, #2134 maven/mavencentral/com.fasterxml.jackson.core/jackson-databind/2.13.5, Apache-2.0, approved, #2134 @@ -42,8 +42,8 @@ maven/mavencentral/com.fasterxml.jackson.core/jackson-databind/2.14.2, Apache-2. maven/mavencentral/com.fasterxml.jackson.core/jackson-databind/2.15.1, Apache-2.0, approved, #7934 maven/mavencentral/com.fasterxml.jackson.core/jackson-databind/2.15.2, Apache-2.0, approved, #7934 maven/mavencentral/com.fasterxml.jackson.core/jackson-databind/2.15.3, Apache-2.0, approved, #7934 -maven/mavencentral/com.fasterxml.jackson.core/jackson-databind/2.16.1, Apache-2.0, approved, #11605 maven/mavencentral/com.fasterxml.jackson.core/jackson-databind/2.16.2, Apache-2.0, approved, #11605 +maven/mavencentral/com.fasterxml.jackson.core/jackson-databind/2.17.0, Apache-2.0, approved, #13671 maven/mavencentral/com.fasterxml.jackson.dataformat/jackson-dataformat-toml/2.15.2, Apache-2.0, approved, #9160 maven/mavencentral/com.fasterxml.jackson.dataformat/jackson-dataformat-toml/2.16.2, Apache-2.0, approved, #13145 maven/mavencentral/com.fasterxml.jackson.dataformat/jackson-dataformat-xml/2.13.5, Apache-2.0, approved, #3768 @@ -52,14 +52,14 @@ maven/mavencentral/com.fasterxml.jackson.dataformat/jackson-dataformat-yaml/2.14 maven/mavencentral/com.fasterxml.jackson.dataformat/jackson-dataformat-yaml/2.15.1, Apache-2.0, approved, #8802 maven/mavencentral/com.fasterxml.jackson.dataformat/jackson-dataformat-yaml/2.15.2, Apache-2.0, approved, #8802 maven/mavencentral/com.fasterxml.jackson.dataformat/jackson-dataformat-yaml/2.16.2, Apache-2.0, approved, #11855 -maven/mavencentral/com.fasterxml.jackson.datatype/jackson-datatype-jakarta-jsonp/2.16.1, Apache-2.0, approved, #11854 maven/mavencentral/com.fasterxml.jackson.datatype/jackson-datatype-jakarta-jsonp/2.16.2, Apache-2.0, approved, #11854 +maven/mavencentral/com.fasterxml.jackson.datatype/jackson-datatype-jakarta-jsonp/2.17.0, , restricted, clearlydefined maven/mavencentral/com.fasterxml.jackson.datatype/jackson-datatype-jsr310/2.13.5, Apache-2.0, approved, clearlydefined maven/mavencentral/com.fasterxml.jackson.datatype/jackson-datatype-jsr310/2.14.0, Apache-2.0, approved, #4699 maven/mavencentral/com.fasterxml.jackson.datatype/jackson-datatype-jsr310/2.15.1, Apache-2.0, approved, #7930 maven/mavencentral/com.fasterxml.jackson.datatype/jackson-datatype-jsr310/2.15.2, Apache-2.0, approved, #7930 -maven/mavencentral/com.fasterxml.jackson.datatype/jackson-datatype-jsr310/2.16.1, Apache-2.0, approved, #11853 maven/mavencentral/com.fasterxml.jackson.datatype/jackson-datatype-jsr310/2.16.2, Apache-2.0, approved, #11853 +maven/mavencentral/com.fasterxml.jackson.datatype/jackson-datatype-jsr310/2.17.0, , restricted, clearlydefined maven/mavencentral/com.fasterxml.jackson.jakarta.rs/jackson-jakarta-rs-base/2.16.2, Apache-2.0, approved, #11851 maven/mavencentral/com.fasterxml.jackson.jakarta.rs/jackson-jakarta-rs-json-provider/2.15.1, Apache-2.0, approved, #9236 maven/mavencentral/com.fasterxml.jackson.jakarta.rs/jackson-jakarta-rs-json-provider/2.15.2, Apache-2.0, approved, #9236 @@ -67,8 +67,8 @@ maven/mavencentral/com.fasterxml.jackson.jakarta.rs/jackson-jakarta-rs-json-prov maven/mavencentral/com.fasterxml.jackson.module/jackson-module-jakarta-xmlbind-annotations/2.15.3, Apache-2.0, approved, #9241 maven/mavencentral/com.fasterxml.jackson.module/jackson-module-jakarta-xmlbind-annotations/2.16.2, Apache-2.0, approved, #11856 maven/mavencentral/com.fasterxml.jackson/jackson-bom/2.15.1, Apache-2.0, approved, #7929 -maven/mavencentral/com.fasterxml.jackson/jackson-bom/2.16.1, Apache-2.0, approved, #11852 maven/mavencentral/com.fasterxml.jackson/jackson-bom/2.16.2, Apache-2.0, approved, #11852 +maven/mavencentral/com.fasterxml.jackson/jackson-bom/2.17.0, , restricted, clearlydefined maven/mavencentral/com.fasterxml.uuid/java-uuid-generator/4.1.0, Apache-2.0, approved, clearlydefined maven/mavencentral/com.fasterxml.woodstox/woodstox-core/6.5.1, Apache-2.0, approved, #7950 maven/mavencentral/com.github.cliftonlabs/json-simple/3.0.2, Apache-2.0, approved, clearlydefined @@ -253,6 +253,7 @@ maven/mavencentral/jakarta.activation/jakarta.activation-api/2.1.0, EPL-2.0 OR B maven/mavencentral/jakarta.annotation/jakarta.annotation-api/2.1.1, EPL-2.0 OR GPL-2.0-only with Classpath-exception-2.0, approved, ee4j.ca maven/mavencentral/jakarta.inject/jakarta.inject-api/2.0.1, Apache-2.0, approved, ee4j.cdi maven/mavencentral/jakarta.json/jakarta.json-api/2.1.1, EPL-2.0 OR GPL-2.0-only with Classpath-exception-2.0, approved, ee4j.jsonp +maven/mavencentral/jakarta.json/jakarta.json-api/2.1.3, EPL-2.0 OR GPL-2.0-only with Classpath-exception-2.0, approved, ee4j.jsonp maven/mavencentral/jakarta.transaction/jakarta.transaction-api/2.0.0, EPL-2.0 OR GPL-2.0-only with Classpath-exception-2.0, approved, ee4j.jta maven/mavencentral/jakarta.validation/jakarta.validation-api/2.0.2, Apache-2.0, approved, ee4j.validation maven/mavencentral/jakarta.validation/jakarta.validation-api/3.0.2, Apache-2.0, approved, ee4j.validation @@ -271,6 +272,7 @@ maven/mavencentral/net.bytebuddy/byte-buddy-agent/1.14.12, Apache-2.0, approved, maven/mavencentral/net.bytebuddy/byte-buddy/1.14.1, Apache-2.0 AND BSD-3-Clause, approved, #7163 maven/mavencentral/net.bytebuddy/byte-buddy/1.14.11, Apache-2.0 AND BSD-3-Clause, approved, #7163 maven/mavencentral/net.bytebuddy/byte-buddy/1.14.12, Apache-2.0 AND BSD-3-Clause, approved, #7163 +maven/mavencentral/net.bytebuddy/byte-buddy/1.14.9, Apache-2.0 AND BSD-3-Clause, approved, #7163 maven/mavencentral/net.java.dev.jna/jna-platform/5.13.0, Apache-2.0 OR LGPL-2.1-or-later, approved, #6707 maven/mavencentral/net.java.dev.jna/jna-platform/5.6.0, Apache-2.0 OR LGPL-2.1-or-later, approved, CQ22390 maven/mavencentral/net.java.dev.jna/jna/5.13.0, Apache-2.0 AND LGPL-2.1-or-later, approved, #6709 diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 8cf2cf851..f3cad4e18 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -11,7 +11,7 @@ azure-identity = "1.11.3" bouncyCastle-jdk18on = "1.77" flyway = "10.8.1" iron-vc = "0.14.0" -jackson = "2.16.1" +jackson = "2.17.0" jakarta-json = "2.0.1" jupiter = "5.10.2" mockwebserver = "5.0.0-alpha.12" From 1adb9ae0830cf0a69623a01e03f1c88d6624bb52 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 21 Mar 2024 10:35:51 +0100 Subject: [PATCH 063/100] chore(deps): bump aws from 2.25.1 to 2.25.14 (#1147) * chore(deps): bump aws from 2.25.1 to 2.25.14 Bumps `aws` from 2.25.1 to 2.25.14. Updates `software.amazon.awssdk:s3` from 2.25.1 to 2.25.14 Updates `software.amazon.awssdk:s3-transfer-manager` from 2.25.1 to 2.25.14 --- updated-dependencies: - dependency-name: software.amazon.awssdk:s3 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:s3-transfer-manager dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] * chore: dependencies file --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Enrico Risa --- DEPENDENCIES | 54 +++++++++++++++++++-------------------- gradle/libs.versions.toml | 2 +- 2 files changed, 28 insertions(+), 28 deletions(-) diff --git a/DEPENDENCIES b/DEPENDENCIES index 2cda9e992..dafcba4f5 100644 --- a/DEPENDENCIES +++ b/DEPENDENCIES @@ -616,58 +616,58 @@ maven/mavencentral/org.yaml/snakeyaml/1.33, Apache-2.0, approved, clearlydefined maven/mavencentral/org.yaml/snakeyaml/2.0, Apache-2.0 AND (Apache-2.0 OR BSD-3-Clause OR EPL-1.0 OR GPL-2.0-or-later OR LGPL-2.1-or-later), approved, #7275 maven/mavencentral/org.yaml/snakeyaml/2.2, Apache-2.0 AND (Apache-2.0 OR BSD-3-Clause OR EPL-1.0 OR GPL-2.0-or-later OR LGPL-2.1-or-later), approved, #10232 maven/mavencentral/software.amazon.awssdk/annotations/2.24.10, Apache-2.0, approved, #13251 -maven/mavencentral/software.amazon.awssdk/annotations/2.25.1, Apache-2.0, approved, #13691 +maven/mavencentral/software.amazon.awssdk/annotations/2.25.14, Apache-2.0, approved, #13691 maven/mavencentral/software.amazon.awssdk/apache-client/2.24.10, Apache-2.0, approved, #13257 -maven/mavencentral/software.amazon.awssdk/apache-client/2.25.1, Apache-2.0, approved, #13687 +maven/mavencentral/software.amazon.awssdk/apache-client/2.25.14, Apache-2.0, approved, #13687 maven/mavencentral/software.amazon.awssdk/arns/2.24.10, Apache-2.0, approved, #13243 -maven/mavencentral/software.amazon.awssdk/arns/2.25.1, Apache-2.0, approved, #13695 +maven/mavencentral/software.amazon.awssdk/arns/2.25.14, Apache-2.0, approved, #13695 maven/mavencentral/software.amazon.awssdk/auth/2.24.10, Apache-2.0, approved, #13256 -maven/mavencentral/software.amazon.awssdk/auth/2.25.1, Apache-2.0, approved, #13692 +maven/mavencentral/software.amazon.awssdk/auth/2.25.14, Apache-2.0, approved, #13692 maven/mavencentral/software.amazon.awssdk/aws-core/2.24.10, Apache-2.0, approved, #13240 -maven/mavencentral/software.amazon.awssdk/aws-core/2.25.1, Apache-2.0, approved, #13702 +maven/mavencentral/software.amazon.awssdk/aws-core/2.25.14, Apache-2.0, approved, #13702 maven/mavencentral/software.amazon.awssdk/aws-query-protocol/2.24.10, Apache-2.0, approved, #13262 -maven/mavencentral/software.amazon.awssdk/aws-query-protocol/2.25.1, Apache-2.0, approved, #13701 +maven/mavencentral/software.amazon.awssdk/aws-query-protocol/2.25.14, Apache-2.0, approved, #13701 maven/mavencentral/software.amazon.awssdk/aws-xml-protocol/2.24.10, Apache-2.0, approved, #13247 -maven/mavencentral/software.amazon.awssdk/aws-xml-protocol/2.25.1, Apache-2.0, approved, #13684 +maven/mavencentral/software.amazon.awssdk/aws-xml-protocol/2.25.14, Apache-2.0, approved, #13684 maven/mavencentral/software.amazon.awssdk/checksums-spi/2.24.10, Apache-2.0, approved, #13245 -maven/mavencentral/software.amazon.awssdk/checksums-spi/2.25.1, Apache-2.0, approved, #13686 +maven/mavencentral/software.amazon.awssdk/checksums-spi/2.25.14, Apache-2.0, approved, #13686 maven/mavencentral/software.amazon.awssdk/checksums/2.24.10, Apache-2.0, approved, #13242 -maven/mavencentral/software.amazon.awssdk/checksums/2.25.1, Apache-2.0, approved, #13677 +maven/mavencentral/software.amazon.awssdk/checksums/2.25.14, Apache-2.0, approved, #13677 maven/mavencentral/software.amazon.awssdk/crt-core/2.24.10, Apache-2.0, approved, #13252 -maven/mavencentral/software.amazon.awssdk/crt-core/2.25.1, Apache-2.0, approved, #13705 +maven/mavencentral/software.amazon.awssdk/crt-core/2.25.14, Apache-2.0, approved, #13705 maven/mavencentral/software.amazon.awssdk/endpoints-spi/2.24.10, Apache-2.0, approved, #13246 -maven/mavencentral/software.amazon.awssdk/endpoints-spi/2.25.1, Apache-2.0, approved, #13681 +maven/mavencentral/software.amazon.awssdk/endpoints-spi/2.25.14, Apache-2.0, approved, #13681 maven/mavencentral/software.amazon.awssdk/http-auth-aws/2.24.10, Apache-2.0, approved, #13253 -maven/mavencentral/software.amazon.awssdk/http-auth-aws/2.25.1, Apache-2.0, approved, #13696 +maven/mavencentral/software.amazon.awssdk/http-auth-aws/2.25.14, Apache-2.0, approved, #13696 maven/mavencentral/software.amazon.awssdk/http-auth-spi/2.24.10, Apache-2.0, approved, #13264 -maven/mavencentral/software.amazon.awssdk/http-auth-spi/2.25.1, Apache-2.0, approved, #13704 +maven/mavencentral/software.amazon.awssdk/http-auth-spi/2.25.14, Apache-2.0, approved, #13704 maven/mavencentral/software.amazon.awssdk/http-auth/2.24.10, Apache-2.0, approved, #13248 -maven/mavencentral/software.amazon.awssdk/http-auth/2.25.1, Apache-2.0, approved, #13682 +maven/mavencentral/software.amazon.awssdk/http-auth/2.25.14, Apache-2.0, approved, #13682 maven/mavencentral/software.amazon.awssdk/http-client-spi/2.24.10, Apache-2.0, approved, #13259 -maven/mavencentral/software.amazon.awssdk/http-client-spi/2.25.1, Apache-2.0, approved, #13706 +maven/mavencentral/software.amazon.awssdk/http-client-spi/2.25.14, Apache-2.0, approved, #13706 maven/mavencentral/software.amazon.awssdk/iam/2.24.10, Apache-2.0, approved, #13444 maven/mavencentral/software.amazon.awssdk/identity-spi/2.24.10, Apache-2.0, approved, #13244 -maven/mavencentral/software.amazon.awssdk/identity-spi/2.25.1, Apache-2.0, approved, #13685 +maven/mavencentral/software.amazon.awssdk/identity-spi/2.25.14, Apache-2.0, approved, #13685 maven/mavencentral/software.amazon.awssdk/json-utils/2.24.10, Apache-2.0, approved, #13261 -maven/mavencentral/software.amazon.awssdk/json-utils/2.25.1, Apache-2.0, approved, #13698 +maven/mavencentral/software.amazon.awssdk/json-utils/2.25.14, Apache-2.0, approved, #13698 maven/mavencentral/software.amazon.awssdk/metrics-spi/2.24.10, Apache-2.0, approved, #13239 -maven/mavencentral/software.amazon.awssdk/metrics-spi/2.25.1, Apache-2.0, approved, #13680 +maven/mavencentral/software.amazon.awssdk/metrics-spi/2.25.14, Apache-2.0, approved, #13680 maven/mavencentral/software.amazon.awssdk/netty-nio-client/2.24.10, Apache-2.0, approved, #13260 -maven/mavencentral/software.amazon.awssdk/netty-nio-client/2.25.1, Apache-2.0, approved, #13693 +maven/mavencentral/software.amazon.awssdk/netty-nio-client/2.25.14, Apache-2.0, approved, #13693 maven/mavencentral/software.amazon.awssdk/profiles/2.24.10, Apache-2.0, approved, #13258 -maven/mavencentral/software.amazon.awssdk/profiles/2.25.1, Apache-2.0, approved, #13697 +maven/mavencentral/software.amazon.awssdk/profiles/2.25.14, Apache-2.0, approved, #13697 maven/mavencentral/software.amazon.awssdk/protocol-core/2.24.10, Apache-2.0, approved, #13241 -maven/mavencentral/software.amazon.awssdk/protocol-core/2.25.1, Apache-2.0, approved, #13679 +maven/mavencentral/software.amazon.awssdk/protocol-core/2.25.14, Apache-2.0, approved, #13679 maven/mavencentral/software.amazon.awssdk/regions/2.24.10, Apache-2.0, approved, #13255 -maven/mavencentral/software.amazon.awssdk/regions/2.25.1, Apache-2.0, approved, #13694 -maven/mavencentral/software.amazon.awssdk/s3-transfer-manager/2.25.1, Apache-2.0, approved, #13699 +maven/mavencentral/software.amazon.awssdk/regions/2.25.14, Apache-2.0, approved, #13694 +maven/mavencentral/software.amazon.awssdk/s3-transfer-manager/2.25.14, Apache-2.0, approved, #13699 maven/mavencentral/software.amazon.awssdk/s3/2.24.10, Apache-2.0, approved, #13254 -maven/mavencentral/software.amazon.awssdk/s3/2.25.1, Apache-2.0, approved, #13688 +maven/mavencentral/software.amazon.awssdk/s3/2.25.14, Apache-2.0, approved, #13688 maven/mavencentral/software.amazon.awssdk/sdk-core/2.24.10, Apache-2.0, approved, #13265 -maven/mavencentral/software.amazon.awssdk/sdk-core/2.25.1, Apache-2.0, approved, #13700 +maven/mavencentral/software.amazon.awssdk/sdk-core/2.25.14, Apache-2.0, approved, #13700 maven/mavencentral/software.amazon.awssdk/sts/2.24.10, Apache-2.0, approved, #13442 maven/mavencentral/software.amazon.awssdk/third-party-jackson-core/2.24.10, Apache-2.0, approved, #13249 -maven/mavencentral/software.amazon.awssdk/third-party-jackson-core/2.25.1, Apache-2.0, approved, #13703 +maven/mavencentral/software.amazon.awssdk/third-party-jackson-core/2.25.14, Apache-2.0, approved, #13703 maven/mavencentral/software.amazon.awssdk/utils/2.24.10, Apache-2.0, approved, #13250 -maven/mavencentral/software.amazon.awssdk/utils/2.25.1, Apache-2.0, approved, #13689 +maven/mavencentral/software.amazon.awssdk/utils/2.25.14, Apache-2.0, approved, #13689 maven/mavencentral/software.amazon.eventstream/eventstream/1.0.1, Apache-2.0, approved, clearlydefined diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index f3cad4e18..1cbe7725b 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -6,7 +6,7 @@ edc = "0.5.2-SNAPSHOT" apache-sshd = "2.12.1" assertj = "3.25.3" awaitility = "4.2.0" -aws = "2.25.1" +aws = "2.25.14" azure-identity = "1.11.3" bouncyCastle-jdk18on = "1.77" flyway = "10.8.1" From 0bbf6b5f1647b1833edf5c3f8b14089eb49aa10f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 21 Mar 2024 10:49:18 +0100 Subject: [PATCH 064/100] chore(deps): bump com.azure:azure-identity from 1.11.3 to 1.11.4 (#1131) * chore(deps): bump com.azure:azure-identity from 1.11.3 to 1.11.4 Bumps [com.azure:azure-identity](https://github.com/Azure/azure-sdk-for-java) from 1.11.3 to 1.11.4. - [Release notes](https://github.com/Azure/azure-sdk-for-java/releases) - [Commits](https://github.com/Azure/azure-sdk-for-java/compare/azure-identity_1.11.3...azure-identity_1.11.4) --- updated-dependencies: - dependency-name: com.azure:azure-identity dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] * chore: dependencies file --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Enrico Risa --- DEPENDENCIES | 5 ++++- gradle/libs.versions.toml | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/DEPENDENCIES b/DEPENDENCIES index dafcba4f5..606ee0260 100644 --- a/DEPENDENCIES +++ b/DEPENDENCIES @@ -11,7 +11,7 @@ maven/mavencentral/com.azure/azure-core/1.45.1, MIT AND Apache-2.0, approved, #1 maven/mavencentral/com.azure/azure-core/1.46.0, MIT AND Apache-2.0, approved, #13234 maven/mavencentral/com.azure/azure-core/1.47.0, MIT AND Apache-2.0, approved, #13678 maven/mavencentral/com.azure/azure-identity/1.11.2, MIT AND Apache-2.0, approved, #13237 -maven/mavencentral/com.azure/azure-identity/1.11.3, MIT AND Apache-2.0, approved, #13237 +maven/mavencentral/com.azure/azure-identity/1.11.4, MIT AND Apache-2.0, approved, #13237 maven/mavencentral/com.azure/azure-json/1.1.0, MIT AND Apache-2.0, approved, #10547 maven/mavencentral/com.azure/azure-security-keyvault-secrets/4.7.3, MIT, approved, #10868 maven/mavencentral/com.azure/azure-security-keyvault-secrets/4.8.0, MIT, approved, #13690 @@ -107,14 +107,17 @@ maven/mavencentral/com.jcraft/jzlib/1.1.3, BSD-2-Clause, approved, CQ6218 maven/mavencentral/com.lmax/disruptor/3.4.4, Apache-2.0, approved, clearlydefined maven/mavencentral/com.microsoft.azure/msal4j-persistence-extension/1.2.0, MIT, approved, clearlydefined maven/mavencentral/com.microsoft.azure/msal4j/1.14.0, MIT, approved, clearlydefined +maven/mavencentral/com.microsoft.azure/msal4j/1.14.3, , restricted, clearlydefined maven/mavencentral/com.microsoft.azure/msal4j/1.4.0, MIT, approved, clearlydefined maven/mavencentral/com.networknt/json-schema-validator/1.0.76, Apache-2.0, approved, CQ22638 maven/mavencentral/com.nimbusds/content-type/2.2, Apache-2.0, approved, clearlydefined +maven/mavencentral/com.nimbusds/content-type/2.3, Apache-2.0, approved, clearlydefined maven/mavencentral/com.nimbusds/lang-tag/1.7, Apache-2.0, approved, clearlydefined maven/mavencentral/com.nimbusds/nimbus-jose-jwt/9.28, Apache-2.0, approved, clearlydefined maven/mavencentral/com.nimbusds/nimbus-jose-jwt/9.30.2, Apache-2.0, approved, clearlydefined maven/mavencentral/com.nimbusds/nimbus-jose-jwt/9.37.3, Apache-2.0, approved, #11701 maven/mavencentral/com.nimbusds/oauth2-oidc-sdk/10.7.1, Apache-2.0, approved, clearlydefined +maven/mavencentral/com.nimbusds/oauth2-oidc-sdk/11.9.1, Apache-2.0, approved, #12667 maven/mavencentral/com.puppycrawl.tools/checkstyle/10.14.2, LGPL-2.1-or-later AND (Apache-2.0 AND LGPL-2.1-or-later) AND Apache-2.0, approved, #13562 maven/mavencentral/com.samskivert/jmustache/1.15, BSD-2-Clause, approved, clearlydefined maven/mavencentral/com.squareup.okhttp3/mockwebserver/5.0.0-alpha.12, Apache-2.0, approved, clearlydefined diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 1cbe7725b..4fbe689ce 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -7,7 +7,7 @@ apache-sshd = "2.12.1" assertj = "3.25.3" awaitility = "4.2.0" aws = "2.25.14" -azure-identity = "1.11.3" +azure-identity = "1.11.4" bouncyCastle-jdk18on = "1.77" flyway = "10.8.1" iron-vc = "0.14.0" From ea2f7d62452f3379327de7201f67131c9b8cd6fb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 21 Mar 2024 11:22:54 +0100 Subject: [PATCH 065/100] chore(deps): bump flyway from 10.8.1 to 10.10.0 (#1130) * chore(deps): bump flyway from 10.8.1 to 10.10.0 Bumps `flyway` from 10.8.1 to 10.10.0. Updates `org.flywaydb:flyway-core` from 10.8.1 to 10.10.0 - [Release notes](https://github.com/flyway/flyway/releases) - [Commits](https://github.com/flyway/flyway/compare/flyway-10.8.1...flyway-10.10.0) Updates `org.flywaydb:flyway-database-postgresql` from 10.8.1 to 10.10.0 --- updated-dependencies: - dependency-name: org.flywaydb:flyway-core dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: org.flywaydb:flyway-database-postgresql dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * chore: dependencies file --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Enrico Risa --- DEPENDENCIES | 4 ++-- gradle/libs.versions.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/DEPENDENCIES b/DEPENDENCIES index 606ee0260..cf542888e 100644 --- a/DEPENDENCIES +++ b/DEPENDENCIES @@ -518,8 +518,8 @@ maven/mavencentral/org.eclipse.jetty/jetty-servlet/11.0.20, EPL-2.0 OR Apache-2. maven/mavencentral/org.eclipse.jetty/jetty-util/11.0.20, EPL-2.0 OR Apache-2.0, approved, rt.jetty maven/mavencentral/org.eclipse.jetty/jetty-webapp/11.0.20, EPL-2.0 OR Apache-2.0, approved, rt.jetty maven/mavencentral/org.eclipse.jetty/jetty-xml/11.0.20, EPL-2.0 OR Apache-2.0, approved, rt.jetty -maven/mavencentral/org.flywaydb/flyway-core/10.8.1, Apache-2.0, approved, #13291 -maven/mavencentral/org.flywaydb/flyway-database-postgresql/10.8.1, Apache-2.0, approved, #13290 +maven/mavencentral/org.flywaydb/flyway-core/10.10.0, , restricted, clearlydefined +maven/mavencentral/org.flywaydb/flyway-database-postgresql/10.10.0, , restricted, clearlydefined maven/mavencentral/org.glassfish.hk2.external/aopalliance-repackaged/3.0.5, EPL-2.0 OR GPL-2.0-only with Classpath-exception-2.0, approved, ee4j.glassfish maven/mavencentral/org.glassfish.hk2/hk2-api/3.0.5, EPL-2.0 OR GPL-2.0-only with Classpath-exception-2.0, approved, ee4j.glassfish maven/mavencentral/org.glassfish.hk2/hk2-locator/3.0.5, EPL-2.0 OR GPL-2.0-only with Classpath-exception-2.0, approved, ee4j.glassfish diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 4fbe689ce..0eb2ca934 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -9,7 +9,7 @@ awaitility = "4.2.0" aws = "2.25.14" azure-identity = "1.11.4" bouncyCastle-jdk18on = "1.77" -flyway = "10.8.1" +flyway = "10.10.0" iron-vc = "0.14.0" jackson = "2.17.0" jakarta-json = "2.0.1" From 1121a043837e3fcaa788dec850687aaa0568d977 Mon Sep 17 00:00:00 2001 From: Enrico Risa Date: Fri, 22 Mar 2024 10:13:23 +0100 Subject: [PATCH 066/100] chore: fix compile issue after upstream EDC module changes (#1149) * chore: fix compile issue after upstream EDC module changes * chore: dependencies file --- DEPENDENCIES | 2 ++ .../edc-runtime-memory/build.gradle.kts | 1 + .../edc/vault/memory/VaultSeedExtensionTest.java | 2 +- .../token-refresh-core/build.gradle.kts | 2 ++ ...laneTokenRefreshServiceImplComponentTest.java | 2 +- edc-tests/e2e-tests/build.gradle.kts | 1 + .../edc/lifecycle/PgParticipantRuntime.java | 2 +- .../tractusx/edc/lifecycle/tx/TxParticipant.java | 2 +- .../edc/lifecycle/tx/iatp/IatpParticipant.java | 2 +- .../lifecycle/tx/iatp/SecureTokenService.java | 2 +- .../edc/tests/edrv2/EdrCacheApiEndToEndTest.java | 2 +- .../edc-controlplane/fixtures/build.gradle.kts | 1 + .../tractusx/edc/tests/TxParticipant.java | 2 +- .../edc/tests/runtimes/PgParticipantRuntime.java | 16 ++++++++-------- ...DimHttpConsumerPullWithProxyInMemoryTest.java | 2 +- .../edc/tests/transfer/iatp/IatpParticipant.java | 2 +- .../iatp/harness/SecureTokenService.java | 2 +- .../tractusx/edc/tests/SsiParticipant.java | 2 +- .../transfer/test/AzureToAzureTest.java | 2 +- .../dataplane/transfer/test/MultiCloudTest.java | 2 +- .../dataplane/transfer/test/RuntimeConfig.java | 2 +- .../edc/dataplane/transfer/test/S3ToS3Test.java | 2 +- .../tokenrefresh/e2e/RuntimeConfig.java | 2 +- edc-tests/miw-tests/build.gradle.kts | 1 + .../tractusx/edc/tests/miw/WalletTest.java | 2 +- gradle/libs.versions.toml | 3 +++ 26 files changed, 37 insertions(+), 26 deletions(-) diff --git a/DEPENDENCIES b/DEPENDENCIES index cf542888e..645b758fc 100644 --- a/DEPENDENCIES +++ b/DEPENDENCIES @@ -352,6 +352,7 @@ maven/mavencentral/org.eclipse.edc/aws-s3-core/0.5.2-SNAPSHOT, Apache-2.0, appro maven/mavencentral/org.eclipse.edc/aws-s3-test/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/azure-blob-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/azure-test/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/boot-lib/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/boot/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/callback-event-dispatcher/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/callback-http-dispatcher/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc @@ -416,6 +417,7 @@ maven/mavencentral/org.eclipse.edc/dsp/0.5.2-SNAPSHOT, Apache-2.0, approved, tec maven/mavencentral/org.eclipse.edc/edr-store-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/edr-store-receiver/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/edr-store-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/http-lib/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/http-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/http/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/iam-mock/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc diff --git a/edc-controlplane/edc-runtime-memory/build.gradle.kts b/edc-controlplane/edc-runtime-memory/build.gradle.kts index c5491e8b3..5e154d725 100644 --- a/edc-controlplane/edc-runtime-memory/build.gradle.kts +++ b/edc-controlplane/edc-runtime-memory/build.gradle.kts @@ -31,6 +31,7 @@ dependencies { runtimeOnly(project(":edc-dataplane:edc-dataplane-base")) runtimeOnly(libs.edc.core.controlplane) testImplementation(libs.edc.junit) + testImplementation(libs.edc.lib.boot) } tasks.withType { diff --git a/edc-controlplane/edc-runtime-memory/src/test/java/org/eclipse/tractusx/edc/vault/memory/VaultSeedExtensionTest.java b/edc-controlplane/edc-runtime-memory/src/test/java/org/eclipse/tractusx/edc/vault/memory/VaultSeedExtensionTest.java index 2eb407ce0..d01e055d3 100644 --- a/edc-controlplane/edc-runtime-memory/src/test/java/org/eclipse/tractusx/edc/vault/memory/VaultSeedExtensionTest.java +++ b/edc-controlplane/edc-runtime-memory/src/test/java/org/eclipse/tractusx/edc/vault/memory/VaultSeedExtensionTest.java @@ -19,7 +19,7 @@ package org.eclipse.tractusx.edc.vault.memory; -import org.eclipse.edc.connector.core.vault.InMemoryVault; +import org.eclipse.edc.boot.vault.InMemoryVault; import org.eclipse.edc.junit.extensions.DependencyInjectionExtension; import org.eclipse.edc.spi.monitor.Monitor; import org.eclipse.edc.spi.security.Vault; diff --git a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/build.gradle.kts b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/build.gradle.kts index 1597ed047..98db1457e 100644 --- a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/build.gradle.kts +++ b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/build.gradle.kts @@ -31,6 +31,8 @@ dependencies { testImplementation(libs.edc.junit) testImplementation(libs.edc.dpf.core) + testImplementation(libs.edc.core.connector) testImplementation(libs.edc.common.crypto) + testImplementation(libs.edc.lib.boot) } diff --git a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImplComponentTest.java b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImplComponentTest.java index 82707a82e..be0889076 100644 --- a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImplComponentTest.java +++ b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImplComponentTest.java @@ -29,8 +29,8 @@ import com.nimbusds.jose.jwk.gen.ECKeyGenerator; import com.nimbusds.jwt.JWTClaimsSet; import com.nimbusds.jwt.SignedJWT; +import org.eclipse.edc.boot.vault.InMemoryVault; import org.eclipse.edc.connector.core.store.CriterionOperatorRegistryImpl; -import org.eclipse.edc.connector.core.vault.InMemoryVault; import org.eclipse.edc.connector.dataplane.framework.store.InMemoryAccessTokenDataStore; import org.eclipse.edc.iam.did.spi.resolution.DidPublicKeyResolver; import org.eclipse.edc.junit.annotations.ComponentTest; diff --git a/edc-tests/e2e-tests/build.gradle.kts b/edc-tests/e2e-tests/build.gradle.kts index d0ee8cf35..fe151453d 100644 --- a/edc-tests/e2e-tests/build.gradle.kts +++ b/edc-tests/e2e-tests/build.gradle.kts @@ -47,6 +47,7 @@ dependencies { testImplementation(libs.edc.ih.spi.store) testImplementation(libs.edc.identity.trust.sts.embedded) testImplementation(libs.edc.token.core) + testImplementation(libs.edc.lib.boot) testImplementation(testFixtures(libs.edc.sql.core)) testImplementation(testFixtures(libs.edc.api.management.test.fixtures)) testImplementation(libs.awaitility) diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/PgParticipantRuntime.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/PgParticipantRuntime.java index 4682bab19..d5a5f2174 100644 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/PgParticipantRuntime.java +++ b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/PgParticipantRuntime.java @@ -19,7 +19,7 @@ package org.eclipse.tractusx.edc.lifecycle; -import org.eclipse.edc.connector.core.vault.InMemoryVault; +import org.eclipse.edc.boot.vault.InMemoryVault; import org.eclipse.edc.spi.monitor.Monitor; import org.eclipse.edc.spi.result.Result; import org.eclipse.edc.spi.security.Vault; diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/tx/TxParticipant.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/tx/TxParticipant.java index 0bae06240..277fa67af 100644 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/tx/TxParticipant.java +++ b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/tx/TxParticipant.java @@ -37,7 +37,7 @@ import static org.eclipse.edc.jsonld.spi.PropertyAndTypeNames.ODRL_ASSIGNER_ATTRIBUTE; import static org.eclipse.edc.jsonld.spi.PropertyAndTypeNames.ODRL_POLICY_ATTRIBUTE; import static org.eclipse.edc.jsonld.spi.PropertyAndTypeNames.ODRL_TARGET_ATTRIBUTE; -import static org.eclipse.edc.junit.testfixtures.TestUtils.getFreePort; +import static org.eclipse.edc.util.io.Ports.getFreePort; import static org.eclipse.tractusx.edc.helpers.PolicyHelperFunctions.TX_NAMESPACE; import static org.eclipse.tractusx.edc.tests.TestCommon.ASYNC_TIMEOUT; diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/tx/iatp/IatpParticipant.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/tx/iatp/IatpParticipant.java index d992a2f96..4cb827626 100644 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/tx/iatp/IatpParticipant.java +++ b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/tx/iatp/IatpParticipant.java @@ -38,7 +38,7 @@ import java.util.stream.Stream; import static java.lang.String.format; -import static org.eclipse.edc.junit.testfixtures.TestUtils.getFreePort; +import static org.eclipse.edc.util.io.Ports.getFreePort; import static org.eclipse.tractusx.edc.helpers.IatpHelperFunctions.generateKeyPair; import static org.eclipse.tractusx.edc.helpers.IatpHelperFunctions.toPemEncoded; import static org.eclipse.tractusx.edc.lifecycle.tx.iatp.DataspaceIssuer.DATASPACE_ISSUER; diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/tx/iatp/SecureTokenService.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/tx/iatp/SecureTokenService.java index 1b29f83b7..a556dda33 100644 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/tx/iatp/SecureTokenService.java +++ b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/tx/iatp/SecureTokenService.java @@ -28,7 +28,7 @@ import java.util.UUID; import static java.lang.String.format; -import static org.eclipse.edc.junit.testfixtures.TestUtils.getFreePort; +import static org.eclipse.edc.util.io.Ports.getFreePort; /** * STS configurations diff --git a/edc-tests/edc-controlplane/edr-api-tests/src/test/java/org/eclipse/tractusx/edc/tests/edrv2/EdrCacheApiEndToEndTest.java b/edc-tests/edc-controlplane/edr-api-tests/src/test/java/org/eclipse/tractusx/edc/tests/edrv2/EdrCacheApiEndToEndTest.java index af7f92dbf..27729eb6d 100644 --- a/edc-tests/edc-controlplane/edr-api-tests/src/test/java/org/eclipse/tractusx/edc/tests/edrv2/EdrCacheApiEndToEndTest.java +++ b/edc-tests/edc-controlplane/edr-api-tests/src/test/java/org/eclipse/tractusx/edc/tests/edrv2/EdrCacheApiEndToEndTest.java @@ -55,8 +55,8 @@ import java.util.Map; import static org.assertj.core.api.Assertions.assertThat; -import static org.eclipse.edc.junit.testfixtures.TestUtils.getFreePort; import static org.eclipse.edc.spi.CoreConstants.EDC_NAMESPACE; +import static org.eclipse.edc.util.io.Ports.getFreePort; import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.TX_AUTH_NS; import static org.mockserver.integration.ClientAndServer.startClientAndServer; import static org.mockserver.matchers.Times.exactly; diff --git a/edc-tests/edc-controlplane/fixtures/build.gradle.kts b/edc-tests/edc-controlplane/fixtures/build.gradle.kts index f6742a42f..79fa980f2 100644 --- a/edc-tests/edc-controlplane/fixtures/build.gradle.kts +++ b/edc-tests/edc-controlplane/fixtures/build.gradle.kts @@ -35,6 +35,7 @@ dependencies { testFixturesApi(testFixtures(libs.edc.api.management.test.fixtures)) testFixturesApi(libs.edc.spi.edrstore) testFixturesApi(libs.edc.common.crypto) + testFixturesApi(libs.edc.lib.boot) // api modules for some test utils testFixturesApi(libs.netty.mockserver) diff --git a/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/TxParticipant.java b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/TxParticipant.java index 691437380..b17fb24ac 100644 --- a/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/TxParticipant.java +++ b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/TxParticipant.java @@ -34,7 +34,7 @@ import static jakarta.json.Json.createObjectBuilder; import static java.time.Duration.ofSeconds; import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.ID; -import static org.eclipse.edc.junit.testfixtures.TestUtils.getFreePort; +import static org.eclipse.edc.util.io.Ports.getFreePort; import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.TX_NAMESPACE; public class TxParticipant extends IdentityParticipant { diff --git a/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/runtimes/PgParticipantRuntime.java b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/runtimes/PgParticipantRuntime.java index 5088e942c..8300d892d 100644 --- a/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/runtimes/PgParticipantRuntime.java +++ b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/runtimes/PgParticipantRuntime.java @@ -19,7 +19,7 @@ package org.eclipse.tractusx.edc.tests.runtimes; -import org.eclipse.edc.connector.core.vault.InMemoryVault; +import org.eclipse.edc.boot.vault.InMemoryVault; import org.eclipse.edc.spi.monitor.ConsoleMonitor; import org.eclipse.edc.spi.monitor.Monitor; import org.eclipse.edc.spi.result.Result; @@ -77,6 +77,13 @@ public void afterAll(ExtensionContext context) throws Exception { postgreSqlContainer.close(); } + @Override + protected void bootExtensions(ServiceExtensionContext context, List> serviceExtensions) { + PostgresqlLocalInstance helper = new PostgresqlLocalInstance(postgreSqlContainer.getUsername(), postgreSqlContainer.getPassword(), baseJdbcUrl(), postgreSqlContainer.getDatabaseName()); + helper.createDatabase(); + super.bootExtensions(context, serviceExtensions); + } + public Map postgresqlConfiguration(String name) { var jdbcUrl = jdbcUrl(name); return new HashMap<>() { @@ -103,13 +110,6 @@ public String baseJdbcUrl() { return format("jdbc:postgresql://%s:%s/", postgreSqlContainer.getHost(), postgreSqlContainer.getFirstMappedPort()); } - @Override - protected void bootExtensions(ServiceExtensionContext context, List> serviceExtensions) { - PostgresqlLocalInstance helper = new PostgresqlLocalInstance(postgreSqlContainer.getUsername(), postgreSqlContainer.getPassword(), baseJdbcUrl(), postgreSqlContainer.getDatabaseName()); - helper.createDatabase(); - super.bootExtensions(context, serviceExtensions); - } - protected void mockVault() { this.registerServiceMock(Vault.class, new InMemoryVaultOverride(new ConsoleMonitor())); } diff --git a/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/DimHttpConsumerPullWithProxyInMemoryTest.java b/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/DimHttpConsumerPullWithProxyInMemoryTest.java index 91eaee3cc..f9f9ea2d0 100644 --- a/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/DimHttpConsumerPullWithProxyInMemoryTest.java +++ b/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/DimHttpConsumerPullWithProxyInMemoryTest.java @@ -44,7 +44,7 @@ import java.util.Map; import java.util.function.Supplier; -import static org.eclipse.edc.junit.testfixtures.TestUtils.getFreePort; +import static org.eclipse.edc.util.io.Ports.getFreePort; import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.CX_CREDENTIAL_NS; import static org.eclipse.tractusx.edc.tests.helpers.PolicyHelperFunctions.frameworkPolicy; import static org.eclipse.tractusx.edc.tests.transfer.iatp.harness.IatpHelperFunctions.configureParticipant; diff --git a/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/iatp/IatpParticipant.java b/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/iatp/IatpParticipant.java index fcaea780b..f0a205c1b 100644 --- a/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/iatp/IatpParticipant.java +++ b/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/iatp/IatpParticipant.java @@ -33,7 +33,7 @@ import java.util.Map; import java.util.stream.Stream; -import static org.eclipse.edc.junit.testfixtures.TestUtils.getFreePort; +import static org.eclipse.edc.util.io.Ports.getFreePort; import static org.eclipse.tractusx.edc.tests.transfer.iatp.harness.DataspaceIssuer.DATASPACE_ISSUER; /** diff --git a/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/iatp/harness/SecureTokenService.java b/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/iatp/harness/SecureTokenService.java index 9e8345ff1..190a74742 100644 --- a/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/iatp/harness/SecureTokenService.java +++ b/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/iatp/harness/SecureTokenService.java @@ -31,7 +31,7 @@ import java.util.UUID; import static java.lang.String.format; -import static org.eclipse.edc.junit.testfixtures.TestUtils.getFreePort; +import static org.eclipse.edc.util.io.Ports.getFreePort; /** * STS configurations diff --git a/edc-tests/edc-controlplane/ssi-summarycred-tests/src/test/java/org/eclipse/tractusx/edc/tests/SsiParticipant.java b/edc-tests/edc-controlplane/ssi-summarycred-tests/src/test/java/org/eclipse/tractusx/edc/tests/SsiParticipant.java index ee79d84e5..38faa7f1c 100644 --- a/edc-tests/edc-controlplane/ssi-summarycred-tests/src/test/java/org/eclipse/tractusx/edc/tests/SsiParticipant.java +++ b/edc-tests/edc-controlplane/ssi-summarycred-tests/src/test/java/org/eclipse/tractusx/edc/tests/SsiParticipant.java @@ -23,7 +23,7 @@ import java.util.HashMap; import java.util.Map; -import static org.eclipse.edc.junit.testfixtures.TestUtils.getFreePort; +import static org.eclipse.edc.util.io.Ports.getFreePort; public class SsiParticipant { diff --git a/edc-tests/edc-dataplane/cloud-transfer-tests/src/test/java/org/eclipse/tractusx/edc/dataplane/transfer/test/AzureToAzureTest.java b/edc-tests/edc-dataplane/cloud-transfer-tests/src/test/java/org/eclipse/tractusx/edc/dataplane/transfer/test/AzureToAzureTest.java index 6b4846d95..ad62b71cd 100644 --- a/edc-tests/edc-dataplane/cloud-transfer-tests/src/test/java/org/eclipse/tractusx/edc/dataplane/transfer/test/AzureToAzureTest.java +++ b/edc-tests/edc-dataplane/cloud-transfer-tests/src/test/java/org/eclipse/tractusx/edc/dataplane/transfer/test/AzureToAzureTest.java @@ -37,7 +37,7 @@ import static io.restassured.RestAssured.given; import static org.assertj.core.api.Assertions.assertThat; -import static org.eclipse.edc.junit.testfixtures.TestUtils.getFreePort; +import static org.eclipse.edc.util.io.Ports.getFreePort; import static org.eclipse.tractusx.edc.dataplane.transfer.test.TestConstants.AZBLOB_CONSUMER_ACCOUNT_KEY; import static org.eclipse.tractusx.edc.dataplane.transfer.test.TestConstants.AZBLOB_CONSUMER_ACCOUNT_NAME; import static org.eclipse.tractusx.edc.dataplane.transfer.test.TestConstants.AZBLOB_CONSUMER_CONTAINER_NAME; diff --git a/edc-tests/edc-dataplane/cloud-transfer-tests/src/test/java/org/eclipse/tractusx/edc/dataplane/transfer/test/MultiCloudTest.java b/edc-tests/edc-dataplane/cloud-transfer-tests/src/test/java/org/eclipse/tractusx/edc/dataplane/transfer/test/MultiCloudTest.java index 06cad6f16..fda365150 100644 --- a/edc-tests/edc-dataplane/cloud-transfer-tests/src/test/java/org/eclipse/tractusx/edc/dataplane/transfer/test/MultiCloudTest.java +++ b/edc-tests/edc-dataplane/cloud-transfer-tests/src/test/java/org/eclipse/tractusx/edc/dataplane/transfer/test/MultiCloudTest.java @@ -48,7 +48,7 @@ import static io.restassured.RestAssured.given; import static org.assertj.core.api.Assertions.assertThat; -import static org.eclipse.edc.junit.testfixtures.TestUtils.getFreePort; +import static org.eclipse.edc.util.io.Ports.getFreePort; import static org.eclipse.tractusx.edc.dataplane.transfer.test.TestConstants.AZBLOB_CONSUMER_ACCOUNT_KEY; import static org.eclipse.tractusx.edc.dataplane.transfer.test.TestConstants.AZBLOB_CONSUMER_ACCOUNT_NAME; import static org.eclipse.tractusx.edc.dataplane.transfer.test.TestConstants.AZBLOB_CONSUMER_CONTAINER_NAME; diff --git a/edc-tests/edc-dataplane/cloud-transfer-tests/src/test/java/org/eclipse/tractusx/edc/dataplane/transfer/test/RuntimeConfig.java b/edc-tests/edc-dataplane/cloud-transfer-tests/src/test/java/org/eclipse/tractusx/edc/dataplane/transfer/test/RuntimeConfig.java index 896131a74..dbf85bb19 100644 --- a/edc-tests/edc-dataplane/cloud-transfer-tests/src/test/java/org/eclipse/tractusx/edc/dataplane/transfer/test/RuntimeConfig.java +++ b/edc-tests/edc-dataplane/cloud-transfer-tests/src/test/java/org/eclipse/tractusx/edc/dataplane/transfer/test/RuntimeConfig.java @@ -22,7 +22,7 @@ import java.util.HashMap; import java.util.Map; -import static org.eclipse.edc.junit.testfixtures.TestUtils.getFreePort; +import static org.eclipse.edc.util.io.Ports.getFreePort; /** * Configuration baseline for Data-Plane e2e tests diff --git a/edc-tests/edc-dataplane/cloud-transfer-tests/src/test/java/org/eclipse/tractusx/edc/dataplane/transfer/test/S3ToS3Test.java b/edc-tests/edc-dataplane/cloud-transfer-tests/src/test/java/org/eclipse/tractusx/edc/dataplane/transfer/test/S3ToS3Test.java index afe18f394..e4b18e4ba 100644 --- a/edc-tests/edc-dataplane/cloud-transfer-tests/src/test/java/org/eclipse/tractusx/edc/dataplane/transfer/test/S3ToS3Test.java +++ b/edc-tests/edc-dataplane/cloud-transfer-tests/src/test/java/org/eclipse/tractusx/edc/dataplane/transfer/test/S3ToS3Test.java @@ -54,7 +54,7 @@ import static io.restassured.RestAssured.given; import static org.assertj.core.api.Assertions.assertThat; -import static org.eclipse.edc.junit.testfixtures.TestUtils.getFreePort; +import static org.eclipse.edc.util.io.Ports.getFreePort; import static org.eclipse.tractusx.edc.dataplane.transfer.test.TestConstants.MINIO_CONTAINER_PORT; import static org.eclipse.tractusx.edc.dataplane.transfer.test.TestConstants.MINIO_DOCKER_IMAGE; import static org.eclipse.tractusx.edc.dataplane.transfer.test.TestConstants.S3_ACCESS_KEY_ID; diff --git a/edc-tests/edc-dataplane/edc-dataplane-tokenrefresh-tests/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/e2e/RuntimeConfig.java b/edc-tests/edc-dataplane/edc-dataplane-tokenrefresh-tests/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/e2e/RuntimeConfig.java index 11c8da8fe..a69c5f3a6 100644 --- a/edc-tests/edc-dataplane/edc-dataplane-tokenrefresh-tests/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/e2e/RuntimeConfig.java +++ b/edc-tests/edc-dataplane/edc-dataplane-tokenrefresh-tests/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/e2e/RuntimeConfig.java @@ -26,7 +26,7 @@ import java.util.Map; import static io.restassured.RestAssured.given; -import static org.eclipse.edc.junit.testfixtures.TestUtils.getFreePort; +import static org.eclipse.edc.util.io.Ports.getFreePort; /** * Configuration baseline for Data-Plane e2e tests diff --git a/edc-tests/miw-tests/build.gradle.kts b/edc-tests/miw-tests/build.gradle.kts index 4f8b2d16a..145375cb9 100644 --- a/edc-tests/miw-tests/build.gradle.kts +++ b/edc-tests/miw-tests/build.gradle.kts @@ -42,6 +42,7 @@ dependencies { testImplementation(libs.edc.spi.dataplane.selector) testImplementation(libs.edc.ext.jsonld) testImplementation(libs.edc.dsp) + testImplementation(libs.edc.lib.http) testImplementation(testFixtures(libs.edc.sql.core)) diff --git a/edc-tests/miw-tests/src/test/java/org/eclipse/tractusx/edc/tests/miw/WalletTest.java b/edc-tests/miw-tests/src/test/java/org/eclipse/tractusx/edc/tests/miw/WalletTest.java index bf3192c5d..a93595301 100644 --- a/edc-tests/miw-tests/src/test/java/org/eclipse/tractusx/edc/tests/miw/WalletTest.java +++ b/edc-tests/miw-tests/src/test/java/org/eclipse/tractusx/edc/tests/miw/WalletTest.java @@ -37,11 +37,11 @@ import dev.failsafe.RetryPolicy; import jakarta.json.Json; import okhttp3.OkHttpClient; -import org.eclipse.edc.connector.core.base.EdcHttpClientImpl; import org.eclipse.edc.iam.oauth2.client.Oauth2ClientImpl; import org.eclipse.edc.jsonld.util.JacksonJsonLd; import org.eclipse.edc.spi.monitor.Monitor; import org.eclipse.edc.spi.types.TypeManager; +import org.eclipse.http.client.EdcHttpClientImpl; import org.eclipse.tractusx.edc.iam.ssi.miw.api.MiwApiClient; import org.eclipse.tractusx.edc.iam.ssi.miw.api.MiwApiClientImpl; import org.eclipse.tractusx.edc.iam.ssi.miw.oauth2.MiwOauth2ClientConfiguration; diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 0eb2ca934..1e6183829 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -91,6 +91,9 @@ edc-ext-azure-test = { module = "org.eclipse.edc:azure-test", version.ref = "edc edc-ext-jsonld = { module = "org.eclipse.edc:json-ld", version.ref = "edc" } edc-ext-jersey-providers = { module = "org.eclipse.edc:jersey-providers", version.ref = "edc" } edc-validator-data-address-http-data = { module = "org.eclipse.edc:validator-data-address-http-data", version.ref = "edc" } +edc-lib-boot = { module = "org.eclipse.edc:boot-lib", version.ref = "edc" } +edc-lib-http = { module = "org.eclipse.edc:http-lib", version.ref = "edc" } + # implementations edc-sql-assetindex = { module = "org.eclipse.edc:asset-index-sql", version.ref = "edc" } From 08aab917406d12a641e441b66c8e954422bc9b22 Mon Sep 17 00:00:00 2001 From: Enrico Risa Date: Fri, 22 Mar 2024 21:59:38 +0100 Subject: [PATCH 067/100] feat: adds Catalog and Transfer integration test with DIM (#1152) --- .github/workflows/verify-dim.yaml | 36 ++ DEPENDENCIES | 2 +- .../cx/common/CredentialTypePredicate.java | 37 --- .../cx/common/CredentialTypePredicate.java | 10 +- ...ismantlerCredentialConstraintFunction.java | 2 +- ...AgreementCredentialConstraintFunction.java | 2 +- ...embershipCredentialConstraintFunction.java | 2 +- .../iatp/sts/dim/DimSecureTokenService.java | 4 +- .../sts/dim/DimSecureTokenServiceTest.java | 8 +- edc-tests/e2e-tests/build.gradle.kts | 42 +-- .../tractusx/edc/did/DidExampleResolver.java | 62 ---- .../edc/helpers/CatalogHelperFunctions.java | 45 --- .../tractusx/edc/helpers/DimHelper.java | 61 ++++ .../edc/helpers/IatpHelperFunctions.java | 172 ---------- .../edc/helpers/PolicyHelperFunctions.java | 203 ------------ .../tractusx/edc/helpers/ReceivedEvent.java | 61 ---- .../TransferProcessHelperFunctions.java | 38 --- .../tractusx/edc/lifecycle/DataWiper.java | 4 +- .../edc/lifecycle/DimParticipant.java | 66 ++++ .../edc/lifecycle/MiwParticipant.java | 82 +++++ .../edc/lifecycle/ParticipantRuntime.java | 38 ++- .../PgHashicorpParticipantRuntime.java | 74 ----- .../edc/lifecycle/PgParticipantRuntime.java | 128 -------- .../Runtimes.java} | 14 +- .../edc/lifecycle/tx/ParticipantDataApi.java | 56 ---- .../edc/lifecycle/tx/ParticipantEdrApi.java | 62 ---- .../edc/lifecycle/tx/TxParticipant.java | 310 ------------------ .../lifecycle/tx/iatp/DataspaceIssuer.java | 183 ----------- .../lifecycle/tx/iatp/IatpDimParticipant.java | 45 --- .../lifecycle/tx/iatp/IatpParticipant.java | 165 ---------- .../lifecycle/tx/iatp/SecureTokenService.java | 82 ----- .../DimIntegrationTest.java} | 23 +- .../edc/tests/catalog/DimCatalogTest.java | 84 +++++ .../edc/tests/catalog/MiwSsiCatalogTest.java | 75 +---- .../transfer/DimHttpPullTransferTest.java | 56 ++++ .../edc/token/MockBpnIdentityService.java | 70 ---- .../tractusx/edc/tests/ParticipantEdrApi.java | 5 +- .../tests/TractusxIatpParticipantBase.java | 107 ++++++ .../edc/tests/TractusxParticipantBase.java | 176 ++++++++++ .../transfer/HttpConsumerPullBaseTest.java | 129 ++++++++ ...HttpConsumerPullWithProxyInMemoryTest.java | 2 +- .../runtime-memory-iatp-dim}/build.gradle.kts | 18 +- .../runtime-postgresql-hashicorp/README.md | 3 - settings.gradle.kts | 2 +- 44 files changed, 891 insertions(+), 1955 deletions(-) create mode 100644 .github/workflows/verify-dim.yaml delete mode 100644 edc-extensions/cx-policy-legacy/src/main/java/org/eclipse/tractusx/edc/policy/cx/common/CredentialTypePredicate.java delete mode 100644 edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/did/DidExampleResolver.java delete mode 100644 edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/helpers/CatalogHelperFunctions.java create mode 100644 edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/helpers/DimHelper.java delete mode 100644 edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/helpers/IatpHelperFunctions.java delete mode 100644 edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/helpers/PolicyHelperFunctions.java delete mode 100644 edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/helpers/ReceivedEvent.java delete mode 100644 edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/helpers/TransferProcessHelperFunctions.java create mode 100644 edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/DimParticipant.java create mode 100644 edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/MiwParticipant.java delete mode 100644 edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/PgHashicorpParticipantRuntime.java delete mode 100644 edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/PgParticipantRuntime.java rename edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/{tests/TestCommon.java => lifecycle/Runtimes.java} (73%) delete mode 100644 edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/tx/ParticipantDataApi.java delete mode 100644 edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/tx/ParticipantEdrApi.java delete mode 100644 edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/tx/TxParticipant.java delete mode 100644 edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/tx/iatp/DataspaceIssuer.java delete mode 100644 edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/tx/iatp/IatpDimParticipant.java delete mode 100644 edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/tx/iatp/IatpParticipant.java delete mode 100644 edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/tx/iatp/SecureTokenService.java rename edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/{lifecycle/TestRuntimeConfiguration.java => tag/DimIntegrationTest.java} (67%) create mode 100644 edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/catalog/DimCatalogTest.java create mode 100644 edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/DimHttpPullTransferTest.java delete mode 100644 edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/token/MockBpnIdentityService.java create mode 100644 edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/TractusxIatpParticipantBase.java create mode 100644 edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/TractusxParticipantBase.java create mode 100644 edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/transfer/HttpConsumerPullBaseTest.java rename edc-tests/runtime/{runtime-postgresql-hashicorp => iatp/runtime-memory-iatp-dim}/build.gradle.kts (69%) delete mode 100644 edc-tests/runtime/runtime-postgresql-hashicorp/README.md diff --git a/.github/workflows/verify-dim.yaml b/.github/workflows/verify-dim.yaml new file mode 100644 index 000000000..091c788f8 --- /dev/null +++ b/.github/workflows/verify-dim.yaml @@ -0,0 +1,36 @@ +################################################################################# +# Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License, Version 2.0 which is available at +# https://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. +# +# SPDX-License-Identifier: Apache-2.0 +################################################################################# + +name: "Verify DIM" + +on: + schedule: + - cron: '0 0 * * *' + workflow_dispatch: + +jobs: + dim-integration-tests: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: ./.github/actions/setup-java + + - name: Run DIM Integration tests + run: ./gradlew test -DincludeTags="DimIntegrationTest" \ No newline at end of file diff --git a/DEPENDENCIES b/DEPENDENCIES index 645b758fc..16d215fe2 100644 --- a/DEPENDENCIES +++ b/DEPENDENCIES @@ -423,6 +423,7 @@ maven/mavencentral/org.eclipse.edc/http/0.5.2-SNAPSHOT, Apache-2.0, approved, te maven/mavencentral/org.eclipse.edc/iam-mock/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/identity-did-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/identity-did-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-did-web/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/identity-hub-api/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/identity-hub-credentials/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/identity-hub-did-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc @@ -613,7 +614,6 @@ maven/mavencentral/org.testcontainers/junit-jupiter/1.19.6, MIT, approved, #1034 maven/mavencentral/org.testcontainers/junit-jupiter/1.19.7, MIT, approved, #10344 maven/mavencentral/org.testcontainers/postgresql/1.19.7, MIT, approved, #10350 maven/mavencentral/org.testcontainers/testcontainers/1.19.7, Apache-2.0 AND MIT, approved, #10347 -maven/mavencentral/org.testcontainers/vault/1.19.7, MIT, approved, #10852 maven/mavencentral/org.xmlresolver/xmlresolver/5.2.2, Apache-2.0, approved, clearlydefined maven/mavencentral/org.xmlunit/xmlunit-core/2.9.1, Apache-2.0, approved, #6272 maven/mavencentral/org.xmlunit/xmlunit-placeholders/2.9.1, Apache-2.0, approved, clearlydefined diff --git a/edc-extensions/cx-policy-legacy/src/main/java/org/eclipse/tractusx/edc/policy/cx/common/CredentialTypePredicate.java b/edc-extensions/cx-policy-legacy/src/main/java/org/eclipse/tractusx/edc/policy/cx/common/CredentialTypePredicate.java deleted file mode 100644 index 4a33eeeca..000000000 --- a/edc-extensions/cx-policy-legacy/src/main/java/org/eclipse/tractusx/edc/policy/cx/common/CredentialTypePredicate.java +++ /dev/null @@ -1,37 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.policy.cx.common; - -import org.eclipse.edc.identitytrust.model.VerifiableCredential; - -import java.util.function.Predicate; - -public class CredentialTypePredicate implements Predicate { - private final String expectedType; - - public CredentialTypePredicate(String expectedType) { - this.expectedType = expectedType; - } - - @Override - public boolean test(VerifiableCredential credential) { - return credential.getType().contains(expectedType); - } -} diff --git a/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/common/CredentialTypePredicate.java b/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/common/CredentialTypePredicate.java index 4a33eeeca..f7a98fb54 100644 --- a/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/common/CredentialTypePredicate.java +++ b/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/common/CredentialTypePredicate.java @@ -24,14 +24,16 @@ import java.util.function.Predicate; public class CredentialTypePredicate implements Predicate { - private final String expectedType; + private final String credentialNamespace; + private final String credentialType; - public CredentialTypePredicate(String expectedType) { - this.expectedType = expectedType; + public CredentialTypePredicate(String credentialNamespace, String credentialType) { + this.credentialNamespace = credentialNamespace; + this.credentialType = credentialType; } @Override public boolean test(VerifiableCredential credential) { - return credential.getType().contains(expectedType); + return credential.getType().contains(credentialType) || credential.getType().contains(credentialNamespace + credentialType); } } diff --git a/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/dismantler/DismantlerCredentialConstraintFunction.java b/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/dismantler/DismantlerCredentialConstraintFunction.java index aee4d12c8..9d054e974 100644 --- a/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/dismantler/DismantlerCredentialConstraintFunction.java +++ b/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/dismantler/DismantlerCredentialConstraintFunction.java @@ -76,7 +76,7 @@ public boolean evaluate(Object leftOperand, Operator operator, Object rightOpera } // always filter for DismantlerCredential type - predicate = new CredentialTypePredicate(CX_CREDENTIAL_NS + DISMANTLER_LITERAL + CREDENTIAL_LITERAL); + predicate = new CredentialTypePredicate(CX_CREDENTIAL_NS, DISMANTLER_LITERAL + CREDENTIAL_LITERAL); if (rightOperand.toString().contains(RIGHT_OPERAND_LIST_SEPARATOR)) { diff --git a/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/framework/FrameworkAgreementCredentialConstraintFunction.java b/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/framework/FrameworkAgreementCredentialConstraintFunction.java index 65ee08856..bd1ed844d 100644 --- a/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/framework/FrameworkAgreementCredentialConstraintFunction.java +++ b/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/framework/FrameworkAgreementCredentialConstraintFunction.java @@ -173,7 +173,7 @@ private Result>> getFilterPredicateLegacy(S @NotNull private List> createPredicates(String subtype, @Nullable String version) { var list = new ArrayList>(); - list.add(new CredentialTypePredicate(CX_CREDENTIAL_NS + capitalize(subtype) + CREDENTIAL_LITERAL)); + list.add(new CredentialTypePredicate(CX_CREDENTIAL_NS, capitalize(subtype) + CREDENTIAL_LITERAL)); if (version != null) { list.add(credential -> credential.getCredentialSubject().stream().anyMatch(cs -> version.equals(cs.getClaims().getOrDefault(CONTRACT_VERSION_PROPERTY, null)))); diff --git a/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/membership/MembershipCredentialConstraintFunction.java b/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/membership/MembershipCredentialConstraintFunction.java index 43325bf73..4c9d9a234 100644 --- a/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/membership/MembershipCredentialConstraintFunction.java +++ b/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/membership/MembershipCredentialConstraintFunction.java @@ -61,7 +61,7 @@ public boolean evaluate(Object leftOperand, Operator operator, Object rightOpera } return credentialResult.getContent() .stream() - .anyMatch(new CredentialTypePredicate(CX_CREDENTIAL_NS + MEMBERSHIP_LITERAL + CREDENTIAL_LITERAL)); + .anyMatch(new CredentialTypePredicate(CX_CREDENTIAL_NS, MEMBERSHIP_LITERAL + CREDENTIAL_LITERAL)); } @Override diff --git a/edc-extensions/iatp/tx-iatp-sts-dim/src/main/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/DimSecureTokenService.java b/edc-extensions/iatp/tx-iatp-sts-dim/src/main/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/DimSecureTokenService.java index 95c45bcfe..6eeef5b4a 100644 --- a/edc-extensions/iatp/tx-iatp-sts-dim/src/main/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/DimSecureTokenService.java +++ b/edc-extensions/iatp/tx-iatp-sts-dim/src/main/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/DimSecureTokenService.java @@ -86,9 +86,9 @@ public class DimSecureTokenService implements SecureTokenService { SUBJECT, "subject", PRESENTATION_TOKEN_CLAIM, PRESENTATION_TOKEN_CLAIM); - public DimSecureTokenService(EdcHttpClient httpClient, String dimBaseUrl, DimOauth2Client dimOauth2Client, ObjectMapper mapper, Monitor monitor) { + public DimSecureTokenService(EdcHttpClient httpClient, String dimUrl, DimOauth2Client dimOauth2Client, ObjectMapper mapper, Monitor monitor) { this.httpClient = httpClient; - this.dimUrl = dimBaseUrl + "/iatp"; + this.dimUrl = dimUrl; this.dimOauth2Client = dimOauth2Client; this.mapper = mapper; this.monitor = monitor; diff --git a/edc-extensions/iatp/tx-iatp-sts-dim/src/test/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/DimSecureTokenServiceTest.java b/edc-extensions/iatp/tx-iatp-sts-dim/src/test/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/DimSecureTokenServiceTest.java index f0764b8d6..00e3aa2f0 100644 --- a/edc-extensions/iatp/tx-iatp-sts-dim/src/test/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/DimSecureTokenServiceTest.java +++ b/edc-extensions/iatp/tx-iatp-sts-dim/src/test/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/DimSecureTokenServiceTest.java @@ -58,7 +58,7 @@ public class DimSecureTokenServiceTest { - static final String BASE_URL = "http://localhost:8080"; + static final String DIM_URL = "http://localhost:8080/iatp"; private final Monitor monitor = mock(Monitor.class); private final DimOauth2Client oauth2Client = mock(DimOauth2Client.class); private final ObjectMapper mapper = new ObjectMapper(); @@ -67,7 +67,7 @@ public class DimSecureTokenServiceTest { @BeforeEach void setup() { - client = new DimSecureTokenService(testHttpClient(interceptor), BASE_URL, oauth2Client, mapper, monitor); + client = new DimSecureTokenService(testHttpClient(interceptor), DIM_URL, oauth2Client, mapper, monitor); } @SuppressWarnings({ "unchecked", "rawtypes" }) @@ -88,7 +88,7 @@ void createToken_grantAccess() throws IOException { assertThat(((Map) payload)).containsAllEntriesOf(expectedBody); }); - assertThat(request.url().url().toString()).isEqualTo(BASE_URL + "/iatp"); + assertThat(request.url().url().toString()).isEqualTo(DIM_URL); }; @@ -122,7 +122,7 @@ void createToken_signToken() throws IOException { assertThat(((Map) payload)).containsAllEntriesOf(expectedBody); }); - assertThat(request.url().url().toString()).isEqualTo(BASE_URL + "/iatp"); + assertThat(request.url().url().toString()).isEqualTo(DIM_URL); }; diff --git a/edc-tests/e2e-tests/build.gradle.kts b/edc-tests/e2e-tests/build.gradle.kts index fe151453d..5211310e9 100644 --- a/edc-tests/e2e-tests/build.gradle.kts +++ b/edc-tests/e2e-tests/build.gradle.kts @@ -23,57 +23,19 @@ plugins { } dependencies { - testImplementation(project(":spi:edr-spi")) testImplementation(libs.okhttp.mockwebserver) testImplementation(libs.restAssured) testImplementation(libs.nimbus.jwt) - testImplementation(libs.postgres) testImplementation(libs.awaitility) - testImplementation(libs.aws.s3) - testImplementation(libs.edc.spi.core) - testImplementation(libs.edc.junit) - testImplementation(libs.edc.spi.policy) - testImplementation(libs.edc.spi.contract) - testImplementation(libs.edc.core.api) - testImplementation(libs.edc.spi.catalog) - testImplementation(libs.edc.api.catalog) - testImplementation(libs.edc.api.contractnegotiation) - testImplementation(libs.edc.api.transferprocess) - testImplementation(libs.edc.spi.dataplane.selector) - testImplementation(libs.edc.ext.jsonld) - testImplementation(libs.edc.dsp) - testImplementation(libs.edc.identity.jws2020) - testImplementation(libs.edc.identity.vc.ldp) - testImplementation(libs.edc.ih.spi.store) - testImplementation(libs.edc.identity.trust.sts.embedded) - testImplementation(libs.edc.token.core) testImplementation(libs.edc.lib.boot) testImplementation(testFixtures(libs.edc.sql.core)) testImplementation(testFixtures(libs.edc.api.management.test.fixtures)) - testImplementation(libs.awaitility) testImplementation(project(":edc-extensions:bpn-validation:bpn-validation-spi")) - testImplementation(libs.edc.auth.oauth2.client) - testImplementation(libs.testcontainers.junit) - testImplementation(libs.testcontainers.postgres) - testImplementation(libs.testcontainers.vault) - testImplementation(libs.bouncyCastle.bcpkixJdk18on) testImplementation(project(":spi:core-spi")) + testImplementation(testFixtures(project(":edc-tests:edc-controlplane:fixtures"))) testCompileOnly(project(":edc-tests:runtime:extensions")) - testCompileOnly(project(":edc-tests:runtime:runtime-memory")) - testCompileOnly(project(":edc-tests:runtime:iatp:runtime-memory-sts")) - testCompileOnly(project(":edc-tests:runtime:iatp:runtime-memory-iatp-ih")) - testCompileOnly(project(":edc-tests:runtime:iatp:runtime-memory-iatp-dim-ih")) - testCompileOnly(project(":edc-tests:runtime:runtime-memory-ssi")) - testCompileOnly(project(":edc-tests:runtime:runtime-postgresql")) - - testFixturesImplementation(libs.junit.jupiter.api) - testFixturesImplementation(libs.edc.spi.core) - testFixturesImplementation(libs.edc.junit) - testFixturesImplementation(libs.edc.spi.policy) - testFixturesImplementation(libs.edc.spi.contract) - testFixturesImplementation(project(":spi:edr-spi")) - testFixturesImplementation(project(":edc-extensions:bpn-validation:bpn-validation-spi")) + testCompileOnly(project(":edc-tests:runtime:iatp:runtime-memory-iatp-dim")) } diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/did/DidExampleResolver.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/did/DidExampleResolver.java deleted file mode 100644 index 34e7952b4..000000000 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/did/DidExampleResolver.java +++ /dev/null @@ -1,62 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.did; - -import org.eclipse.edc.iam.did.spi.document.DidDocument; -import org.eclipse.edc.iam.did.spi.resolution.DidResolver; -import org.eclipse.edc.spi.result.Result; -import org.jetbrains.annotations.NotNull; - -import java.util.HashMap; -import java.util.Map; -import java.util.Optional; - -/** - * Implementation of {@link DidResolver} for `did:example` with local cache (for testing) - */ -public class DidExampleResolver implements DidResolver { - - private final Map cache = new HashMap<>(); - - public DidExampleResolver() { - } - - @Override - public @NotNull String getMethod() { - return "example"; - } - - @Override - public @NotNull Result resolve(String did) { - - var ix = did.indexOf("#"); - if (ix > 0) { - did = did.substring(0, ix); - } - - return Optional.ofNullable(cache.get(did)) - .map(Result::success) - .orElseGet(() -> Result.failure("Failed to fetch did")); - } - - public void addCached(String did, DidDocument document) { - cache.put(did, document); - } -} diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/helpers/CatalogHelperFunctions.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/helpers/CatalogHelperFunctions.java deleted file mode 100644 index 642c8cee7..000000000 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/helpers/CatalogHelperFunctions.java +++ /dev/null @@ -1,45 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.helpers; - -import jakarta.json.JsonObject; -import jakarta.json.JsonValue; -import org.eclipse.edc.connector.contract.spi.ContractId; - -import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.ID; -import static org.eclipse.edc.jsonld.spi.PropertyAndTypeNames.ODRL_POLICY_ATTRIBUTE; - -public class CatalogHelperFunctions { - - - public static ContractId getDatasetContractId(JsonObject dataset) { - var id = dataset.getJsonArray(ODRL_POLICY_ATTRIBUTE).get(0).asJsonObject().getString(ID); - return ContractId.parseId(id).orElseThrow(f -> new RuntimeException(f.getFailureDetail())); - } - - public static String getDatasetAssetId(JsonObject dataset) { - return getDatasetContractId(dataset).assetIdPart(); - } - - public static String getDatasetAssetId(JsonValue dataset) { - return getDatasetContractId(dataset.asJsonObject()).assetIdPart(); - } - -} diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/helpers/DimHelper.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/helpers/DimHelper.java new file mode 100644 index 000000000..dce4bf013 --- /dev/null +++ b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/helpers/DimHelper.java @@ -0,0 +1,61 @@ +/******************************************************************************** + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +package org.eclipse.tractusx.edc.helpers; + +import org.eclipse.tractusx.edc.lifecycle.DimParticipant; + +import java.net.URI; +import java.util.Objects; + +import static java.lang.String.format; +import static java.lang.System.getenv; + +public interface DimHelper { + + /** + * Configure a {@link DimParticipant} from env variables + * + * @param name The participant name + * @return The composed {@link DimParticipant} + */ + static DimParticipant configureParticipant(String name) { + var bpn = getEnv(format("DIM_%s_BPN", name)); + var dimUrl = getEnv(format("DIM_%s_DIM_URL", name)); + var stsUrl = getEnv(format("DIM_%s_STS_URL", name)); + var stsClientId = getEnv(format("DIM_%s_STS_CLIENT_ID", name)); + var stsClientSecret = getEnv(format("DIM_%s_STS_CLIENT_SECRET", name)); + var did = getEnv(format("DIM_%s_DID", name)); + var trustedIssuer = getEnv("DIM_TRUSTED_ISSUER"); + return DimParticipant.Builder.newInstance().id(bpn) + .name(name) + .stsUri(URI.create(stsUrl)) + .stsClientId(stsClientId) + .stsClientSecret(stsClientSecret) + .dimUri(URI.create(dimUrl)) + .trustedIssuer(trustedIssuer) + .did(did) + .build(); + } + + private static String getEnv(String env) { + return Objects.requireNonNull(getenv(env), "%s env variable not present".formatted(env)); + } + +} diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/helpers/IatpHelperFunctions.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/helpers/IatpHelperFunctions.java deleted file mode 100644 index 8bc16089b..000000000 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/helpers/IatpHelperFunctions.java +++ /dev/null @@ -1,172 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.helpers; - -import jakarta.json.Json; -import jakarta.json.JsonArray; -import jakarta.json.JsonObject; -import org.bouncycastle.openssl.jcajce.JcaPEMWriter; -import org.eclipse.edc.iam.did.spi.document.DidDocument; -import org.eclipse.edc.iam.did.spi.resolution.DidResolverRegistry; -import org.eclipse.edc.identityhub.spi.ParticipantContextService; -import org.eclipse.edc.identityhub.spi.model.VerifiableCredentialResource; -import org.eclipse.edc.identityhub.spi.model.participant.KeyDescriptor; -import org.eclipse.edc.identityhub.spi.model.participant.ParticipantManifest; -import org.eclipse.edc.identityhub.spi.store.CredentialStore; -import org.eclipse.edc.jsonld.spi.JsonLd; -import org.eclipse.edc.spi.EdcException; -import org.eclipse.edc.spi.security.Vault; -import org.eclipse.tractusx.edc.did.DidExampleResolver; -import org.eclipse.tractusx.edc.lifecycle.ParticipantRuntime; -import org.eclipse.tractusx.edc.lifecycle.tx.iatp.DataspaceIssuer; -import org.eclipse.tractusx.edc.lifecycle.tx.iatp.IatpParticipant; -import org.testcontainers.shaded.org.bouncycastle.jce.provider.BouncyCastleProvider; - -import java.io.IOException; -import java.io.StringWriter; -import java.security.InvalidAlgorithmParameterException; -import java.security.Key; -import java.security.KeyPair; -import java.security.KeyPairGenerator; -import java.security.NoSuchAlgorithmException; -import java.security.spec.ECGenParameterSpec; -import java.time.Instant; -import java.util.List; -import java.util.Map; -import java.util.function.Supplier; - -public class IatpHelperFunctions { - - /** - * Returns the Pem representation of a {@link Key} - * - * @param key The input key - * @return The pem encoded key - */ - public static String toPemEncoded(Key key) { - var writer = new StringWriter(); - try (var jcaPEMWriter = new JcaPEMWriter(writer)) { - jcaPEMWriter.writeObject(key); - } catch (IOException e) { - throw new EdcException("Unable to convert private in PEM format ", e); - } - return writer.toString(); - } - - - public static KeyPair generateKeyPair() { - try { - KeyPairGenerator gen = KeyPairGenerator.getInstance("EC", new BouncyCastleProvider()); - gen.initialize(new ECGenParameterSpec("secp256r1")); - return gen.generateKeyPair(); - } catch (NoSuchAlgorithmException | InvalidAlgorithmParameterException e) { - throw new RuntimeException(e); - } - } - - public static JsonObject createVc(String issuer, String type, Supplier subjectSupplier) { - return Json.createObjectBuilder() - .add("@context", context()) - .add("type", types(type)) - .add("credentialSubject", subjectSupplier.get()) - .add("issuer", issuer) - .add("issuanceDate", Instant.now().toString()) - .build(); - } - - public static JsonObject membershipSubject(String did, String id) { - return Json.createObjectBuilder() - .add("type", "MembershipCredential") - .add("holderIdentifier", id) - .add("id", did) - .build(); - - } - - public static JsonObject frameworkAgreementSubject(String did, String id, String type) { - return Json.createObjectBuilder() - .add("type", type) - .add("holderIdentifier", id) - .add("contractVersion", "1.0.0") - .add("contractTemplate", "https://public.catena-x.org/contracts/traceabilty.v1.pdf") - .add("id", did) - .build(); - - } - - private static JsonArray types(String type) { - return Json.createArrayBuilder() - .add("VerifiableCredential") - .add(type) - .build(); - } - - private static JsonArray context() { - return Json.createArrayBuilder() - .add("https://www.w3.org/2018/credentials/v1") - .add("https://w3id.org/security/suites/jws-2020/v1") - .add("https://w3id.org/catenax/credentials") - .build(); - } - - public static void configureParticipant(DataspaceIssuer issuer, IatpParticipant participant, ParticipantRuntime runtime, Map dids, ParticipantRuntime stsRuntime) { - - if (stsRuntime != null) { - stsRuntime.getContext().getService(Vault.class).storeSecret(participant.verificationId(), participant.privateKey()); - } - var participantContextService = runtime.getContext().getService(ParticipantContextService.class); - var vault = runtime.getContext().getService(Vault.class); - var didResolverRegistry = runtime.getContext().getService(DidResolverRegistry.class); - var didResolver = new DidExampleResolver(); - dids.forEach(didResolver::addCached); - didResolverRegistry.register(didResolver); - - var key = KeyDescriptor.Builder.newInstance() - .keyId(participant.keyId()) - .publicKeyPem(participant.publicKey()) - .privateKeyAlias(participant.keyId()) - .build(); - - var participantManifest = ParticipantManifest.Builder.newInstance() - .participantId(participant.didUrl()) - .did(participant.didUrl()) - .key(key) - .build(); - - participantContextService.createParticipantContext(participantManifest); - vault.storeSecret(participant.keyId(), participant.privateKey()); - - storeCredentials(issuer, participant, runtime); - } - - private static void storeCredentials(DataspaceIssuer issuer, IatpParticipant participant, ParticipantRuntime runtime) { - var credentialStore = runtime.getContext().getService(CredentialStore.class); - var jsonLd = runtime.getContext().getService(JsonLd.class); - issueCredentials(issuer, participant, jsonLd).forEach(credentialStore::create); - } - - private static List issueCredentials(DataspaceIssuer issuer, IatpParticipant participant, JsonLd jsonLd) { - return List.of( - issuer.issueMembershipCredential(participant, jsonLd), - issuer.issueDismantlerCredential(participant, jsonLd), - issuer.issueFrameworkCredential(participant, jsonLd, "PcfCredential")); - - } -} diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/helpers/PolicyHelperFunctions.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/helpers/PolicyHelperFunctions.java deleted file mode 100644 index 87766c02f..000000000 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/helpers/PolicyHelperFunctions.java +++ /dev/null @@ -1,203 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.helpers; - - -import com.fasterxml.jackson.databind.ObjectMapper; -import jakarta.json.Json; -import jakarta.json.JsonArrayBuilder; -import jakarta.json.JsonObject; -import jakarta.json.JsonObjectBuilder; -import org.eclipse.edc.connector.policy.spi.PolicyDefinition; -import org.eclipse.edc.jsonld.util.JacksonJsonLd; -import org.eclipse.edc.policy.model.AtomicConstraint; -import org.eclipse.edc.policy.model.Operator; - -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.util.Arrays; -import java.util.Collection; -import java.util.Map; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.CONTEXT; -import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.ID; -import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.TYPE; -import static org.eclipse.edc.jsonld.spi.PropertyAndTypeNames.ODRL_CONSTRAINT_TYPE; -import static org.eclipse.edc.jsonld.spi.PropertyAndTypeNames.ODRL_LOGICAL_CONSTRAINT_TYPE; -import static org.eclipse.edc.spi.CoreConstants.EDC_NAMESPACE; - -public class PolicyHelperFunctions { - - public static final String TX_NAMESPACE = "https://w3id.org/tractusx/v0.0.1/ns/"; - private static final String ODRL_JSONLD = "http://www.w3.org/ns/odrl.jsonld"; - private static final String BUSINESS_PARTNER_EVALUATION_KEY = "BusinessPartnerNumber"; - - private static final String BUSINESS_PARTNER_CONSTRAINT_KEY = TX_NAMESPACE + "BusinessPartnerGroup"; - - private static final ObjectMapper MAPPER = JacksonJsonLd.createObjectMapper(); - - public static JsonObject bpnGroupPolicy(Operator operator, String... allowedGroups) { - return bpnGroupPolicy(operator.getOdrlRepresentation(), allowedGroups); - } - - /** - * Creates a {@link PolicyDefinition} using the given ID, that contains equality constraints for each of the given BusinessPartnerNumbers: - * each BPN is converted into an {@link AtomicConstraint} {@code BusinessPartnerNumber EQ [BPN]}. - */ - public static JsonObject frameworkPolicy(String id, Map permissions) { - return policyDefinitionBuilder(frameworkPolicy(permissions)) - .add(ID, id) - .build(); - } - - public static JsonObject frameworkPolicy(Map permissions) { - return Json.createObjectBuilder() - .add(CONTEXT, ODRL_JSONLD) - .add(TYPE, "Set") - .add("permission", Json.createArrayBuilder() - .add(frameworkPermission(permissions))) - .build(); - } - - public static JsonObject frameworkPolicy(String leftOperand, Operator operator, Object rightOperand) { - var constraint = atomicConstraint(leftOperand, operator.getOdrlRepresentation(), rightOperand); - - var permission = Json.createObjectBuilder() - .add("action", "use") - .add("constraint", Json.createObjectBuilder() - .add(TYPE, ODRL_LOGICAL_CONSTRAINT_TYPE) - .add("or", constraint) - .build()) - .build(); - - return Json.createObjectBuilder() - .add(CONTEXT, ODRL_JSONLD) - .add(TYPE, "Set") - .add("permission", Json.createArrayBuilder().add(permission)) - .build(); - } - - /** - * Creates a {@link PolicyDefinition} using the given ID, that contains equality constraints for each of the given BusinessPartnerNumbers: - * each BPN is converted into an {@link AtomicConstraint} {@code BusinessPartnerNumber EQ [BPN]}. - */ - public static JsonObject frameworkTemplatePolicy(String id, String frameworkKind) { - var template = fetchFrameworkTemplate().replace("${POLICY_ID}", id).replace("${FRAMEWORK_CREDENTIAL}", frameworkKind); - try { - return MAPPER.readValue(template, JsonObject.class); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - public static JsonObjectBuilder policyDefinitionBuilder() { - return Json.createObjectBuilder() - .add(TYPE, EDC_NAMESPACE + "PolicyDefinitionDto"); - } - - public static JsonObjectBuilder policyDefinitionBuilder(JsonObject policy) { - return policyDefinitionBuilder() - .add(EDC_NAMESPACE + "policy", policy); - } - - public static JsonObject bnpPolicy(String... bnps) { - return Json.createObjectBuilder() - .add(CONTEXT, ODRL_JSONLD) - .add(TYPE, "Set") - .add("permission", Json.createArrayBuilder() - .add(permission(bnps))) - .build(); - } - - - private static JsonObject bpnGroupPolicy(String operator, String... allowedGroups) { - - var groupConstraint = atomicConstraint(BUSINESS_PARTNER_CONSTRAINT_KEY, operator, Arrays.asList(allowedGroups)); - - var permission = Json.createObjectBuilder() - .add("action", "use") - .add("constraint", Json.createObjectBuilder() - .add(TYPE, ODRL_LOGICAL_CONSTRAINT_TYPE) - .add("or", groupConstraint) - .build()) - .build(); - - return Json.createObjectBuilder() - .add(CONTEXT, ODRL_JSONLD) - .add(TYPE, "Set") - .add("permission", permission) - .build(); - } - - private static String fetchFrameworkTemplate() { - try (var stream = PolicyHelperFunctions.class.getClassLoader().getResourceAsStream("framework-policy.json")) { - return new String(stream.readAllBytes(), StandardCharsets.UTF_8); - } catch (IOException e) { - throw new RuntimeException(e); - } - - } - - private static JsonObject permission(String... bpns) { - - var bpnConstraints = Stream.of(bpns) - .map(bpn -> atomicConstraint(TX_NAMESPACE + BUSINESS_PARTNER_EVALUATION_KEY, "eq", bpn)) - .collect(Json::createArrayBuilder, JsonArrayBuilder::add, JsonArrayBuilder::add); - - return Json.createObjectBuilder() - .add("action", "use") - .add("constraint", Json.createObjectBuilder() - .add(TYPE, ODRL_LOGICAL_CONSTRAINT_TYPE) - .add("or", bpnConstraints) - .build()) - .build(); - } - - private static JsonObject frameworkPermission(Map permissions) { - - var constraints = permissions.entrySet().stream() - .map(permission -> atomicConstraint(permission.getKey(), "eq", permission.getValue())) - .collect(Json::createArrayBuilder, JsonArrayBuilder::add, JsonArrayBuilder::add); - - return Json.createObjectBuilder() - .add("action", "use") - .add("constraint", Json.createObjectBuilder() - .add(TYPE, ODRL_LOGICAL_CONSTRAINT_TYPE) - .add("or", constraints) - .build()) - .build(); - } - - private static JsonObject atomicConstraint(String leftOperand, String operator, Object rightOperand) { - var builder = Json.createObjectBuilder() - .add(TYPE, ODRL_CONSTRAINT_TYPE) - .add("leftOperand", leftOperand) - .add("operator", operator); - - if (rightOperand instanceof Collection coll) { - builder.add("rightOperand", coll.stream().map(Object::toString).collect(Collectors.joining(","))); - } else { - builder.add("rightOperand", rightOperand.toString()); - } - return builder.build(); - } -} diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/helpers/ReceivedEvent.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/helpers/ReceivedEvent.java deleted file mode 100644 index 2699b702c..000000000 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/helpers/ReceivedEvent.java +++ /dev/null @@ -1,61 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.helpers; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; - - -@JsonIgnoreProperties(ignoreUnknown = true) -public class ReceivedEvent { - private String type; - - public String getType() { - return type; - } - - @Override - public String toString() { - return "ReceivedEvent{" + - "type='" + type + '\'' + - '}'; - } - - public static class Builder { - private final ReceivedEvent event; - - private Builder(ReceivedEvent event) { - this.event = event; - } - - public static Builder newInstance() { - return new Builder(new ReceivedEvent()); - } - - public Builder type(String type) { - this.event.type = type; - return this; - } - - public ReceivedEvent build() { - return event; - } - } -} - diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/helpers/TransferProcessHelperFunctions.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/helpers/TransferProcessHelperFunctions.java deleted file mode 100644 index e5aba8adc..000000000 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/helpers/TransferProcessHelperFunctions.java +++ /dev/null @@ -1,38 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.helpers; - -import jakarta.json.Json; -import jakarta.json.JsonObject; - -import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.TYPE; -import static org.eclipse.edc.spi.CoreConstants.EDC_NAMESPACE; - -public class TransferProcessHelperFunctions { - - - public static JsonObject createProxyRequest() { - return Json.createObjectBuilder() - .add(TYPE, EDC_NAMESPACE + "DataAddress") - .add(EDC_NAMESPACE + "type", "HttpProxy") - .build(); - - } -} diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/DataWiper.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/DataWiper.java index 2bb1b12e7..553a956d9 100644 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/DataWiper.java +++ b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/DataWiper.java @@ -27,8 +27,8 @@ import org.eclipse.tractusx.edc.edr.spi.store.EndpointDataReferenceCache; import org.eclipse.tractusx.edc.validation.businesspartner.spi.BusinessPartnerStore; -import static org.eclipse.tractusx.edc.lifecycle.TestRuntimeConfiguration.PLATO_BPN; -import static org.eclipse.tractusx.edc.lifecycle.TestRuntimeConfiguration.SOKRATES_BPN; +import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.PLATO_BPN; +import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.SOKRATES_BPN; /** * Helper class to delete all objects from a runtime's data stores. diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/DimParticipant.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/DimParticipant.java new file mode 100644 index 000000000..29ff7540c --- /dev/null +++ b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/DimParticipant.java @@ -0,0 +1,66 @@ +/******************************************************************************** + * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +package org.eclipse.tractusx.edc.lifecycle; + +import org.eclipse.tractusx.edc.tests.TractusxIatpParticipantBase; + +import java.net.URI; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +/** + * Extension of {@link TractusxIatpParticipantBase} with DIM specific configuration + */ +public class DimParticipant extends TractusxIatpParticipantBase { + + protected URI dimUri; + + @Override + public Map iatpConfiguration(TractusxIatpParticipantBase... others) { + var config = new HashMap<>(super.iatpConfiguration(others)); + config.put("edc.iam.sts.dim.url", dimUri.toString()); + config.put("edc.transfer.proxy.token.verifier.publickey.alias", getKeyId()); + return config; + } + + public static class Builder extends TractusxIatpParticipantBase.Builder { + + protected Builder() { + super(new DimParticipant()); + } + + public static Builder newInstance() { + return new Builder(); + } + + public Builder dimUri(URI dimUri) { + participant.dimUri = dimUri; + return self(); + } + + @Override + public DimParticipant build() { + super.build(); + Objects.requireNonNull(participant.dimUri, "DIM URI should not be null"); + return participant; + } + } +} diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/MiwParticipant.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/MiwParticipant.java new file mode 100644 index 000000000..1db4c37a5 --- /dev/null +++ b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/MiwParticipant.java @@ -0,0 +1,82 @@ +/******************************************************************************** + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +package org.eclipse.tractusx.edc.lifecycle; + +import org.eclipse.tractusx.edc.tests.TractusxParticipantBase; + +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +/** + * Extension of {@link TractusxParticipantBase} with MIW specific configuration + */ +public class MiwParticipant extends TractusxParticipantBase { + + protected String miwUri; + protected String oauth2Uri; + + public Map getConfiguration() { + var baseConfiguration = super.getConfiguration(); + + var ssiConfiguration = new HashMap() { + { + put("tx.ssi.miw.url", miwUri); + put("tx.ssi.oauth.token.url", oauth2Uri); + put("tx.ssi.oauth.client.id", "miw_private_client"); + put("tx.ssi.oauth.client.secret.alias", "client_secret_alias"); + put("tx.ssi.miw.authority.id", "BPNL000000000000"); + put("tx.ssi.miw.authority.issuer", "did:web:localhost%3A8000:BPNL000000000000"); + put("tx.vault.seed.secrets", "client_secret_alias:miw_private_client"); + put("tx.ssi.endpoint.audience", getProtocolEndpoint().getUrl().toString()); + } + }; + ssiConfiguration.putAll(baseConfiguration); + return ssiConfiguration; + } + + public static class Builder extends TractusxParticipantBase.Builder { + + protected Builder() { + super(new MiwParticipant()); + } + + public static Builder newInstance() { + return new Builder(); + } + + public Builder miwUri(String miwUri) { + participant.miwUri = miwUri; + return self(); + } + + public Builder oauth2Uri(String oauth2Uri) { + participant.oauth2Uri = oauth2Uri; + return self(); + } + + @Override + public MiwParticipant build() { + super.build(); + Objects.requireNonNull(participant.miwUri, "MIW URI should not be null"); + return participant; + } + } +} diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/ParticipantRuntime.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/ParticipantRuntime.java index 3a644a074..ce4a2e80a 100644 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/ParticipantRuntime.java +++ b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/ParticipantRuntime.java @@ -19,15 +19,14 @@ package org.eclipse.tractusx.edc.lifecycle; +import com.nimbusds.jose.JOSEException; +import com.nimbusds.jose.jwk.Curve; +import com.nimbusds.jose.jwk.gen.ECKeyGenerator; import org.eclipse.edc.junit.extensions.EdcRuntimeExtension; -import org.eclipse.edc.spi.iam.AudienceResolver; -import org.eclipse.edc.spi.iam.IdentityService; import org.eclipse.edc.spi.security.Vault; import org.eclipse.edc.spi.system.ServiceExtension; import org.eclipse.edc.spi.system.ServiceExtensionContext; import org.eclipse.edc.spi.system.injection.InjectionContainer; -import org.eclipse.edc.spi.types.domain.message.RemoteMessage; -import org.eclipse.tractusx.edc.token.MockBpnIdentityService; import org.junit.jupiter.api.extension.AfterAllCallback; import org.junit.jupiter.api.extension.BeforeAllCallback; import org.junit.jupiter.api.extension.ExtensionContext; @@ -35,24 +34,23 @@ import java.util.List; import java.util.Map; -import static org.eclipse.tractusx.edc.helpers.IatpHelperFunctions.generateKeyPair; -import static org.eclipse.tractusx.edc.helpers.IatpHelperFunctions.toPemEncoded; - public class ParticipantRuntime extends EdcRuntimeExtension implements BeforeAllCallback, AfterAllCallback { - private final Map properties; private DataWiper wiper; - public ParticipantRuntime(String moduleName, String runtimeName, String bpn, Map properties) { + + public ParticipantRuntime(String moduleName, String runtimeName, Map properties) { super(moduleName, runtimeName, properties); this.properties = properties; - if (!properties.containsKey("tx.ssi.miw.url") && !properties.containsKey("edc.iam.issuer.id")) { - this.registerServiceMock(IdentityService.class, new MockBpnIdentityService(bpn)); - this.registerServiceMock(AudienceResolver.class, RemoteMessage::getCounterPartyAddress); - } } + public ParticipantRuntime(String runtimeName, Map properties, String... modules) { + super(runtimeName, properties, modules); + this.properties = properties; + } + + @Override public void beforeTestExecution(ExtensionContext extensionContext) { //do nothing - we only want to start the runtime once @@ -84,12 +82,16 @@ protected void bootExtensions(ServiceExtensionContext context, List properties) { var privateAlias = properties.get("edc.transfer.proxy.token.signer.privatekey.alias"); var publicAlias = properties.get("edc.transfer.proxy.token.verifier.publickey.alias"); - if (privateAlias != null && publicAlias != null) { - var keyPair = generateKeyPair(); - var vault = getContext().getService(Vault.class); - vault.storeSecret(privateAlias, toPemEncoded(keyPair.getPrivate())); - vault.storeSecret(publicAlias, toPemEncoded(keyPair.getPublic())); + try { + var ecKey = new ECKeyGenerator(Curve.P_256).keyID(publicAlias).generate(); + var vault = getContext().getService(Vault.class); + vault.storeSecret(privateAlias, ecKey.toJSONString()); + vault.storeSecret(publicAlias, ecKey.toPublicJWK().toJSONString()); + } catch (JOSEException e) { + throw new RuntimeException(e); + } + } } diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/PgHashicorpParticipantRuntime.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/PgHashicorpParticipantRuntime.java deleted file mode 100644 index 942ba81a2..000000000 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/PgHashicorpParticipantRuntime.java +++ /dev/null @@ -1,74 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.lifecycle; - -import org.junit.jupiter.api.extension.ExtensionContext; -import org.testcontainers.vault.VaultContainer; - -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; - -import static java.lang.String.format; - -public class PgHashicorpParticipantRuntime extends PgParticipantRuntime { - - static final String DOCKER_IMAGE_NAME = "vault:1.9.6"; - static final String TOKEN = UUID.randomUUID().toString(); - - - public final VaultContainer vaultContainer = new VaultContainer<>(DOCKER_IMAGE_NAME) - .withVaultToken(TOKEN); - private final String vaultDirectory; - - public PgHashicorpParticipantRuntime(String moduleName, String runtimeName, String bpn, String vaultDirectory, Map properties) { - super(moduleName, runtimeName, bpn, properties); - this.vaultDirectory = vaultDirectory; - } - - @Override - public void beforeAll(ExtensionContext context) throws Exception { - vaultContainer.start(); - config().forEach(System::setProperty); - super.beforeAll(context); - } - - @Override - public void afterAll(ExtensionContext context) throws Exception { - super.afterAll(context); - vaultContainer.stop(); - vaultContainer.close(); - } - - @Override - protected void mockVault() { - - } - - private Map config() { - return new HashMap<>() { - { - put("edc.vault.hashicorp.url", format("http://%s:%s", vaultContainer.getHost(), vaultContainer.getFirstMappedPort())); - put("edc.vault.hashicorp.token", TOKEN); - put("edc.edr.vault.path", vaultDirectory); - } - }; - } -} diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/PgParticipantRuntime.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/PgParticipantRuntime.java deleted file mode 100644 index d5a5f2174..000000000 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/PgParticipantRuntime.java +++ /dev/null @@ -1,128 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.lifecycle; - -import org.eclipse.edc.boot.vault.InMemoryVault; -import org.eclipse.edc.spi.monitor.Monitor; -import org.eclipse.edc.spi.result.Result; -import org.eclipse.edc.spi.security.Vault; -import org.eclipse.edc.spi.system.ServiceExtension; -import org.eclipse.edc.spi.system.ServiceExtensionContext; -import org.eclipse.edc.spi.system.injection.InjectionContainer; -import org.eclipse.edc.sql.testfixtures.PostgresqlLocalInstance; -import org.junit.jupiter.api.extension.ExtensionContext; -import org.testcontainers.containers.PostgreSQLContainer; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.stream.Stream; - -import static java.lang.String.format; -import static org.eclipse.tractusx.edc.lifecycle.TestRuntimeConfiguration.DB_SCHEMA_NAME; -import static org.mockito.Mockito.mock; - -public class PgParticipantRuntime extends ParticipantRuntime { - - private static final String POSTGRES_IMAGE_NAME = "postgres:14.2"; - private static final String USER = "postgres"; - private static final String PASSWORD = "password"; - private final String dbName; - public PostgreSQLContainer postgreSqlContainer; - - public PgParticipantRuntime(String moduleName, String runtimeName, String bpn, Map properties) { - super(moduleName, runtimeName, bpn, properties); - this.dbName = runtimeName.toLowerCase(); - mockVault(); - - postgreSqlContainer = new PostgreSQLContainer<>(POSTGRES_IMAGE_NAME) - .withLabel("runtime", dbName) - .withExposedPorts(5432) - .withUsername(USER) - .withPassword(PASSWORD) - .withDatabaseName(dbName); - } - - @Override - public void beforeAll(ExtensionContext context) throws Exception { - postgreSqlContainer.start(); - var config = postgresqlConfiguration(dbName); - config.forEach(System::setProperty); - super.beforeAll(context); - } - - @Override - public void afterAll(ExtensionContext context) throws Exception { - super.afterAll(context); - postgreSqlContainer.stop(); - postgreSqlContainer.close(); - } - - @Override - protected void bootExtensions(ServiceExtensionContext context, List> serviceExtensions) { - PostgresqlLocalInstance helper = new PostgresqlLocalInstance(postgreSqlContainer.getUsername(), postgreSqlContainer.getPassword(), baseJdbcUrl(), postgreSqlContainer.getDatabaseName()); - helper.createDatabase(); - super.bootExtensions(context, serviceExtensions); - } - - public Map postgresqlConfiguration(String name) { - var jdbcUrl = jdbcUrl(name); - return new HashMap<>() { - { - Stream.of("asset", "contractdefinition", "contractnegotiation", "policy", "transferprocess", "edr", "bpn", "policy-monitor") - .forEach(context -> { - var group = "edc.datasource." + context; - put(group + ".name", context); - put(group + ".url", jdbcUrl); - put(group + ".user", USER); - put(group + ".password", PASSWORD); - }); - // use non-default schema name to test usage of non-default schema - put("org.eclipse.tractusx.edc.postgresql.migration.schema", DB_SCHEMA_NAME); - } - }; - } - - public String jdbcUrl(String name) { - return baseJdbcUrl() + name + "?currentSchema=" + DB_SCHEMA_NAME; - } - - public String baseJdbcUrl() { - return format("jdbc:postgresql://%s:%s/", postgreSqlContainer.getHost(), postgreSqlContainer.getFirstMappedPort()); - } - - protected void mockVault() { - this.registerServiceMock(Vault.class, new InMemoryVaultOverride(mock(Monitor.class))); - } - - private static class InMemoryVaultOverride extends InMemoryVault { - - InMemoryVaultOverride(Monitor monitor) { - super(monitor); - } - - @Override - public Result deleteSecret(String s) { - super.deleteSecret(s); - return Result.success(); - } - } - -} diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/TestCommon.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/Runtimes.java similarity index 73% rename from edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/TestCommon.java rename to edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/Runtimes.java index 486044a9a..6b265ddb4 100644 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/TestCommon.java +++ b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/Runtimes.java @@ -17,13 +17,15 @@ * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ -package org.eclipse.tractusx.edc.tests; +package org.eclipse.tractusx.edc.lifecycle; -import java.time.Duration; +import java.util.Map; -import static java.time.Duration.ofSeconds; +public interface Runtimes { -public interface TestCommon { - Duration ASYNC_TIMEOUT = ofSeconds(60); - Duration ASYNC_POLL_INTERVAL = ofSeconds(1); + static ParticipantRuntime dimRuntime(String name, Map configuration) { + return new ParticipantRuntime(name, configuration, + ":edc-tests:runtime:iatp:runtime-memory-iatp-dim" + ); + } } diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/tx/ParticipantDataApi.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/tx/ParticipantDataApi.java deleted file mode 100644 index ce2198f5e..000000000 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/tx/ParticipantDataApi.java +++ /dev/null @@ -1,56 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.lifecycle.tx; - -import org.eclipse.edc.spi.types.domain.edr.EndpointDataReference; - -import java.util.Map; - -import static io.restassured.RestAssured.given; -import static org.assertj.core.api.Assertions.assertThat; - - -/** - * E2E test helper for fetching the data - */ -public class ParticipantDataApi { - - public ParticipantDataApi() { - } - - /** - * Pull the data with an {@link EndpointDataReference} - * - * @param edr The edr - * @param queryParams additional params - * @return the data - */ - public String pullData(EndpointDataReference edr, Map queryParams) { - var response = given() - .baseUri(edr.getEndpoint()) - .header(edr.getAuthKey(), edr.getAuthCode()) - .queryParams(queryParams) - .when() - .get(); - assertThat(response.statusCode()).isBetween(200, 300); - return response.body().asString(); - } - -} diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/tx/ParticipantEdrApi.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/tx/ParticipantEdrApi.java deleted file mode 100644 index 801fc691e..000000000 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/tx/ParticipantEdrApi.java +++ /dev/null @@ -1,62 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.lifecycle.tx; - -import org.eclipse.edc.spi.types.domain.edr.EndpointDataReference; - -import java.net.URI; -import java.util.concurrent.atomic.AtomicReference; - -import static io.restassured.RestAssured.given; - -/** - * E2E test helper for the EDR APIs - */ -public class ParticipantEdrApi { - - private final URI edrBackend; - - public ParticipantEdrApi(URI edrBackend) { - this.edrBackend = edrBackend; - } - - /** - * Get the cached EDR for a transfer process cached in a backend - * - * @param transferProcessId The transfer process id - * @return The EDR - */ - public EndpointDataReference getDataReferenceFromBackend(String transferProcessId) { - var dataReference = new AtomicReference(); - - var result = given() - .when() - .get(edrBackend + "/{id}", transferProcessId) - .then() - .statusCode(200) - .extract() - .body() - .as(EndpointDataReference.class); - dataReference.set(result); - - return dataReference.get(); - } - -} diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/tx/TxParticipant.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/tx/TxParticipant.java deleted file mode 100644 index 277fa67af..000000000 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/tx/TxParticipant.java +++ /dev/null @@ -1,310 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.lifecycle.tx; - -import com.fasterxml.jackson.annotation.JsonCreator; -import io.restassured.specification.RequestSpecification; -import jakarta.json.Json; -import jakarta.json.JsonObject; -import org.eclipse.edc.spi.EdcException; -import org.eclipse.edc.test.system.utils.Participant; - -import java.net.URI; -import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; - -import static io.restassured.http.ContentType.JSON; -import static jakarta.json.Json.createObjectBuilder; -import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.ID; -import static org.eclipse.edc.jsonld.spi.PropertyAndTypeNames.ODRL_ASSIGNER_ATTRIBUTE; -import static org.eclipse.edc.jsonld.spi.PropertyAndTypeNames.ODRL_POLICY_ATTRIBUTE; -import static org.eclipse.edc.jsonld.spi.PropertyAndTypeNames.ODRL_TARGET_ATTRIBUTE; -import static org.eclipse.edc.util.io.Ports.getFreePort; -import static org.eclipse.tractusx.edc.helpers.PolicyHelperFunctions.TX_NAMESPACE; -import static org.eclipse.tractusx.edc.tests.TestCommon.ASYNC_TIMEOUT; - -/** - * Implementation for TX of a {@link Participant} - */ -public class TxParticipant extends Participant { - - public static final String API_KEY = "testkey"; - public static final String PROXY_SUBPATH = "proxy/aas/request"; - private final URI controlPlaneDefault = URI.create("http://localhost:" + getFreePort()); - private final URI controlPlaneControl = URI.create("http://localhost:" + getFreePort() + "/control"); - private final URI gateway = URI.create("http://localhost:" + getFreePort() + "/api/gateway"); - private final URI backendProviderProxy = URI.create("http://localhost:" + getFreePort() + "/events"); - private final URI dataPlaneProxy = URI.create("http://localhost:" + getFreePort()); - private final URI dataPlanePublic = URI.create("http://localhost:" + getFreePort() + "/public"); - private final URI miwUri = URI.create("http://localhost:" + getFreePort()); - private final URI oauthTokenUri = URI.create("http://localhost:" + getFreePort()); - private final URI backend = URI.create("http://localhost:" + controlPlaneDefault.getPort() + "/api/consumer/datareference"); - private ParticipantEdrApi edrs; - private ParticipantDataApi data; - - /** - * Creates an asset with the given ID and props using the participant's Data Management API - */ - public void createAsset(String id) { - createAsset(id, new HashMap<>(), Map.of("type", "test-type")); - } - - /** - * Stores BPN groups - */ - public void storeBusinessPartner(String bpn, String... groups) { - var body = createObjectBuilder() - .add(ID, bpn) - .add(TX_NAMESPACE + "groups", Json.createArrayBuilder(Arrays.asList(groups))) - .build(); - managementEndpoint.baseRequest() - .contentType(JSON) - .body(body) - .when() - .post("/business-partner-groups") - .then() - .statusCode(204); - } - - /** - * The BPN/ID of the participant - * - * @return The bpn - */ - - public String getBpn() { - return id; - } - - - /** - * Returns the client API for interacting with EDRs - */ - public ParticipantEdrApi edrs() { - return edrs; - } - - /** - * Returns the client API for fetching data - */ - public ParticipantDataApi data() { - return data; - } - - /** - * Creates a policy definition - */ - public String createPolicy(JsonObject policyDefinition) { - return managementRequest() - .contentType(JSON) - .body(policyDefinition) - .when() - .post("/v2/policydefinitions") - .then() - .log().ifError() - .statusCode(200) - .contentType(JSON) - .extract() - .path("@id"); - } - - /** - * Get current error if any of a contract negotiation. - * - * @param negotiationId contract negotiation id - * @return error of the contract negotiation. - */ - public String getContractNegotiationError(String negotiationId) { - return getContractNegotiationField(negotiationId, "errorDetail"); - } - - // TODO: temporary with workaround override due https://github.com/eclipse-edc/Connector/pull/3926 - // remove once fixed in EDC upstream - @Override - public String initContractNegotiation(Participant provider, String assetId) { - - if (provider instanceof TxParticipant txProvider) { - var dataset = getDatasetForAsset(provider, assetId); - var policy = dataset.getJsonArray(ODRL_POLICY_ATTRIBUTE).get(0).asJsonObject(); - - var offer = createObjectBuilder(policy) - .add(ODRL_ASSIGNER_ATTRIBUTE, createObjectBuilder().add(ID, txProvider.getBpn())) - .add(ODRL_TARGET_ATTRIBUTE, createObjectBuilder().add(ID, dataset.get(ID))) - .build(); - - return super.initContractNegotiation(provider, offer); - } else { - throw new EdcException("Not a TX participant"); - } - - } - - /** - * Returns the base configuration - */ - public Map getConfiguration() { - return new HashMap<>() { - { - put("edc.connector.name", name); - put("edc.participant.id", id); - put("web.http.port", String.valueOf(controlPlaneDefault.getPort())); - put("web.http.path", "/api"); - put("web.http.protocol.port", String.valueOf(protocolEndpoint.getUrl().getPort())); - put("web.http.protocol.path", protocolEndpoint.getUrl().getPath()); - put("web.http.management.port", String.valueOf(managementEndpoint.getUrl().getPort())); - put("web.http.management.path", managementEndpoint.getUrl().getPath()); - put("web.http.control.port", String.valueOf(controlPlaneControl.getPort())); - put("web.http.control.path", controlPlaneControl.getPath()); - put("edc.dsp.callback.address", protocolEndpoint.getUrl().toString()); - put("edc.api.auth.key", "testkey"); - put("web.http.public.path", "/api/public"); - put("web.http.public.port", String.valueOf(dataPlanePublic.getPort())); - put("web.http.gateway.path", gateway.getPath()); - put("web.http.gateway.port", String.valueOf(gateway.getPort())); - put("edc.transfer.proxy.token.signer.privatekey.alias", "private-key"); - put("edc.transfer.proxy.token.verifier.publickey.alias", "public-key"); - put("edc.transfer.send.retry.limit", "1"); - put("edc.transfer.send.retry.base-delay.ms", "100"); - put("tx.dpf.consumer.proxy.port", String.valueOf(dataPlaneProxy.getPort())); - put("edc.dataplane.token.validation.endpoint", controlPlaneControl + "/token"); - put("edc.dataplane.selector.httpplane.url", controlPlaneControl.toString()); - put("edc.dataplane.selector.httpplane.sourcetypes", "HttpData"); - put("edc.dataplane.selector.httpplane.destinationtypes", "HttpProxy"); - put("edc.dataplane.selector.httpplane.properties", "{\"publicApiUrl\":\"http://localhost:" + dataPlanePublic.getPort() + "/api/public\"}"); - put("edc.receiver.http.dynamic.endpoint", "http://localhost:" + controlPlaneDefault.getPort() + "/api/consumer/datareference"); - put("tractusx.businesspartnervalidation.log.agreement.validation", "true"); - put("edc.agent.identity.key", "BusinessPartnerNumber"); - put("edc.data.encryption.keys.alias", "test-alias"); - put("tx.dpf.proxy.gateway.aas.proxied.path", backendProviderProxy.toString()); - put("tx.dpf.proxy.gateway.aas.authorization.type", "none"); - put("edc.iam.issuer.id", "did:web:" + name); - } - }; - } - - /** - * Returns the SSI configuration - */ - public Map ssiConfiguration() { - var ssiConfiguration = new HashMap() { - { - put("tx.ssi.miw.url", miwUri.toString()); - put("tx.ssi.oauth.token.url", oauthTokenUri.toString()); - put("tx.ssi.oauth.client.id", "client_id"); - put("tx.ssi.oauth.client.secret.alias", "client_secret_alias"); - put("tx.ssi.miw.authority.id", "authorityId"); - put("tx.ssi.miw.authority.issuer", "did:web:example.com"); - put("tx.vault.seed.secrets", "client_secret_alias:client_secret"); - put("tx.ssi.endpoint.audience", protocolEndpoint.getUrl().toString()); - } - }; - var baseConfiguration = getConfiguration(); - ssiConfiguration.putAll(baseConfiguration); - return ssiConfiguration; - } - - /** - * Returns the renewal configuration - */ - public Map renewalConfiguration() { - return renewalConfiguration("10"); - } - - /** - * Returns the renewal configuration - */ - public Map renewalConfiguration(String retention) { - var renewalConfig = new HashMap() { - { - put("edc.edr.state-machine.expiring-duration", "10"); - put("edc.edr.state-machine.expired-retention", retention); - put("edc.transfer.proxy.token.validity.seconds", "15"); - } - }; - var baseConfiguration = getConfiguration(); - renewalConfig.putAll(baseConfiguration); - - return renewalConfig; - } - - /** - * Returns the MIW endpoint - */ - public URI miwEndpoint() { - return miwUri; - } - - /** - * Returns the OAuth2 token endpoint - */ - public URI authTokenEndpoint() { - return oauthTokenUri; - } - - /** - * Returns the Gateway endpoint - */ - public URI gatewayEndpoint() { - return gateway; - } - - /** - * Returns the Consumer data plane proxy endpoint - */ - public URI dataPlaneProxy() { - return dataPlaneProxy; - } - - /** - * Returns the provider gateway backend endpoint - */ - public URI backendProviderProxy() { - return backendProviderProxy; - } - - protected RequestSpecification managementRequest() { - return managementEndpoint.baseRequest(); - } - - public static final class Builder extends Participant.Builder { - - private Builder() { - super(new TxParticipant()); - } - - @JsonCreator - public static Builder newInstance() { - return new Builder(); - } - - @Override - public TxParticipant build() { - super.managementEndpoint(new Endpoint(URI.create("http://localhost:" + getFreePort() + "/api/management"), Map.of("x-api-key", API_KEY))); - super.protocolEndpoint(new Endpoint(URI.create("http://localhost:" + getFreePort() + "/protocol"))); - super.timeout(ASYNC_TIMEOUT); - super.build(); - - this.participant.edrs = new ParticipantEdrApi(participant.backend); - this.participant.data = new ParticipantDataApi(); - return participant; - } - } -} diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/tx/iatp/DataspaceIssuer.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/tx/iatp/DataspaceIssuer.java deleted file mode 100644 index 829291808..000000000 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/tx/iatp/DataspaceIssuer.java +++ /dev/null @@ -1,183 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.lifecycle.tx.iatp; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.nimbusds.jose.jwk.Curve; -import com.nimbusds.jose.jwk.ECKey; -import com.nimbusds.jose.jwk.JWK; -import jakarta.json.Json; -import jakarta.json.JsonObject; -import org.eclipse.edc.iam.did.spi.document.DidDocument; -import org.eclipse.edc.iam.did.spi.document.VerificationMethod; -import org.eclipse.edc.identityhub.spi.model.VerifiableCredentialResource; -import org.eclipse.edc.identitytrust.model.CredentialFormat; -import org.eclipse.edc.identitytrust.model.CredentialSubject; -import org.eclipse.edc.identitytrust.model.Issuer; -import org.eclipse.edc.identitytrust.model.VerifiableCredential; -import org.eclipse.edc.identitytrust.model.VerifiableCredentialContainer; -import org.eclipse.edc.jsonld.spi.JsonLd; -import org.eclipse.edc.security.signature.jws2020.JwkMethod; -import org.eclipse.edc.security.signature.jws2020.JwsSignature2020Suite; -import org.eclipse.edc.verifiablecredentials.linkeddata.LdpIssuer; - -import java.net.URI; -import java.security.KeyPair; -import java.security.interfaces.ECPrivateKey; -import java.security.interfaces.ECPublicKey; -import java.time.Instant; -import java.util.List; -import java.util.Map; -import java.util.function.Supplier; - -import static org.eclipse.edc.jsonld.util.JacksonJsonLd.createObjectMapper; -import static org.eclipse.tractusx.edc.helpers.IatpHelperFunctions.createVc; -import static org.eclipse.tractusx.edc.helpers.IatpHelperFunctions.frameworkAgreementSubject; -import static org.eclipse.tractusx.edc.helpers.IatpHelperFunctions.generateKeyPair; -import static org.eclipse.tractusx.edc.helpers.IatpHelperFunctions.membershipSubject; -import static org.mockito.Mockito.mock; - -/** - * Dataspace issuer configurations - */ -public class DataspaceIssuer { - - public static final String DATASPACE_ISSUER = "did:example:dataspace_issuer"; - private static final ObjectMapper MAPPER = createObjectMapper(); - private static final String KEY_ID = "#key1"; - private final JwsSignature2020Suite jws2020suite = new JwsSignature2020Suite(MAPPER); - private final DidDocument didDocument; - private final KeyPair keyPair; - - public DataspaceIssuer() { - keyPair = generateKeyPair(); - didDocument = generateDidDocument(); - } - - public String didUrl() { - return DATASPACE_ISSUER; - } - - public DidDocument didDocument() { - return didDocument; - } - - public String verificationId() { - return DATASPACE_ISSUER + KEY_ID; - } - - public VerifiableCredentialResource issueCredential(IatpParticipant participant, JsonLd jsonLd, String type, Supplier credentialSubjectSupplier, Supplier subjectSupplier) { - var credential = VerifiableCredential.Builder.newInstance() - .type(type) - .credentialSubject(credentialSubjectSupplier.get()) - .issuer(new Issuer(didUrl(), Map.of())) - .issuanceDate(Instant.now()) - .build(); - - var rawVc = createLdpVc(jsonLd, type, subjectSupplier); - return VerifiableCredentialResource.Builder.newInstance() - .issuerId(didUrl()) - .participantId(participant.didUrl()) - .holderId(participant.getBpn()) - .credential(new VerifiableCredentialContainer(rawVc, CredentialFormat.JSON_LD, credential)) - .build(); - - } - - public VerifiableCredentialResource issueMembershipCredential(IatpParticipant participant, JsonLd jsonLd) { - return issueCredential(participant, jsonLd, "MembershipCredential", () -> CredentialSubject.Builder.newInstance() - .claim("holderIdentifier", participant.getBpn()) - .build(), - () -> membershipSubject(participant.didUrl(), participant.getBpn())); - } - - public VerifiableCredentialResource issueDismantlerCredential(IatpParticipant participant, JsonLd jsonLd) { - return issueCredential(participant, jsonLd, "DismantlerCredential", () -> CredentialSubject.Builder.newInstance() - .claim("holderIdentifier", participant.didUrl()) - .claim("activityType", "vehicleDismantle") - .claim("allowedVehicleBrands", List.of("Moskvich", "Lada")) - .build(), - () -> Json.createObjectBuilder() - .add("type", "MembershipCredential") - .add("holderIdentifier", participant.didUrl()) - .add("activityType", "vehicleDismantle") - .add("allowedVehicleBrands", Json.createArrayBuilder().add("Moskvich").add("Lada").build()) - .add("id", participant.didUrl()) - .build()); - } - - public VerifiableCredentialResource issueFrameworkCredential(IatpParticipant participant, JsonLd jsonLd, String credentialType) { - return issueCredential(participant, jsonLd, credentialType, () -> CredentialSubject.Builder.newInstance() - .claim("holderIdentifier", participant.getBpn()) - .build(), - () -> frameworkAgreementSubject(participant.didUrl(), participant.getBpn(), credentialType)); - - } - - private String createLdpVc(JsonLd jsonLd, String type, Supplier subjectSupplier) { - var issuer = LdpIssuer.Builder.newInstance() - .jsonLd(jsonLd) - .monitor(mock()) - .build(); - - var proofOptions = jws2020suite.createOptions() - .created(Instant.now()) - .verificationMethod(new JwkMethod(URI.create(verificationId()), null, null, null)) - .purpose(URI.create("https://w3id.org/security#assertionMethod")); - - var key = new ECKey.Builder(Curve.P_256, (ECPublicKey) keyPair.getPublic()).privateKey(keyPair.getPrivate()).build(); - - var vc = createVc(didUrl(), type, subjectSupplier); - var result = issuer.signDocument(vc, createKeyPair(key, verificationId()), proofOptions).orElseThrow(err -> new RuntimeException(err.getFailureDetail())); - - try { - return MAPPER.writeValueAsString(result); - } catch (JsonProcessingException e) { - throw new RuntimeException(e); - } - } - - private com.apicatalog.ld.signature.key.KeyPair createKeyPair(JWK jwk, String id) { - var type = URI.create("https://w3id.org/security#JsonWebKey2020"); - return new JwkMethod(URI.create(id), type, null, jwk); - } - - private DidDocument generateDidDocument() { - - var ecKey = new ECKey.Builder(Curve.P_256, (ECPublicKey) keyPair.getPublic()) - .privateKey((ECPrivateKey) keyPair.getPrivate()) - .build(); - - var verificationMethod = VerificationMethod.Builder.newInstance() - .id(verificationId()) - .controller(didUrl()) - .type("JsonWebKey2020") - .publicKeyJwk(ecKey.toPublicJWK().toJSONObject()) - .build(); - - return DidDocument.Builder.newInstance() - .id(didUrl()) - .authentication(List.of(KEY_ID)) - .verificationMethod(List.of(verificationMethod)) - .build(); - - } -} diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/tx/iatp/IatpDimParticipant.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/tx/iatp/IatpDimParticipant.java deleted file mode 100644 index e35e1150e..000000000 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/tx/iatp/IatpDimParticipant.java +++ /dev/null @@ -1,45 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.lifecycle.tx.iatp; - -import org.eclipse.tractusx.edc.lifecycle.tx.TxParticipant; - -import java.net.URI; -import java.util.HashMap; -import java.util.Map; - -/** - * Extension of {@link IatpParticipant} with DIM specific configuration - */ -public class IatpDimParticipant extends IatpParticipant { - private final URI dimUri; - - public IatpDimParticipant(TxParticipant participant, URI stsUri, URI dimUri) { - super(participant, stsUri); - this.dimUri = dimUri; - } - - @Override - public Map iatpConfiguration(TxParticipant... others) { - var config = new HashMap<>(super.iatpConfiguration(others)); - config.put("edc.iam.sts.dim.url", dimUri.toString()); - return config; - } -} diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/tx/iatp/IatpParticipant.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/tx/iatp/IatpParticipant.java deleted file mode 100644 index 4cb827626..000000000 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/tx/iatp/IatpParticipant.java +++ /dev/null @@ -1,165 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.lifecycle.tx.iatp; - -import com.nimbusds.jose.jwk.Curve; -import com.nimbusds.jose.jwk.ECKey; -import org.eclipse.edc.iam.did.spi.document.DidDocument; -import org.eclipse.edc.iam.did.spi.document.Service; -import org.eclipse.edc.iam.did.spi.document.VerificationMethod; -import org.eclipse.tractusx.edc.lifecycle.tx.TxParticipant; - -import java.net.URI; -import java.security.KeyPair; -import java.security.interfaces.ECPrivateKey; -import java.security.interfaces.ECPublicKey; -import java.util.Arrays; -import java.util.Base64; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.stream.Stream; - -import static java.lang.String.format; -import static org.eclipse.edc.util.io.Ports.getFreePort; -import static org.eclipse.tractusx.edc.helpers.IatpHelperFunctions.generateKeyPair; -import static org.eclipse.tractusx.edc.helpers.IatpHelperFunctions.toPemEncoded; -import static org.eclipse.tractusx.edc.lifecycle.tx.iatp.DataspaceIssuer.DATASPACE_ISSUER; - -/** - * Wrapper of {@link TxParticipant} with IATP specific configurations - */ -public class IatpParticipant { - - public static final String KEY_ID = "key1"; - public static final String DID_EXAMPLE = "did:example:"; - protected final URI csService = URI.create("http://localhost:" + getFreePort() + "/api/resolution"); - private final TxParticipant participant; - private final URI stsUri; - private final KeyPair keyPair; - private final DidDocument didDocument; - private final String privateKey; - private final String publicKey; - - public IatpParticipant(TxParticipant participant, URI stsUri) { - this.participant = participant; - this.stsUri = stsUri; - this.keyPair = generateKeyPair(); - this.didDocument = generateDidDocument(); - this.privateKey = toPemEncoded(keyPair.getPrivate()); - this.publicKey = toPemEncoded(keyPair.getPublic()); - } - - public String getBpn() { - return participant.getBpn(); - } - - public String getName() { - return participant.getName(); - } - - public Map iatpConfiguration(TxParticipant... others) { - var did = DID_EXAMPLE + participant.getName().toLowerCase(); - var iatpConfiguration = new HashMap<>(participant.getConfiguration()) { - { - - put("edc.iam.sts.oauth.token.url", stsUri + "/token"); - put("edc.iam.sts.oauth.client.id", getBpn()); - put("edc.iam.sts.oauth.client.secret.alias", "client_secret_alias"); - put("edc.iam.issuer.id", did); - put("edc.ih.iam.id", participant.getBpn()); - put("tx.vault.seed.secrets", "client_secret_alias:client_secret"); - put("edc.ih.iam.publickey.pem", publicKey()); - put("web.http.resolution.port", String.valueOf(csService.getPort())); - put("web.http.resolution.path", csService.getPath()); - put("edc.agent.identity.key", "client_id"); - put("edc.iam.trusted-issuer.issuer.id", DATASPACE_ISSUER); - } - }; - - Stream.concat(Stream.of(participant), Arrays.stream(others)).forEach(p -> { - var prefix = format("tx.iam.iatp.audiences.%s", p.getName().toLowerCase()); - var participantDid = DID_EXAMPLE + p.getName().toLowerCase(); - iatpConfiguration.put(prefix + "_endpoint" + ".from", p.getProtocolEndpoint().getUrl().toString()); - iatpConfiguration.put(prefix + "_endpoint" + ".to", participantDid); - iatpConfiguration.put(prefix + "_id" + ".from", p.getBpn()); - iatpConfiguration.put(prefix + "_id" + ".to", participantDid); - }); - return iatpConfiguration; - } - - public String didUrl() { - return DID_EXAMPLE + participant.getName().toLowerCase(); - } - - public String verificationId() { - return didUrl() + "#" + KEY_ID; - } - - public String keyId() { - return KEY_ID; - } - - public String privateKey() { - return privateKey; - } - - public String publicKey() { - return publicKey; - } - - public DidDocument didDocument() { - return didDocument; - } - - - public KeyPair getKeyPair() { - return keyPair; - } - - private DidDocument generateDidDocument() { - var service = new Service(); - service.setId("#credential-service"); - service.setType("CredentialService"); - service.setServiceEndpoint(csService + "/v1/participants/" + toBase64(didUrl())); - - var ecKey = new ECKey.Builder(Curve.P_256, (ECPublicKey) keyPair.getPublic()) - .privateKey((ECPrivateKey) keyPair.getPrivate()) - .build(); - - var verificationMethod = VerificationMethod.Builder.newInstance() - .id(verificationId()) - .controller(didUrl()) - .type("JsonWebKey2020") - .publicKeyJwk(ecKey.toPublicJWK().toJSONObject()) - .build(); - - return DidDocument.Builder.newInstance() - .id(didUrl()) - .service(List.of(service)) - .authentication(List.of("#key1")) - .verificationMethod(List.of(verificationMethod)) - .build(); - } - - private String toBase64(String s) { - return Base64.getUrlEncoder().encodeToString(s.getBytes()); - } -} diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/tx/iatp/SecureTokenService.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/tx/iatp/SecureTokenService.java deleted file mode 100644 index a556dda33..000000000 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/tx/iatp/SecureTokenService.java +++ /dev/null @@ -1,82 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.lifecycle.tx.iatp; - -import org.eclipse.tractusx.edc.lifecycle.tx.TxParticipant; - -import java.net.URI; -import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; - -import static java.lang.String.format; -import static org.eclipse.edc.util.io.Ports.getFreePort; - -/** - * STS configurations - */ -public class SecureTokenService { - - protected final URI stsUri = URI.create("http://localhost:" + getFreePort() + "/api/v1/sts"); - protected final TxParticipant stsParticipant = TxParticipant.Builder.newInstance() - .name("STS") - .id("STS") - .build(); - - public Map stsConfiguration(IatpParticipant... participants) { - var stsConfiguration = new HashMap() { - { - - put("web.http.sts.port", String.valueOf(stsUri.getPort())); - put("web.http.sts.path", stsUri.getPath()); - put("edc.dataplane.token.validation.endpoint", ""); - put("tx.vault.seed.secrets", "client_secret_alias:client_secret"); - } - }; - - Arrays.stream(participants).forEach(participant -> { - var prefix = format("edc.iam.sts.clients.%s", participant.getName().toLowerCase()); - stsConfiguration.put(prefix + ".name", participant.getName()); - stsConfiguration.put(prefix + ".id", UUID.randomUUID().toString()); - stsConfiguration.put(prefix + ".client_id", participant.getBpn()); - stsConfiguration.put(prefix + ".did", participant.didUrl()); - stsConfiguration.put(prefix + ".secret.alias", "client_secret_alias"); - stsConfiguration.put(prefix + ".private-key.alias", participant.verificationId()); - stsConfiguration.put(prefix + ".public-key.reference", participant.verificationId()); - }); - - var baseConfiguration = stsParticipant.getConfiguration(); - stsConfiguration.putAll(baseConfiguration); - return stsConfiguration; - } - - public String getBpn() { - return stsParticipant.getBpn(); - } - - public String getName() { - return stsParticipant.getName(); - } - - public URI stsUri() { - return stsUri; - } -} diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/TestRuntimeConfiguration.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tag/DimIntegrationTest.java similarity index 67% rename from edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/TestRuntimeConfiguration.java rename to edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tag/DimIntegrationTest.java index 861796680..267814b79 100644 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/TestRuntimeConfiguration.java +++ b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tag/DimIntegrationTest.java @@ -17,15 +17,20 @@ * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ -package org.eclipse.tractusx.edc.lifecycle; +package org.eclipse.tractusx.edc.tag; -public class TestRuntimeConfiguration { - - public static final String BPN_SUFFIX = "-BPN"; - public static final String SOKRATES_NAME = "SOKRATES"; - public static final String SOKRATES_BPN = SOKRATES_NAME + BPN_SUFFIX; - public static final String PLATO_NAME = "PLATO"; - public static final String PLATO_BPN = PLATO_NAME + BPN_SUFFIX; - static final String DB_SCHEMA_NAME = "testschema"; +import org.eclipse.edc.junit.annotations.IntegrationTest; +import org.junit.jupiter.api.Tag; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target({ ElementType.TYPE }) +@Retention(RetentionPolicy.RUNTIME) +@IntegrationTest +@Tag("DimIntegrationTest") +public @interface DimIntegrationTest { } + diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/catalog/DimCatalogTest.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/catalog/DimCatalogTest.java new file mode 100644 index 000000000..1d0cb3edd --- /dev/null +++ b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/catalog/DimCatalogTest.java @@ -0,0 +1,84 @@ +/******************************************************************************** + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +package org.eclipse.tractusx.edc.tests.catalog; + +import org.eclipse.tractusx.edc.lifecycle.DimParticipant; +import org.eclipse.tractusx.edc.lifecycle.ParticipantRuntime; +import org.eclipse.tractusx.edc.tag.DimIntegrationTest; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.eclipse.edc.test.system.utils.PolicyFixtures.noConstraintPolicy; +import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.CX_POLICY_NS; +import static org.eclipse.tractusx.edc.helpers.DimHelper.configureParticipant; +import static org.eclipse.tractusx.edc.lifecycle.Runtimes.dimRuntime; +import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.PLATO_NAME; +import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.SOKRATES_NAME; +import static org.eclipse.tractusx.edc.tests.helpers.CatalogHelperFunctions.getDatasetAssetId; +import static org.eclipse.tractusx.edc.tests.helpers.PolicyHelperFunctions.frameworkPolicy; + +@DimIntegrationTest +@Disabled +public class DimCatalogTest { + + protected static final DimParticipant SOKRATES = configureParticipant(SOKRATES_NAME); + protected static final DimParticipant PLATO = configureParticipant(PLATO_NAME); + + @RegisterExtension + protected static final ParticipantRuntime PLATO_RUNTIME = dimRuntime(PLATO.getName(), PLATO.iatpConfiguration(SOKRATES)); + + @RegisterExtension + protected static final ParticipantRuntime SOKRATES_RUNTIME = dimRuntime(SOKRATES.getName(), SOKRATES.iatpConfiguration(PLATO)); + + @Test + @DisplayName("Verify that Sokrates receives only the offers he is permitted to") + void requestCatalog_filteredByDismantler_shouldReturnOffer() { + // arrange + PLATO.createAsset("test-asset"); + PLATO.createAsset("test-asset-1"); + + var bpnAccessPolicy = frameworkPolicy(Map.of(CX_POLICY_NS + "Membership", "active")); + var dismantlerAccessPolicy = frameworkPolicy(Map.of(CX_POLICY_NS + "Dismantler", "active")); + + var bpnAccessId = PLATO.createPolicyDefinition(bpnAccessPolicy); + var contractPolicyId = PLATO.createPolicyDefinition(noConstraintPolicy()); + var dismantlerAccessPolicyId = PLATO.createPolicyDefinition(dismantlerAccessPolicy); + + PLATO.createContractDefinition("test-asset", "test-def", bpnAccessId, contractPolicyId); + PLATO.createContractDefinition("test-asset-1", "test-def-2", dismantlerAccessPolicyId, contractPolicyId); + + // act + var catalog = SOKRATES.getCatalogDatasets(PLATO); + + // assert + assertThat(catalog).isNotEmpty() + .hasSize(1) + .allSatisfy(co -> { + assertThat(getDatasetAssetId(co)).isEqualTo("test-asset"); + }); + + } + +} diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/catalog/MiwSsiCatalogTest.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/catalog/MiwSsiCatalogTest.java index e067c19b2..01f2e7233 100644 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/catalog/MiwSsiCatalogTest.java +++ b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/catalog/MiwSsiCatalogTest.java @@ -19,61 +19,43 @@ package org.eclipse.tractusx.edc.tests.catalog; +import org.eclipse.tractusx.edc.lifecycle.MiwParticipant; import org.eclipse.tractusx.edc.lifecycle.ParticipantRuntime; -import org.eclipse.tractusx.edc.lifecycle.tx.TxParticipant; import org.eclipse.tractusx.edc.tag.MiwIntegrationTest; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; -import java.util.HashMap; import java.util.Map; import static org.assertj.core.api.Assertions.assertThat; import static org.eclipse.edc.test.system.utils.PolicyFixtures.noConstraintPolicy; -import static org.eclipse.tractusx.edc.helpers.CatalogHelperFunctions.getDatasetAssetId; -import static org.eclipse.tractusx.edc.helpers.PolicyHelperFunctions.TX_NAMESPACE; -import static org.eclipse.tractusx.edc.helpers.PolicyHelperFunctions.frameworkPolicy; -import static org.eclipse.tractusx.edc.helpers.PolicyHelperFunctions.frameworkTemplatePolicy; -import static org.eclipse.tractusx.edc.lifecycle.TestRuntimeConfiguration.SOKRATES_BPN; -import static org.eclipse.tractusx.edc.lifecycle.TestRuntimeConfiguration.SOKRATES_NAME; +import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.TX_NAMESPACE; +import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.SOKRATES_BPN; +import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.SOKRATES_NAME; +import static org.eclipse.tractusx.edc.tests.helpers.CatalogHelperFunctions.getDatasetAssetId; +import static org.eclipse.tractusx.edc.tests.helpers.PolicyHelperFunctions.frameworkPolicy; @MiwIntegrationTest public class MiwSsiCatalogTest { - protected static final TxParticipant SOKRATES = TxParticipant.Builder.newInstance() + protected static final String MIW_SOKRATES_URL = "http://localhost:8000"; + protected static final String OAUTH_TOKEN_URL = "http://localhost:8080/realms/miw_test/protocol/openid-connect/token"; + protected static final MiwParticipant SOKRATES = MiwParticipant.Builder.newInstance() .name(SOKRATES_NAME) .id(SOKRATES_BPN) + .miwUri(MIW_SOKRATES_URL) + .oauth2Uri(OAUTH_TOKEN_URL) .build(); - static final String MIW_SOKRATES_URL = "http://localhost:8000"; - static final String OAUTH_TOKEN_URL = "http://localhost:8080/realms/miw_test/protocol/openid-connect/token"; + @RegisterExtension protected static final ParticipantRuntime SOKRATES_RUNTIME = new ParticipantRuntime( ":edc-tests:runtime:runtime-memory-ssi", SOKRATES.getName(), - SOKRATES.getBpn(), - sokratesSsiMiwConfiguration() + SOKRATES.getConfiguration() ); - public static Map sokratesSsiMiwConfiguration() { - var ssiConfiguration = new HashMap() { - { - put("tx.ssi.miw.url", MIW_SOKRATES_URL); - put("tx.ssi.oauth.token.url", OAUTH_TOKEN_URL); - put("tx.ssi.oauth.client.id", "miw_private_client"); - put("tx.ssi.oauth.client.secret.alias", "client_secret_alias"); - put("tx.ssi.miw.authority.id", "BPNL000000000000"); - put("tx.ssi.miw.authority.issuer", "did:web:localhost%3A8000:BPNL000000000000"); - put("tx.vault.seed.secrets", "client_secret_alias:miw_private_client"); - put("tx.ssi.endpoint.audience", SOKRATES.getProtocolEndpoint().getUrl().toString()); - } - }; - var baseConfiguration = SOKRATES.getConfiguration(); - ssiConfiguration.putAll(baseConfiguration); - return ssiConfiguration; - } - @Test @DisplayName("Verify that Sokrates receives only the offers he is permitted to") void requestCatalog_fulfillsPolicy_shouldReturnOffer() { @@ -91,7 +73,6 @@ void requestCatalog_fulfillsPolicy_shouldReturnOffer() { SOKRATES.createContractDefinition("test-asset", "test-def", bpnAccessId, contractPolicyId); SOKRATES.createContractDefinition("test-asset-1", "test-def-2", dismantlerAccessPolicyId, contractPolicyId); - // act var catalog = SOKRATES.getCatalogDatasets(SOKRATES); @@ -104,34 +85,4 @@ void requestCatalog_fulfillsPolicy_shouldReturnOffer() { } - - @Test - @DisplayName("Verify that Sokrates receives only the offers he is permitted to using @context") - void requestCatalog_fulfillsPolicy_shouldReturnOffer_withContexts() { - // arrange - SOKRATES.createAsset("test-asset"); - SOKRATES.createAsset("test-asset-1"); - - var bpnAccessPolicy = frameworkTemplatePolicy("test-ap1", "BPN"); - var contractPolicy = noConstraintPolicy(); - var dismantlerAccessPolicy = frameworkTemplatePolicy("test-ap2", "Dismantler"); - - SOKRATES.createPolicy(bpnAccessPolicy); - var contractPolicyId = SOKRATES.createPolicyDefinition(contractPolicy); - SOKRATES.createPolicy(dismantlerAccessPolicy); - - SOKRATES.createContractDefinition("test-asset", "test-def", "test-ap1", contractPolicyId); - SOKRATES.createContractDefinition("test-asset-1", "test-def-2", "test-ap2", contractPolicyId); - - // act - var catalog = SOKRATES.getCatalogDatasets(SOKRATES); - - // assert - assertThat(catalog).isNotEmpty() - .hasSize(1) - .allSatisfy(co -> { - assertThat(getDatasetAssetId(co)).isEqualTo("test-asset"); - }); - - } } diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/DimHttpPullTransferTest.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/DimHttpPullTransferTest.java new file mode 100644 index 000000000..e70bc2697 --- /dev/null +++ b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/DimHttpPullTransferTest.java @@ -0,0 +1,56 @@ +/******************************************************************************** + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +package org.eclipse.tractusx.edc.tests.transfer; + +import org.eclipse.tractusx.edc.lifecycle.DimParticipant; +import org.eclipse.tractusx.edc.lifecycle.ParticipantRuntime; +import org.eclipse.tractusx.edc.tag.DimIntegrationTest; +import org.eclipse.tractusx.edc.tests.TractusxParticipantBase; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.extension.RegisterExtension; + +import static org.eclipse.tractusx.edc.helpers.DimHelper.configureParticipant; +import static org.eclipse.tractusx.edc.lifecycle.Runtimes.dimRuntime; +import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.PLATO_NAME; +import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.SOKRATES_NAME; + +@DimIntegrationTest +@Disabled +public class DimHttpPullTransferTest extends HttpConsumerPullBaseTest { + + protected static final DimParticipant SOKRATES = configureParticipant(SOKRATES_NAME); + protected static final DimParticipant PLATO = configureParticipant(PLATO_NAME); + + @RegisterExtension + protected static final ParticipantRuntime PLATO_RUNTIME = dimRuntime(PLATO.getName(), PLATO.iatpConfiguration(SOKRATES)); + + @RegisterExtension + protected static final ParticipantRuntime SOKRATES_RUNTIME = dimRuntime(SOKRATES.getName(), SOKRATES.iatpConfiguration(PLATO)); + + @Override + protected TractusxParticipantBase plato() { + return PLATO; + } + + @Override + protected TractusxParticipantBase sokrates() { + return SOKRATES; + } +} diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/token/MockBpnIdentityService.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/token/MockBpnIdentityService.java deleted file mode 100644 index caf733a0b..000000000 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/token/MockBpnIdentityService.java +++ /dev/null @@ -1,70 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.token; - -import org.eclipse.edc.spi.iam.ClaimToken; -import org.eclipse.edc.spi.iam.IdentityService; -import org.eclipse.edc.spi.iam.TokenParameters; -import org.eclipse.edc.spi.iam.TokenRepresentation; -import org.eclipse.edc.spi.iam.VerificationContext; -import org.eclipse.edc.spi.result.Result; -import org.eclipse.edc.spi.types.TypeManager; - -import java.util.Map; - -import static java.lang.String.format; - -/** - * An {@link IdentityService} that will inject the BPN claim in every token. - * Please only use in testing scenarios! - */ -public class MockBpnIdentityService implements IdentityService { - - private static final String BUSINESS_PARTNER_NUMBER_CLAIM = "BusinessPartnerNumber"; - private final String businessPartnerNumber; - private final TypeManager typeManager = new TypeManager(); - - public MockBpnIdentityService(String businessPartnerNumber) { - this.businessPartnerNumber = businessPartnerNumber; - } - - @Override - public Result obtainClientCredentials(TokenParameters parameters) { - var token = Map.of(BUSINESS_PARTNER_NUMBER_CLAIM, businessPartnerNumber); - - var tokenRepresentation = TokenRepresentation.Builder.newInstance() - .token(typeManager.writeValueAsString(token)) - .build(); - return Result.success(tokenRepresentation); - } - - @Override - public Result verifyJwtToken(TokenRepresentation tokenRepresentation, VerificationContext verificationContext) { - - var token = typeManager.readValue(tokenRepresentation.getToken(), Map.class); - if (token.containsKey(BUSINESS_PARTNER_NUMBER_CLAIM)) { - return Result.success(ClaimToken.Builder.newInstance() - .claim(BUSINESS_PARTNER_NUMBER_CLAIM, token.get(BUSINESS_PARTNER_NUMBER_CLAIM)) - .build()); - } - return Result.failure(format("Expected %s claim, but token did not contain them", BUSINESS_PARTNER_NUMBER_CLAIM)); - } - -} diff --git a/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/ParticipantEdrApi.java b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/ParticipantEdrApi.java index 48b4f6576..443dd8967 100644 --- a/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/ParticipantEdrApi.java +++ b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/ParticipantEdrApi.java @@ -24,6 +24,7 @@ import jakarta.json.Json; import jakarta.json.JsonArray; import jakarta.json.JsonObject; +import org.eclipse.edc.test.system.utils.Participant; import static io.restassured.http.ContentType.JSON; import static jakarta.json.Json.createObjectBuilder; @@ -44,9 +45,9 @@ */ public class ParticipantEdrApi { - private final TxParticipant participant; + private final Participant participant; - public ParticipantEdrApi(TxParticipant participant) { + public ParticipantEdrApi(Participant participant) { this.participant = participant; } diff --git a/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/TractusxIatpParticipantBase.java b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/TractusxIatpParticipantBase.java new file mode 100644 index 000000000..fada1c3de --- /dev/null +++ b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/TractusxIatpParticipantBase.java @@ -0,0 +1,107 @@ +/******************************************************************************** + * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +package org.eclipse.tractusx.edc.tests; + +import java.net.URI; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import java.util.stream.Stream; + +/** + * Specialized version of {@link TractusxParticipantBase} with IATP configurations + */ +public abstract class TractusxIatpParticipantBase extends TractusxParticipantBase { + + protected URI stsUri; + protected String stsClientId; + protected String stsClientSecret; + protected String trustedIssuer; + + public Map iatpConfiguration(TractusxIatpParticipantBase... others) { + var iatpConfiguration = new HashMap<>(getConfiguration()) { + { + + put("edc.iam.sts.oauth.token.url", stsUri + "/token"); + put("edc.iam.sts.oauth.client.id", stsClientId); + put("edc.iam.sts.oauth.client.secret.alias", "client_secret_alias"); + put("edc.ih.iam.id", getBpn()); + put("tx.vault.seed.secrets", "client_secret_alias:%s".formatted(stsClientSecret)); + put("edc.ih.iam.publickey.alias", getFullKeyId()); + put("edc.agent.identity.key", "client_id"); + put("edc.iam.trusted-issuer.issuer.id", trustedIssuer); + put("edc.transfer.proxy.token.signer.privatekey.alias", getPrivateKeyAlias()); + put("edc.transfer.proxy.token.verifier.publickey.alias", getFullKeyId()); + } + }; + + Stream.concat(Stream.of(this), Arrays.stream(others)).forEach(p -> { + var prefix = "tx.iam.iatp.audiences.%s".formatted(p.getName().toLowerCase()); + iatpConfiguration.put("%s.from".formatted(prefix), p.getBpn()); + iatpConfiguration.put("%s.to".formatted(prefix), p.getDid()); + }); + return iatpConfiguration; + } + + public static class Builder

    > extends TractusxParticipantBase.Builder { + + protected Builder(P participant) { + super(participant); + } + + public B stsUri(URI stsUri) { + participant.stsUri = stsUri; + return self(); + } + + public B stsClientId(String stsClientId) { + participant.stsClientId = stsClientId; + return self(); + } + + public B stsClientSecret(String stsClientSecret) { + participant.stsClientSecret = stsClientSecret; + return self(); + } + + public B trustedIssuer(String trustedIssuer) { + participant.trustedIssuer = trustedIssuer; + return self(); + } + + @Override + public TractusxIatpParticipantBase build() { + super.build(); + Objects.requireNonNull(participant.stsUri, "STS URI should not be null"); + Objects.requireNonNull(participant.trustedIssuer, "Trusted issuer cannot be null"); + + if (participant.stsClientId == null) { + participant.stsClientId = participant.id; + } + + if (participant.stsClientSecret == null) { + participant.stsClientSecret = "clientSecret"; + } + return participant; + } + } + +} diff --git a/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/TractusxParticipantBase.java b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/TractusxParticipantBase.java new file mode 100644 index 000000000..cd8d8fe78 --- /dev/null +++ b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/TractusxParticipantBase.java @@ -0,0 +1,176 @@ +/* + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.eclipse.tractusx.edc.tests; + +import jakarta.json.Json; +import org.eclipse.edc.test.system.utils.Participant; +import org.jetbrains.annotations.NotNull; + +import java.net.URI; +import java.time.Duration; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +import static io.restassured.http.ContentType.JSON; +import static jakarta.json.Json.createObjectBuilder; +import static java.time.Duration.ofSeconds; +import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.ID; +import static org.eclipse.edc.util.io.Ports.getFreePort; +import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.TX_NAMESPACE; + +/** + * Base class for doing E2E tests with participants. It will replace {@link TxParticipant} + */ +public abstract class TractusxParticipantBase extends IdentityParticipant { + + public static final String API_KEY = "testkey"; + public static final Duration ASYNC_TIMEOUT = ofSeconds(60); + private final URI controlPlaneDefault = URI.create("http://localhost:" + getFreePort()); + private final URI controlPlaneControl = URI.create("http://localhost:" + getFreePort() + "/control"); + private final URI backendProviderProxy = URI.create("http://localhost:" + getFreePort() + "/events"); + private final URI dataPlaneProxy = URI.create("http://localhost:" + getFreePort()); + private final URI dataPlanePublic = URI.create("http://localhost:" + getFreePort() + "/public"); + + protected ParticipantEdrApi edrs; + protected ParticipantDataApi data; + protected String did; + + public void createAsset(String id) { + createAsset(id, new HashMap<>(), Map.of("type", "test-type")); + } + + public String getBpn() { + return getId(); + } + + /** + * Returns the base configuration + */ + public Map getConfiguration() { + return new HashMap<>() { + { + put("edc.connector.name", name); + put("edc.participant.id", id); + put("web.http.port", String.valueOf(controlPlaneDefault.getPort())); + put("web.http.path", "/api"); + put("web.http.protocol.port", String.valueOf(protocolEndpoint.getUrl().getPort())); + put("web.http.protocol.path", protocolEndpoint.getUrl().getPath()); + put("web.http.management.port", String.valueOf(managementEndpoint.getUrl().getPort())); + put("web.http.management.path", managementEndpoint.getUrl().getPath()); + put("web.http.control.port", String.valueOf(controlPlaneControl.getPort())); + put("web.http.control.path", controlPlaneControl.getPath()); + put("edc.dsp.callback.address", protocolEndpoint.getUrl().toString()); + put("edc.api.auth.key", "testkey"); + put("web.http.public.path", "/api/public"); + put("web.http.public.port", String.valueOf(dataPlanePublic.getPort())); + put("edc.transfer.proxy.token.signer.privatekey.alias", getPrivateKeyAlias()); + put("edc.transfer.proxy.token.verifier.publickey.alias", getFullKeyId()); + put("edc.transfer.send.retry.limit", "1"); + put("edc.transfer.send.retry.base-delay.ms", "100"); + put("tx.dpf.consumer.proxy.port", String.valueOf(dataPlaneProxy.getPort())); + put("edc.dataplane.token.validation.endpoint", controlPlaneControl + "/token"); + put("edc.dataplane.selector.httpplane.url", controlPlaneControl.toString()); + put("edc.dataplane.selector.httpplane.sourcetypes", "HttpData"); + put("edc.dataplane.selector.httpplane.destinationtypes", "HttpProxy"); + put("edc.dataplane.selector.httpplane.transfertypes", "HttpProxy-PULL"); + put("edc.dataplane.selector.httpplane.properties", "{\"publicApiUrl\":\"http://localhost:" + dataPlanePublic.getPort() + "/api/public/v2\"}"); + put("edc.receiver.http.dynamic.endpoint", "http://localhost:" + controlPlaneDefault.getPort() + "/api/consumer/datareference"); + put("tractusx.businesspartnervalidation.log.agreement.validation", "true"); + put("edc.agent.identity.key", "BusinessPartnerNumber"); + put("edc.data.encryption.keys.alias", "test-alias"); + put("tx.dpf.proxy.gateway.aas.proxied.path", backendProviderProxy.toString()); + put("tx.dpf.proxy.gateway.aas.authorization.type", "none"); + put("edc.iam.issuer.id", getDid()); + put("edc.dataplane.api.public.baseurl", "http://localhost:%d/api/public/v2/data".formatted(dataPlanePublic.getPort())); + } + }; + } + + /** + * Returns the client api for fetching EDRs + */ + public ParticipantEdrApi edrs() { + return edrs; + } + + /** + * Returns the client API for fetching data + */ + public ParticipantDataApi data() { + return data; + } + + /** + * Stores BPN groups + */ + public void storeBusinessPartner(String bpn, String... groups) { + var body = createObjectBuilder() + .add(ID, bpn) + .add(TX_NAMESPACE + "groups", Json.createArrayBuilder(Arrays.asList(groups))) + .build(); + managementEndpoint.baseRequest() + .contentType(JSON) + .body(body) + .when() + .post("/business-partner-groups") + .then() + .statusCode(204); + } + + @Override + public String getFullKeyId() { + return getDid() + "#" + getKeyId(); + } + + @NotNull + public String getDid() { + return did; + } + + public static class Builder

    > extends Participant.Builder { + + protected Builder(P participant) { + super(participant); + } + + public B did(String did) { + this.participant.did = did; + return self(); + } + + @Override + public TractusxParticipantBase build() { + if (participant.did == null) { + participant.did = "did:web:" + participant.name.toLowerCase(); + } + + super.managementEndpoint(new Endpoint(URI.create("http://localhost:" + getFreePort() + "/api/management"), Map.of("x-api-key", API_KEY))); + super.protocolEndpoint(new Endpoint(URI.create("http://localhost:" + getFreePort() + "/protocol"))); + super.timeout(ASYNC_TIMEOUT); + super.build(); + + this.participant.edrs = new ParticipantEdrApi(participant); + this.participant.data = new ParticipantDataApi(); + return participant; + } + } + +} diff --git a/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/transfer/HttpConsumerPullBaseTest.java b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/transfer/HttpConsumerPullBaseTest.java new file mode 100644 index 000000000..ea6383b23 --- /dev/null +++ b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/transfer/HttpConsumerPullBaseTest.java @@ -0,0 +1,129 @@ +/******************************************************************************** + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +package org.eclipse.tractusx.edc.tests.transfer; + +import jakarta.json.Json; +import jakarta.json.JsonObject; +import okhttp3.mockwebserver.MockResponse; +import okhttp3.mockwebserver.MockWebServer; +import org.eclipse.edc.connector.transfer.spi.types.TransferProcessStates; +import org.eclipse.tractusx.edc.tests.TractusxParticipantBase; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.util.Map; +import java.util.concurrent.atomic.AtomicReference; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.awaitility.Awaitility.await; +import static org.awaitility.pollinterval.FibonacciPollInterval.fibonacci; +import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.TYPE; +import static org.eclipse.edc.spi.CoreConstants.EDC_NAMESPACE; +import static org.eclipse.tractusx.edc.tests.TxParticipant.ASYNC_TIMEOUT; +import static org.eclipse.tractusx.edc.tests.helpers.PolicyHelperFunctions.bnpPolicy; + +/** + * Base tests for Http PULL scenario + */ +public abstract class HttpConsumerPullBaseTest { + + protected MockWebServer server; + + public static JsonObject createProxyRequest() { + return Json.createObjectBuilder() + .add(TYPE, EDC_NAMESPACE + "DataAddress") + .add(EDC_NAMESPACE + "type", "HttpProxy-PULL") + .build(); + + } + + @BeforeEach + void setup() { + server = new MockWebServer(); + } + + @Test + void transferData_privateBackend() throws IOException, InterruptedException { + var assetId = "api-asset-1"; + var url = server.url("/mock/api"); + server.start(); + + + Map dataAddress = Map.of( + "baseUrl", url.toString(), + "type", "HttpData", + "contentType", "application/json" + ); + + plato().createAsset(assetId, Map.of(), dataAddress); + + var accessPolicyId = plato().createPolicyDefinition(createAccessPolicy(sokrates().getBpn())); + var contractPolicyId = plato().createPolicyDefinition(createContractPolicy(sokrates().getBpn())); + plato().createContractDefinition(assetId, "def-1", accessPolicyId, contractPolicyId); + var transferProcessId = sokrates().requestAsset(plato(), assetId, Json.createObjectBuilder().build(), createProxyRequest()); + + var contractAgreementId = new AtomicReference(); + var edr = new AtomicReference(); + + // wait until transfer process completes + await().pollInterval(fibonacci()) + .atMost(ASYNC_TIMEOUT) + .untilAsserted(() -> { + var tpState = sokrates().getTransferProcessState(transferProcessId); + assertThat(tpState).isNotNull().isEqualTo(TransferProcessStates.STARTED.toString()); + }); + + // wait until EDC is available on the consumer side + server.enqueue(new MockResponse().setBody("test response").setResponseCode(200)); + await().pollInterval(fibonacci()) + .atMost(ASYNC_TIMEOUT) + .untilAsserted(() -> { + edr.set(sokrates().edrs().getEdr(transferProcessId)); + assertThat(edr).isNotNull(); + }); + + // pull data out of provider's backend service: + // Prov-DP -> Prov-backend + assertThat(sokrates().data().pullData(edr.get(), Map.of())).isEqualTo("test response"); + var rq = server.takeRequest(); + assertThat(rq.getHeader("Edc-Contract-Agreement-Id")).isNotNull(); + assertThat(rq.getHeader("Edc-Bpn")).isEqualTo(sokrates().getBpn()); + assertThat(rq.getMethod()).isEqualToIgnoringCase("GET"); + } + + @AfterEach + void teardown() throws IOException { + server.shutdown(); + } + + protected abstract TractusxParticipantBase plato(); + + protected abstract TractusxParticipantBase sokrates(); + + protected JsonObject createAccessPolicy(String bpn) { + return bnpPolicy(bpn); + } + + protected JsonObject createContractPolicy(String bpn) { + return bnpPolicy(bpn); + } +} diff --git a/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/DimHttpConsumerPullWithProxyInMemoryTest.java b/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/DimHttpConsumerPullWithProxyInMemoryTest.java index f9f9ea2d0..68f20aa3e 100644 --- a/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/DimHttpConsumerPullWithProxyInMemoryTest.java +++ b/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/DimHttpConsumerPullWithProxyInMemoryTest.java @@ -91,7 +91,7 @@ static void prepare() throws IOException { dimDispatcher = new MockWebServer(); dimDispatcher.start(DIM_URI.getPort()); - dimDispatcher.setDispatcher(new DimDispatcher("/iatp", generatorServices)); + dimDispatcher.setDispatcher(new DimDispatcher(generatorServices)); // create the DIDs cache var dids = new HashMap(); diff --git a/edc-tests/runtime/runtime-postgresql-hashicorp/build.gradle.kts b/edc-tests/runtime/iatp/runtime-memory-iatp-dim/build.gradle.kts similarity index 69% rename from edc-tests/runtime/runtime-postgresql-hashicorp/build.gradle.kts rename to edc-tests/runtime/iatp/runtime-memory-iatp-dim/build.gradle.kts index 6a4339af2..8ad020a26 100644 --- a/edc-tests/runtime/runtime-postgresql-hashicorp/build.gradle.kts +++ b/edc-tests/runtime/iatp/runtime-memory-iatp-dim/build.gradle.kts @@ -1,5 +1,5 @@ /******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) * * See the NOTICE file(s) distributed with this work for additional * information regarding copyright ownership. @@ -22,20 +22,23 @@ plugins { id("application") } - dependencies { // use basic (all in-mem) control plane - implementation(project(":edc-controlplane:edc-controlplane-postgresql-hashicorp-vault")) { + implementation(project(":edc-controlplane:edc-controlplane-base")) { exclude(module = "data-encryption") - exclude(module = "json-ld-core") exclude(module = "ssi-identity-core") exclude(module = "ssi-miw-credential-client") exclude(module = "ssi-identity-extractor") exclude(module = "cx-policy-legacy") } + implementation(project(":edc-extensions:cx-policy")) + implementation(project(":core:json-ld-core")) + implementation(project(":edc-extensions:iatp:tx-iatp")) + implementation(project(":edc-extensions:iatp:tx-iatp-sts-dim")) implementation(project(":edc-tests:runtime:extensions")) + implementation(project(":edc-tests:runtime:iatp:iatp-extensions")) // use basic (all in-mem) data plane runtimeOnly(project(":edc-dataplane:edc-dataplane-base")) { @@ -43,6 +46,13 @@ dependencies { } implementation(libs.edc.core.controlplane) + implementation(libs.edc.identity.core.trust) + implementation(libs.edc.identity.core.did) + implementation(libs.edc.identity.did.web) + implementation(libs.edc.identity.trust.transform) + implementation(libs.edc.identity.trust.issuers.configuration) + implementation(libs.edc.auth.oauth2.client) + // for the controller implementation(libs.jakarta.rsApi) } diff --git a/edc-tests/runtime/runtime-postgresql-hashicorp/README.md b/edc-tests/runtime/runtime-postgresql-hashicorp/README.md deleted file mode 100644 index 7ec7be084..000000000 --- a/edc-tests/runtime/runtime-postgresql-hashicorp/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# PostgreSQL + Hashicorp Vault Runtime for Testing Purposes - -This module provides a very small,runtime using PostgreSQL as persistence backend and Hashicorp Vault to execute tests against. Not intended for anything other than testing! diff --git a/settings.gradle.kts b/settings.gradle.kts index 846584b6b..8a4d6c9e2 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -76,9 +76,9 @@ include(":edc-tests:runtime:runtime-memory") include(":edc-tests:runtime:dataplane-cloud") include(":edc-tests:runtime:runtime-memory-ssi") include(":edc-tests:runtime:runtime-postgresql") -include(":edc-tests:runtime:runtime-postgresql-hashicorp") include(":edc-tests:runtime:iatp:runtime-memory-iatp-ih") include(":edc-tests:runtime:iatp:runtime-memory-iatp-dim-ih") +include(":edc-tests:runtime:iatp:runtime-memory-iatp-dim") include(":edc-tests:runtime:iatp:runtime-memory-sts") include(":edc-tests:runtime:iatp:iatp-extensions") include(":edc-tests:edc-dataplane:edc-dataplane-tokenrefresh-tests") From 04f1224e5a2689c657724b2a68c5a693ae7f24df Mon Sep 17 00:00:00 2001 From: Enrico Risa Date: Mon, 25 Mar 2024 10:31:02 +0100 Subject: [PATCH 068/100] chore: fixes after junit and keys module refactoring (#1159) * chore: fixes after junit and keys module refactoring * chore: dependencies file --- DEPENDENCIES | 3 +++ .../token-refresh-core/build.gradle.kts | 1 + .../core/DataPlaneTokenRefreshServiceExtension.java | 2 +- edc-extensions/iatp/tx-iatp-sts-dim/build.gradle.kts | 1 + .../edc/iam/iatp/sts/dim/DimSecureTokenServiceTest.java | 3 +-- .../tractusx/edc/iam/ssi/identity/SsiIdentityServiceTest.java | 2 -- edc-extensions/ssi/ssi-miw-credential-client/build.gradle.kts | 1 + .../tractusx/edc/iam/ssi/miw/api/MiwApiClientImplTest.java | 2 +- edc-tests/runtime/iatp/runtime-memory-sts/build.gradle.kts | 1 + .../tractusx/edc/lifecycle/SecureTokenServiceExtension.java | 2 +- gradle/libs.versions.toml | 1 + 11 files changed, 12 insertions(+), 7 deletions(-) diff --git a/DEPENDENCIES b/DEPENDENCIES index 16d215fe2..ff9015bb4 100644 --- a/DEPENDENCIES +++ b/DEPENDENCIES @@ -451,10 +451,13 @@ maven/mavencentral/org.eclipse.edc/jetty-core/0.5.2-SNAPSHOT, Apache-2.0, approv maven/mavencentral/org.eclipse.edc/jetty-micrometer/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/json-ld-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/json-ld/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/junit-base/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/junit/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/jws2020/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/jwt-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/jwt-verifiable-credentials/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/keys-lib/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/keys-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/ldp-verifiable-credentials/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/management-api-configuration/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/management-api-test-fixtures/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc diff --git a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/build.gradle.kts b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/build.gradle.kts index 98db1457e..cda2dda0d 100644 --- a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/build.gradle.kts +++ b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/build.gradle.kts @@ -25,6 +25,7 @@ dependencies { api(project(":spi:tokenrefresh-spi")) implementation(libs.edc.spi.core) implementation(libs.edc.spi.token) + implementation(libs.edc.spi.keys) implementation(libs.edc.spi.identity.did) implementation(libs.edc.spi.dataplane.dataplane) implementation(libs.edc.core.token) diff --git a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceExtension.java b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceExtension.java index 67f218bbb..abfbc4970 100644 --- a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceExtension.java +++ b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceExtension.java @@ -22,12 +22,12 @@ import org.eclipse.edc.connector.dataplane.spi.iam.DataPlaneAccessTokenService; import org.eclipse.edc.connector.dataplane.spi.store.AccessTokenDataStore; import org.eclipse.edc.iam.did.spi.resolution.DidPublicKeyResolver; +import org.eclipse.edc.keys.spi.PrivateKeyResolver; import org.eclipse.edc.runtime.metamodel.annotation.Extension; import org.eclipse.edc.runtime.metamodel.annotation.Inject; import org.eclipse.edc.runtime.metamodel.annotation.Provider; import org.eclipse.edc.runtime.metamodel.annotation.Setting; import org.eclipse.edc.spi.monitor.Monitor; -import org.eclipse.edc.spi.security.PrivateKeyResolver; import org.eclipse.edc.spi.security.Vault; import org.eclipse.edc.spi.system.Hostname; import org.eclipse.edc.spi.system.ServiceExtension; diff --git a/edc-extensions/iatp/tx-iatp-sts-dim/build.gradle.kts b/edc-extensions/iatp/tx-iatp-sts-dim/build.gradle.kts index 1286f6cf1..4c4b90b45 100644 --- a/edc-extensions/iatp/tx-iatp-sts-dim/build.gradle.kts +++ b/edc-extensions/iatp/tx-iatp-sts-dim/build.gradle.kts @@ -29,4 +29,5 @@ dependencies { implementation(project(":core:core-utils")) testImplementation(libs.edc.junit) + testImplementation(testFixtures(libs.edc.lib.http)) } diff --git a/edc-extensions/iatp/tx-iatp-sts-dim/src/test/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/DimSecureTokenServiceTest.java b/edc-extensions/iatp/tx-iatp-sts-dim/src/test/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/DimSecureTokenServiceTest.java index 00e3aa2f0..ef4a0a758 100644 --- a/edc-extensions/iatp/tx-iatp-sts-dim/src/test/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/DimSecureTokenServiceTest.java +++ b/edc-extensions/iatp/tx-iatp-sts-dim/src/test/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/DimSecureTokenServiceTest.java @@ -47,15 +47,14 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.eclipse.edc.identitytrust.SelfIssuedTokenConstants.PRESENTATION_TOKEN_CLAIM; import static org.eclipse.edc.junit.assertions.AbstractResultAssert.assertThat; -import static org.eclipse.edc.junit.testfixtures.TestUtils.testHttpClient; import static org.eclipse.edc.jwt.spi.JwtRegisteredClaimNames.AUDIENCE; import static org.eclipse.edc.jwt.spi.JwtRegisteredClaimNames.ISSUER; import static org.eclipse.edc.jwt.spi.JwtRegisteredClaimNames.SUBJECT; +import static org.eclipse.http.client.testfixtures.HttpTestUtils.testHttpClient; import static org.mockito.ArgumentMatchers.isA; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; - public class DimSecureTokenServiceTest { static final String DIM_URL = "http://localhost:8080/iatp"; diff --git a/edc-extensions/ssi/ssi-identity-core/src/test/java/org/eclipse/tractusx/edc/iam/ssi/identity/SsiIdentityServiceTest.java b/edc-extensions/ssi/ssi-identity-core/src/test/java/org/eclipse/tractusx/edc/iam/ssi/identity/SsiIdentityServiceTest.java index b6d7fc050..059c77283 100644 --- a/edc-extensions/ssi/ssi-identity-core/src/test/java/org/eclipse/tractusx/edc/iam/ssi/identity/SsiIdentityServiceTest.java +++ b/edc-extensions/ssi/ssi-identity-core/src/test/java/org/eclipse/tractusx/edc/iam/ssi/identity/SsiIdentityServiceTest.java @@ -20,7 +20,6 @@ package org.eclipse.tractusx.edc.iam.ssi.identity; import org.eclipse.edc.spi.iam.ClaimToken; -import org.eclipse.edc.spi.iam.PublicKeyResolver; import org.eclipse.edc.spi.iam.TokenParameters; import org.eclipse.edc.spi.iam.TokenRepresentation; import org.eclipse.edc.spi.result.Result; @@ -43,7 +42,6 @@ public class SsiIdentityServiceTest { SsiCredentialClient credentialClient = mock(SsiCredentialClient.class); SsiTokenValidationService tokenValidationService = mock(SsiTokenValidationService.class); TokenValidationRulesRegistry rulesRegistry = mock(TokenValidationRulesRegistry.class); - PublicKeyResolver publicKeyResolver = mock(PublicKeyResolver.class); SsiIdentityService identityService; diff --git a/edc-extensions/ssi/ssi-miw-credential-client/build.gradle.kts b/edc-extensions/ssi/ssi-miw-credential-client/build.gradle.kts index 87da94438..9f03fb974 100644 --- a/edc-extensions/ssi/ssi-miw-credential-client/build.gradle.kts +++ b/edc-extensions/ssi/ssi-miw-credential-client/build.gradle.kts @@ -36,4 +36,5 @@ dependencies { testImplementation(testFixtures(project(":spi:ssi-spi"))) testImplementation(testFixtures(libs.edc.junit)) + testImplementation(testFixtures(libs.edc.lib.http)) } diff --git a/edc-extensions/ssi/ssi-miw-credential-client/src/test/java/org/eclipse/tractusx/edc/iam/ssi/miw/api/MiwApiClientImplTest.java b/edc-extensions/ssi/ssi-miw-credential-client/src/test/java/org/eclipse/tractusx/edc/iam/ssi/miw/api/MiwApiClientImplTest.java index 83db6299b..71b747e56 100644 --- a/edc-extensions/ssi/ssi-miw-credential-client/src/test/java/org/eclipse/tractusx/edc/iam/ssi/miw/api/MiwApiClientImplTest.java +++ b/edc-extensions/ssi/ssi-miw-credential-client/src/test/java/org/eclipse/tractusx/edc/iam/ssi/miw/api/MiwApiClientImplTest.java @@ -47,7 +47,7 @@ import static java.lang.String.format; import static org.assertj.core.api.Assertions.assertThat; -import static org.eclipse.edc.junit.testfixtures.TestUtils.testHttpClient; +import static org.eclipse.http.client.testfixtures.HttpTestUtils.testHttpClient; import static org.eclipse.tractusx.edc.iam.ssi.miw.api.MiwApiClientImpl.CREDENTIAL_PATH; import static org.eclipse.tractusx.edc.iam.ssi.miw.api.MiwApiClientImpl.HOLDER_IDENTIFIER; import static org.eclipse.tractusx.edc.iam.ssi.miw.api.MiwApiClientImpl.PRESENTATIONS_PATH; diff --git a/edc-tests/runtime/iatp/runtime-memory-sts/build.gradle.kts b/edc-tests/runtime/iatp/runtime-memory-sts/build.gradle.kts index fa7db7bb0..6b7213087 100644 --- a/edc-tests/runtime/iatp/runtime-memory-sts/build.gradle.kts +++ b/edc-tests/runtime/iatp/runtime-memory-sts/build.gradle.kts @@ -37,6 +37,7 @@ dependencies { implementation(project(":edc-tests:runtime:extensions")) implementation(libs.edc.iam.mock) + implementation(libs.edc.spi.keys) // for the controller implementation(libs.jakarta.rsApi) implementation(libs.bundles.edc.sts) diff --git a/edc-tests/runtime/iatp/runtime-memory-sts/src/main/java/org/eclipse/tractusx/edc/lifecycle/SecureTokenServiceExtension.java b/edc-tests/runtime/iatp/runtime-memory-sts/src/main/java/org/eclipse/tractusx/edc/lifecycle/SecureTokenServiceExtension.java index 0cf88e4b0..b76dffaf8 100644 --- a/edc-tests/runtime/iatp/runtime-memory-sts/src/main/java/org/eclipse/tractusx/edc/lifecycle/SecureTokenServiceExtension.java +++ b/edc-tests/runtime/iatp/runtime-memory-sts/src/main/java/org/eclipse/tractusx/edc/lifecycle/SecureTokenServiceExtension.java @@ -21,10 +21,10 @@ import org.eclipse.edc.iam.identitytrust.sts.embedded.EmbeddedSecureTokenService; import org.eclipse.edc.identitytrust.SecureTokenService; +import org.eclipse.edc.keys.spi.PrivateKeyResolver; import org.eclipse.edc.runtime.metamodel.annotation.Inject; import org.eclipse.edc.runtime.metamodel.annotation.Provider; import org.eclipse.edc.spi.EdcException; -import org.eclipse.edc.spi.security.PrivateKeyResolver; import org.eclipse.edc.spi.system.ServiceExtension; import org.eclipse.edc.spi.system.ServiceExtensionContext; import org.eclipse.edc.token.JwtGenerationService; diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 1e6183829..e4042fc46 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -40,6 +40,7 @@ edc-spi-controlplane = { module = "org.eclipse.edc:control-plane-spi", version.r edc-controlplane-apiclient = { module = "org.eclipse.edc:control-plane-api-client", version.ref = "edc" } edc-spi-web = { module = "org.eclipse.edc:web-spi", version.ref = "edc" } edc-spi-http = { module = "org.eclipse.edc:http-spi", version.ref = "edc" } +edc-spi-keys = { module = "org.eclipse.edc:keys-spi", version.ref = "edc" } edc-spi-identitytrust = { module = "org.eclipse.edc:identity-trust-spi", version.ref = "edc" } edc-spi-jsonld = { module = "org.eclipse.edc:json-ld-spi", version.ref = "edc" } edc-spi-jwt = { module = "org.eclipse.edc:jwt-spi", version.ref = "edc" } From fc8dd45d6ea4e4c42f83aa4830274c02a0e36eb7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 25 Mar 2024 13:09:09 +0100 Subject: [PATCH 069/100] chore(deps): bump com.azure:azure-security-keyvault-secrets from 4.8.0 to 4.8.1 (#1158) * chore(deps): bump com.azure:azure-security-keyvault-secrets Bumps [com.azure:azure-security-keyvault-secrets](https://github.com/Azure/azure-sdk-for-java) from 4.8.0 to 4.8.1. - [Release notes](https://github.com/Azure/azure-sdk-for-java/releases) - [Commits](https://github.com/Azure/azure-sdk-for-java/compare/azure-cosmos_4.8.0...azure-security-keyvault-keys_4.8.1) --- updated-dependencies: - dependency-name: com.azure:azure-security-keyvault-secrets dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] * chore: dependencies file --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Enrico Risa --- DEPENDENCIES | 2 +- edc-dataplane/edc-dataplane-azure-vault/build.gradle.kts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/DEPENDENCIES b/DEPENDENCIES index ff9015bb4..35ce2678c 100644 --- a/DEPENDENCIES +++ b/DEPENDENCIES @@ -14,7 +14,7 @@ maven/mavencentral/com.azure/azure-identity/1.11.2, MIT AND Apache-2.0, approved maven/mavencentral/com.azure/azure-identity/1.11.4, MIT AND Apache-2.0, approved, #13237 maven/mavencentral/com.azure/azure-json/1.1.0, MIT AND Apache-2.0, approved, #10547 maven/mavencentral/com.azure/azure-security-keyvault-secrets/4.7.3, MIT, approved, #10868 -maven/mavencentral/com.azure/azure-security-keyvault-secrets/4.8.0, MIT, approved, #13690 +maven/mavencentral/com.azure/azure-security-keyvault-secrets/4.8.1, MIT, approved, #13690 maven/mavencentral/com.azure/azure-storage-blob/12.25.2, MIT, approved, #13400 maven/mavencentral/com.azure/azure-storage-common/12.24.2, MIT, approved, #13402 maven/mavencentral/com.azure/azure-storage-internal-avro/12.10.2, MIT, approved, #13399 diff --git a/edc-dataplane/edc-dataplane-azure-vault/build.gradle.kts b/edc-dataplane/edc-dataplane-azure-vault/build.gradle.kts index deef00f71..627939029 100644 --- a/edc-dataplane/edc-dataplane-azure-vault/build.gradle.kts +++ b/edc-dataplane/edc-dataplane-azure-vault/build.gradle.kts @@ -32,7 +32,7 @@ dependencies { } } implementation(libs.edc.azure.identity) - implementation("com.azure:azure-security-keyvault-secrets:4.8.0") + implementation("com.azure:azure-security-keyvault-secrets:4.8.1") runtimeOnly(libs.edc.transaction.local) runtimeOnly(libs.edc.sql.pool) runtimeOnly(libs.postgres) From ee9cf7c7512bb511253a34b8723954baee533436 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 25 Mar 2024 13:42:58 +0100 Subject: [PATCH 070/100] chore(deps): bump aws from 2.25.14 to 2.25.16 (#1157) * chore(deps): bump aws from 2.25.14 to 2.25.16 Bumps `aws` from 2.25.14 to 2.25.16. Updates `software.amazon.awssdk:s3` from 2.25.14 to 2.25.16 Updates `software.amazon.awssdk:s3-transfer-manager` from 2.25.14 to 2.25.16 --- updated-dependencies: - dependency-name: software.amazon.awssdk:s3 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:s3-transfer-manager dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] * chore: dependencies file --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Enrico Risa --- DEPENDENCIES | 54 +++++++++++++++++++-------------------- gradle/libs.versions.toml | 2 +- 2 files changed, 28 insertions(+), 28 deletions(-) diff --git a/DEPENDENCIES b/DEPENDENCIES index 35ce2678c..2f65c868e 100644 --- a/DEPENDENCIES +++ b/DEPENDENCIES @@ -624,58 +624,58 @@ maven/mavencentral/org.yaml/snakeyaml/1.33, Apache-2.0, approved, clearlydefined maven/mavencentral/org.yaml/snakeyaml/2.0, Apache-2.0 AND (Apache-2.0 OR BSD-3-Clause OR EPL-1.0 OR GPL-2.0-or-later OR LGPL-2.1-or-later), approved, #7275 maven/mavencentral/org.yaml/snakeyaml/2.2, Apache-2.0 AND (Apache-2.0 OR BSD-3-Clause OR EPL-1.0 OR GPL-2.0-or-later OR LGPL-2.1-or-later), approved, #10232 maven/mavencentral/software.amazon.awssdk/annotations/2.24.10, Apache-2.0, approved, #13251 -maven/mavencentral/software.amazon.awssdk/annotations/2.25.14, Apache-2.0, approved, #13691 +maven/mavencentral/software.amazon.awssdk/annotations/2.25.16, Apache-2.0, approved, #13691 maven/mavencentral/software.amazon.awssdk/apache-client/2.24.10, Apache-2.0, approved, #13257 -maven/mavencentral/software.amazon.awssdk/apache-client/2.25.14, Apache-2.0, approved, #13687 +maven/mavencentral/software.amazon.awssdk/apache-client/2.25.16, Apache-2.0, approved, #13687 maven/mavencentral/software.amazon.awssdk/arns/2.24.10, Apache-2.0, approved, #13243 -maven/mavencentral/software.amazon.awssdk/arns/2.25.14, Apache-2.0, approved, #13695 +maven/mavencentral/software.amazon.awssdk/arns/2.25.16, Apache-2.0, approved, #13695 maven/mavencentral/software.amazon.awssdk/auth/2.24.10, Apache-2.0, approved, #13256 -maven/mavencentral/software.amazon.awssdk/auth/2.25.14, Apache-2.0, approved, #13692 +maven/mavencentral/software.amazon.awssdk/auth/2.25.16, Apache-2.0, approved, #13692 maven/mavencentral/software.amazon.awssdk/aws-core/2.24.10, Apache-2.0, approved, #13240 -maven/mavencentral/software.amazon.awssdk/aws-core/2.25.14, Apache-2.0, approved, #13702 +maven/mavencentral/software.amazon.awssdk/aws-core/2.25.16, Apache-2.0, approved, #13702 maven/mavencentral/software.amazon.awssdk/aws-query-protocol/2.24.10, Apache-2.0, approved, #13262 -maven/mavencentral/software.amazon.awssdk/aws-query-protocol/2.25.14, Apache-2.0, approved, #13701 +maven/mavencentral/software.amazon.awssdk/aws-query-protocol/2.25.16, Apache-2.0, approved, #13701 maven/mavencentral/software.amazon.awssdk/aws-xml-protocol/2.24.10, Apache-2.0, approved, #13247 -maven/mavencentral/software.amazon.awssdk/aws-xml-protocol/2.25.14, Apache-2.0, approved, #13684 +maven/mavencentral/software.amazon.awssdk/aws-xml-protocol/2.25.16, Apache-2.0, approved, #13684 maven/mavencentral/software.amazon.awssdk/checksums-spi/2.24.10, Apache-2.0, approved, #13245 -maven/mavencentral/software.amazon.awssdk/checksums-spi/2.25.14, Apache-2.0, approved, #13686 +maven/mavencentral/software.amazon.awssdk/checksums-spi/2.25.16, Apache-2.0, approved, #13686 maven/mavencentral/software.amazon.awssdk/checksums/2.24.10, Apache-2.0, approved, #13242 -maven/mavencentral/software.amazon.awssdk/checksums/2.25.14, Apache-2.0, approved, #13677 +maven/mavencentral/software.amazon.awssdk/checksums/2.25.16, Apache-2.0, approved, #13677 maven/mavencentral/software.amazon.awssdk/crt-core/2.24.10, Apache-2.0, approved, #13252 -maven/mavencentral/software.amazon.awssdk/crt-core/2.25.14, Apache-2.0, approved, #13705 +maven/mavencentral/software.amazon.awssdk/crt-core/2.25.16, Apache-2.0, approved, #13705 maven/mavencentral/software.amazon.awssdk/endpoints-spi/2.24.10, Apache-2.0, approved, #13246 -maven/mavencentral/software.amazon.awssdk/endpoints-spi/2.25.14, Apache-2.0, approved, #13681 +maven/mavencentral/software.amazon.awssdk/endpoints-spi/2.25.16, Apache-2.0, approved, #13681 maven/mavencentral/software.amazon.awssdk/http-auth-aws/2.24.10, Apache-2.0, approved, #13253 -maven/mavencentral/software.amazon.awssdk/http-auth-aws/2.25.14, Apache-2.0, approved, #13696 +maven/mavencentral/software.amazon.awssdk/http-auth-aws/2.25.16, Apache-2.0, approved, #13696 maven/mavencentral/software.amazon.awssdk/http-auth-spi/2.24.10, Apache-2.0, approved, #13264 -maven/mavencentral/software.amazon.awssdk/http-auth-spi/2.25.14, Apache-2.0, approved, #13704 +maven/mavencentral/software.amazon.awssdk/http-auth-spi/2.25.16, Apache-2.0, approved, #13704 maven/mavencentral/software.amazon.awssdk/http-auth/2.24.10, Apache-2.0, approved, #13248 -maven/mavencentral/software.amazon.awssdk/http-auth/2.25.14, Apache-2.0, approved, #13682 +maven/mavencentral/software.amazon.awssdk/http-auth/2.25.16, Apache-2.0, approved, #13682 maven/mavencentral/software.amazon.awssdk/http-client-spi/2.24.10, Apache-2.0, approved, #13259 -maven/mavencentral/software.amazon.awssdk/http-client-spi/2.25.14, Apache-2.0, approved, #13706 +maven/mavencentral/software.amazon.awssdk/http-client-spi/2.25.16, Apache-2.0, approved, #13706 maven/mavencentral/software.amazon.awssdk/iam/2.24.10, Apache-2.0, approved, #13444 maven/mavencentral/software.amazon.awssdk/identity-spi/2.24.10, Apache-2.0, approved, #13244 -maven/mavencentral/software.amazon.awssdk/identity-spi/2.25.14, Apache-2.0, approved, #13685 +maven/mavencentral/software.amazon.awssdk/identity-spi/2.25.16, Apache-2.0, approved, #13685 maven/mavencentral/software.amazon.awssdk/json-utils/2.24.10, Apache-2.0, approved, #13261 -maven/mavencentral/software.amazon.awssdk/json-utils/2.25.14, Apache-2.0, approved, #13698 +maven/mavencentral/software.amazon.awssdk/json-utils/2.25.16, Apache-2.0, approved, #13698 maven/mavencentral/software.amazon.awssdk/metrics-spi/2.24.10, Apache-2.0, approved, #13239 -maven/mavencentral/software.amazon.awssdk/metrics-spi/2.25.14, Apache-2.0, approved, #13680 +maven/mavencentral/software.amazon.awssdk/metrics-spi/2.25.16, Apache-2.0, approved, #13680 maven/mavencentral/software.amazon.awssdk/netty-nio-client/2.24.10, Apache-2.0, approved, #13260 -maven/mavencentral/software.amazon.awssdk/netty-nio-client/2.25.14, Apache-2.0, approved, #13693 +maven/mavencentral/software.amazon.awssdk/netty-nio-client/2.25.16, Apache-2.0, approved, #13693 maven/mavencentral/software.amazon.awssdk/profiles/2.24.10, Apache-2.0, approved, #13258 -maven/mavencentral/software.amazon.awssdk/profiles/2.25.14, Apache-2.0, approved, #13697 +maven/mavencentral/software.amazon.awssdk/profiles/2.25.16, Apache-2.0, approved, #13697 maven/mavencentral/software.amazon.awssdk/protocol-core/2.24.10, Apache-2.0, approved, #13241 -maven/mavencentral/software.amazon.awssdk/protocol-core/2.25.14, Apache-2.0, approved, #13679 +maven/mavencentral/software.amazon.awssdk/protocol-core/2.25.16, Apache-2.0, approved, #13679 maven/mavencentral/software.amazon.awssdk/regions/2.24.10, Apache-2.0, approved, #13255 -maven/mavencentral/software.amazon.awssdk/regions/2.25.14, Apache-2.0, approved, #13694 -maven/mavencentral/software.amazon.awssdk/s3-transfer-manager/2.25.14, Apache-2.0, approved, #13699 +maven/mavencentral/software.amazon.awssdk/regions/2.25.16, Apache-2.0, approved, #13694 +maven/mavencentral/software.amazon.awssdk/s3-transfer-manager/2.25.16, Apache-2.0, approved, #13699 maven/mavencentral/software.amazon.awssdk/s3/2.24.10, Apache-2.0, approved, #13254 -maven/mavencentral/software.amazon.awssdk/s3/2.25.14, Apache-2.0, approved, #13688 +maven/mavencentral/software.amazon.awssdk/s3/2.25.16, Apache-2.0, approved, #13688 maven/mavencentral/software.amazon.awssdk/sdk-core/2.24.10, Apache-2.0, approved, #13265 -maven/mavencentral/software.amazon.awssdk/sdk-core/2.25.14, Apache-2.0, approved, #13700 +maven/mavencentral/software.amazon.awssdk/sdk-core/2.25.16, Apache-2.0, approved, #13700 maven/mavencentral/software.amazon.awssdk/sts/2.24.10, Apache-2.0, approved, #13442 maven/mavencentral/software.amazon.awssdk/third-party-jackson-core/2.24.10, Apache-2.0, approved, #13249 -maven/mavencentral/software.amazon.awssdk/third-party-jackson-core/2.25.14, Apache-2.0, approved, #13703 +maven/mavencentral/software.amazon.awssdk/third-party-jackson-core/2.25.16, Apache-2.0, approved, #13703 maven/mavencentral/software.amazon.awssdk/utils/2.24.10, Apache-2.0, approved, #13250 -maven/mavencentral/software.amazon.awssdk/utils/2.25.14, Apache-2.0, approved, #13689 +maven/mavencentral/software.amazon.awssdk/utils/2.25.16, Apache-2.0, approved, #13689 maven/mavencentral/software.amazon.eventstream/eventstream/1.0.1, Apache-2.0, approved, clearlydefined diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index e4042fc46..aeedaa4df 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -6,7 +6,7 @@ edc = "0.5.2-SNAPSHOT" apache-sshd = "2.12.1" assertj = "3.25.3" awaitility = "4.2.0" -aws = "2.25.14" +aws = "2.25.16" azure-identity = "1.11.4" bouncyCastle-jdk18on = "1.77" flyway = "10.10.0" From da5db30313faaceb0799a2a813fe621cad86d2ac Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 25 Mar 2024 14:02:53 +0100 Subject: [PATCH 071/100] chore(deps): bump github/codeql-action from 2 to 3 (#1156) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 2 to 3. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/v2...v3) --- updated-dependencies: - dependency-name: github/codeql-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/codeql.yaml b/.github/workflows/codeql.yaml index 57108b49d..00114c621 100644 --- a/.github/workflows/codeql.yaml +++ b/.github/workflows/codeql.yaml @@ -59,7 +59,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@v2 + uses: github/codeql-action/init@v3 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file From a67822ed6dc9396d3dfa2e5686f2634786558e10 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 25 Mar 2024 14:29:02 +0100 Subject: [PATCH 072/100] chore(deps): bump mikefarah/yq from 4.42.1 to 4.43.1 (#1155) Bumps [mikefarah/yq](https://github.com/mikefarah/yq) from 4.42.1 to 4.43.1. - [Release notes](https://github.com/mikefarah/yq/releases) - [Changelog](https://github.com/mikefarah/yq/blob/master/release_notes.txt) - [Commits](https://github.com/mikefarah/yq/compare/v4.42.1...v4.43.1) --- updated-dependencies: - dependency-name: mikefarah/yq dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/draft-new-release.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/draft-new-release.yaml b/.github/workflows/draft-new-release.yaml index 48033a9bd..3133badfa 100644 --- a/.github/workflows/draft-new-release.yaml +++ b/.github/workflows/draft-new-release.yaml @@ -54,7 +54,7 @@ jobs: GITHUB_PACKAGE_USERNAME: ${{ github.actor }} GITHUB_PACKAGE_PASSWORD: ${{ secrets.GITHUB_TOKEN }} - name: Bump version in /charts - uses: mikefarah/yq@v4.42.1 + uses: mikefarah/yq@v4.43.1 with: cmd: |- find charts -name Chart.yaml -maxdepth 3 | xargs -n1 yq -i '.appVersion = "${{ github.event.inputs.version }}" | .version = "${{ github.event.inputs.version }}"' From 5c8a549bb24cf527763f8e9c1c88017f32dce29e Mon Sep 17 00:00:00 2001 From: Paul Latzelsperger <43503240+paullatzelsperger@users.noreply.github.com> Date: Tue, 26 Mar 2024 07:30:39 +0100 Subject: [PATCH 073/100] feat: add Token Refresh e2e tests (#1160) * feat: add E2E tests for token renewal * parallelize tests --- .github/workflows/verify.yaml | 9 - .../token-refresh-core/build.gradle.kts | 1 + ...DataPlaneTokenRefreshServiceExtension.java | 13 +- .../DataPlaneTokenRefreshServiceImpl.java | 81 +++--- .../tokenrefresh/core/TokenFunctions.java | 41 +++ .../core/rules/AuthTokenAudienceRule.java | 13 +- .../rules/RefreshTokenValidationRule.java | 4 +- ...eTokenRefreshServiceImplComponentTest.java | 37 +-- .../DataPlaneTokenRefreshServiceImplTest.java | 63 ++-- .../tokenrefresh/core/TestFunctions.java | 32 ++- .../core/rules/AuthTokenAudienceRuleTest.java | 8 +- .../rules/RefreshTokenValidationRuleTest.java | 14 +- .../edc/api/edr/v2/EdrCacheApiController.java | 4 +- .../tokenrefresh/TokenRefreshHandlerImpl.java | 27 +- .../TokenRefreshHandlerImplTest.java | 43 +-- .../tests/edrv2/EdrCacheApiEndToEndTest.java | 10 +- .../edc/tests/ParticipantDataApi.java | 1 + .../transfer-tests/build.gradle.kts | 1 - ...AbstractHttpConsumerPullWithProxyTest.java | 44 +-- .../AbstractHttpProviderPushTest.java | 47 ++- .../TransferWithTokenRefreshTest.java | 271 ++++++++++++++++++ .../tractusx/edc/edr/spi/CoreConstants.java | 8 + 22 files changed, 575 insertions(+), 197 deletions(-) create mode 100644 edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/TokenFunctions.java create mode 100644 edc-tests/edc-controlplane/transfer-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/TransferWithTokenRefreshTest.java diff --git a/.github/workflows/verify.yaml b/.github/workflows/verify.yaml index 3eafae03c..a1df254d0 100644 --- a/.github/workflows/verify.yaml +++ b/.github/workflows/verify.yaml @@ -79,7 +79,6 @@ jobs: unit-tests: runs-on: ubuntu-latest - needs: [ verify-formatting, verify-license-headers ] steps: - uses: actions/checkout@v4 @@ -90,7 +89,6 @@ jobs: integration-tests: runs-on: ubuntu-latest - needs: [ verify-formatting, verify-license-headers ] steps: - uses: actions/checkout@v4 @@ -101,7 +99,6 @@ jobs: api-tests: runs-on: ubuntu-latest - needs: [ verify-formatting, verify-license-headers ] steps: - uses: actions/checkout@v4 @@ -112,7 +109,6 @@ jobs: end-to-end-tests: runs-on: ubuntu-latest - needs: [ verify-formatting, verify-license-headers ] strategy: fail-fast: false matrix: @@ -134,9 +130,6 @@ jobs: postgres-tests: runs-on: ubuntu-latest - - needs: [ verify-formatting, verify-license-headers ] - services: postgres: image: postgres:14.2 @@ -154,7 +147,6 @@ jobs: dataplane-tests: runs-on: ubuntu-latest - needs: [ verify-formatting, verify-license-headers ] steps: - uses: actions/checkout@v4 @@ -165,7 +157,6 @@ jobs: miw-integration-tests: runs-on: ubuntu-latest - needs: [ verify-formatting, verify-license-headers ] steps: - uses: actions/checkout@v4 - uses: ./.github/actions/setup-java diff --git a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/build.gradle.kts b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/build.gradle.kts index cda2dda0d..b51ab28dc 100644 --- a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/build.gradle.kts +++ b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/build.gradle.kts @@ -23,6 +23,7 @@ plugins { dependencies { api(project(":spi:tokenrefresh-spi")) + api(project(":spi:core-spi")) implementation(libs.edc.spi.core) implementation(libs.edc.spi.token) implementation(libs.edc.spi.keys) diff --git a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceExtension.java b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceExtension.java index abfbc4970..ab4de2587 100644 --- a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceExtension.java +++ b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceExtension.java @@ -48,17 +48,17 @@ public class DataPlaneTokenRefreshServiceExtension implements ServiceExtension { public static final String NAME = "DataPlane Token Refresh Service extension"; public static final int DEFAULT_TOKEN_EXPIRY_TOLERANCE_SECONDS = 5; + public static final long DEFAULT_TOKEN_EXPIRY_SECONDS = 300L; @Setting(value = "Token expiry tolerance period in seconds to allow for clock skew", defaultValue = "" + DEFAULT_TOKEN_EXPIRY_TOLERANCE_SECONDS) public static final String TOKEN_EXPIRY_TOLERANCE_SECONDS_PROPERTY = "edc.dataplane.token.expiry.tolerance"; - @Setting(value = "The HTTP endpoint where clients can request a renewal of their access token for the public dataplane API") public static final String REFRESH_ENDPOINT_PROPERTY = "edc.dataplane.token.refresh.endpoint"; @Setting(value = "Alias of private key used for signing tokens, retrieved from private key resolver") public static final String TOKEN_SIGNER_PRIVATE_KEY_ALIAS = "edc.transfer.proxy.token.signer.privatekey.alias"; - @Setting(value = "Alias of public key used for verifying the tokens, retrieved from the vault") public static final String TOKEN_VERIFIER_PUBLIC_KEY_ALIAS = "edc.transfer.proxy.token.verifier.publickey.alias"; - + @Setting(value = "Expiry time of access token in seconds", defaultValue = DEFAULT_TOKEN_EXPIRY_SECONDS + "") + public static final String TOKEN_EXPIRY_SECONDS_PROPERTY = "edc.dataplane.token.expiry"; @Inject private TokenValidationService tokenValidationService; @Inject @@ -105,15 +105,20 @@ private DataPlaneTokenRefreshServiceImpl getTokenRefreshService(ServiceExtension var monitor = context.getMonitor().withPrefix("DataPlane Token Refresh"); var expiryTolerance = getExpiryToleranceConfig(context); var refreshEndpoint = getRefreshEndpointConfig(context, monitor); + var tokenExpiry = getExpiryConfig(context); monitor.debug("Token refresh endpoint: %s".formatted(refreshEndpoint)); monitor.debug("Token refresh time tolerance: %d s".formatted(expiryTolerance)); tokenRefreshService = new DataPlaneTokenRefreshServiceImpl(clock, tokenValidationService, didPkResolver, accessTokenDataStore, new JwtGenerationService(), - getPrivateKeySupplier(context), context.getMonitor(), refreshEndpoint, expiryTolerance, + getPrivateKeySupplier(context), context.getMonitor(), refreshEndpoint, expiryTolerance, tokenExpiry, () -> context.getConfig().getString(TOKEN_VERIFIER_PUBLIC_KEY_ALIAS), vault, typeManager.getMapper()); } return tokenRefreshService; } + private Long getExpiryConfig(ServiceExtensionContext context) { + return context.getConfig().getLong(TOKEN_EXPIRY_SECONDS_PROPERTY, DEFAULT_TOKEN_EXPIRY_SECONDS); + } + private String getRefreshEndpointConfig(ServiceExtensionContext context, Monitor monitor) { var refreshEndpoint = context.getConfig().getString(REFRESH_ENDPOINT_PROPERTY, null); if (refreshEndpoint == null) { diff --git a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImpl.java b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImpl.java index 281e35f85..44f851cd6 100644 --- a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImpl.java +++ b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImpl.java @@ -21,6 +21,7 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; +import com.nimbusds.jwt.JWTClaimNames; import org.eclipse.edc.connector.dataplane.spi.AccessTokenData; import org.eclipse.edc.connector.dataplane.spi.iam.DataPlaneAccessTokenService; import org.eclipse.edc.connector.dataplane.spi.store.AccessTokenDataStore; @@ -41,7 +42,6 @@ import org.eclipse.edc.token.spi.TokenGenerationService; import org.eclipse.edc.token.spi.TokenValidationRule; import org.eclipse.edc.token.spi.TokenValidationService; -import org.eclipse.tractusx.edc.dataplane.tokenrefresh.core.rules.AuthTokenAudienceRule; import org.eclipse.tractusx.edc.dataplane.tokenrefresh.core.rules.ClaimIsPresentRule; import org.eclipse.tractusx.edc.dataplane.tokenrefresh.core.rules.IssuerEqualsSubjectRule; import org.eclipse.tractusx.edc.dataplane.tokenrefresh.core.rules.RefreshTokenValidationRule; @@ -62,17 +62,19 @@ import static org.eclipse.edc.jwt.spi.JwtRegisteredClaimNames.AUDIENCE; import static org.eclipse.edc.jwt.spi.JwtRegisteredClaimNames.EXPIRATION_TIME; +import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.EDR_PROPERTY_EXPIRES_IN; +import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.EDR_PROPERTY_REFRESH_ENDPOINT; +import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.EDR_PROPERTY_REFRESH_TOKEN; /** * This implementation of the {@link DataPlaneTokenRefreshService} validates an incoming authentication token. */ public class DataPlaneTokenRefreshServiceImpl implements DataPlaneTokenRefreshService, DataPlaneAccessTokenService { - public static final String ACCESS_TOKEN_CLAIM = "access_token"; + public static final String ACCESS_TOKEN_CLAIM = "token"; public static final String TOKEN_ID_CLAIM = "jti"; - public static final String REFRESH_TOKEN_PROPERTY = "refreshToken"; - private static final Long DEFAULT_EXPIRY_IN_SECONDS = 60 * 5L; + private final long tokenExpirySeconds; private final List authenticationTokenValidationRules; - private final List accessTokenRules; + private final List accessTokenAuthorizationRules; private final TokenValidationService tokenValidationService; private final DidPublicKeyResolver publicKeyResolver; private final AccessTokenDataStore accessTokenDataStore; @@ -94,6 +96,7 @@ public DataPlaneTokenRefreshServiceImpl(Clock clock, Monitor monitor, String refreshEndpoint, int tokenExpiryToleranceSeconds, + long tokenExpirySeconds, Supplier publicKeyIdSupplier, Vault vault, ObjectMapper objectMapper) { @@ -108,11 +111,13 @@ public DataPlaneTokenRefreshServiceImpl(Clock clock, this.publicKeyIdSupplier = publicKeyIdSupplier; this.vault = vault; this.objectMapper = objectMapper; + this.tokenExpirySeconds = tokenExpirySeconds; authenticationTokenValidationRules = List.of(new IssuerEqualsSubjectRule(), new ClaimIsPresentRule(AUDIENCE), // we don't check the contents, only it is present new ClaimIsPresentRule(ACCESS_TOKEN_CLAIM), - new ClaimIsPresentRule(TOKEN_ID_CLAIM)); - accessTokenRules = List.of(new IssuerEqualsSubjectRule(), + new ClaimIsPresentRule(TOKEN_ID_CLAIM) + /*new AuthTokenAudienceRule(accessTokenDataStore)*/); + accessTokenAuthorizationRules = List.of(new IssuerEqualsSubjectRule(), new ClaimIsPresentRule(AUDIENCE), new ClaimIsPresentRule(TOKEN_ID_CLAIM), new ExpirationIssuedAtValidationRule(clock, tokenExpiryToleranceSeconds)); @@ -137,15 +142,22 @@ public DataPlaneTokenRefreshServiceImpl(Clock clock, @Override public Result refreshToken(String refreshToken, String authenticationToken) { - var allRules = new ArrayList<>(authenticationTokenValidationRules); - allRules.add(new RefreshTokenValidationRule(vault, refreshToken, objectMapper)); - allRules.add(new AuthTokenAudienceRule(accessTokenDataStore)); - authenticationToken = authenticationToken.replace("Bearer", "").trim(); - var accessTokenDataResult = resolveToken(authenticationToken, allRules); + // 1. validate authentication token + monitor.warning(" TOKEN REFRESH :: TEMPORARILY DISABLED RULE AuthTokenAudienceRule UNTIL THE 'audience' PROPERTY IS FORWARDED TO DATAPLANES%n"); + var authTokenRes = tokenValidationService.validate(authenticationToken, publicKeyResolver, authenticationTokenValidationRules); + if (authTokenRes.failed()) { + return Result.failure("Authentication token validation failed: %s".formatted(authTokenRes.getFailureDetail())); + } + + // 2. extract access token and validate it + var accessToken = authTokenRes.getContent().getStringClaim("token"); + var accessTokenDataResult = tokenValidationService.validate(accessToken, publicKeyResolver, new RefreshTokenValidationRule(vault, refreshToken, objectMapper)) + .map(accessTokenClaims -> accessTokenDataStore.getById(accessTokenClaims.getStringClaim(JwtRegisteredClaimNames.JWT_ID))); + if (accessTokenDataResult.failed()) { - return accessTokenDataResult.mapTo(); + return Result.failure("Access token validation failed: %s".formatted(accessTokenDataResult.getFailureDetail())); } var existingAccessTokenData = accessTokenDataResult.getContent(); @@ -162,7 +174,7 @@ public Result refreshToken(String refreshToken, String authentica return Result.failure("Failed to regenerate access/refresh token pair: %s".formatted(errors)); } - storeRefreshToken(existingAccessTokenData.id(), new RefreshToken(newRefreshToken.getContent(), DEFAULT_EXPIRY_IN_SECONDS, refreshEndpoint)); + storeRefreshToken(existingAccessTokenData.id(), new RefreshToken(newRefreshToken.getContent(), tokenExpirySeconds, refreshEndpoint)); // the ClaimToken is created based solely on the TokenParameters. The additional information (refresh token...) is persisted separately var claimToken = ClaimToken.Builder.newInstance().claims(newTokenParams.getClaims()).build(); @@ -171,7 +183,7 @@ public Result refreshToken(String refreshToken, String authentica var storeResult = accessTokenDataStore.update(accessTokenData); return storeResult.succeeded() ? Result.success(new TokenResponse(newAccessToken.getContent(), - newRefreshToken.getContent(), DEFAULT_EXPIRY_IN_SECONDS, "bearer")) : + newRefreshToken.getContent(), tokenExpirySeconds, "bearer")) : Result.failure(storeResult.getFailureMessages()); } @@ -203,18 +215,18 @@ public Result obtainToken(TokenParameters tokenParameters, var storeResult = accessTokenDataStore.store(accessTokenData); storeRefreshToken(accessTokenResult.getContent().id(), new RefreshToken(refreshTokenResult.getContent().tokenRepresentation().getToken(), - DEFAULT_EXPIRY_IN_SECONDS, refreshEndpoint)); + tokenExpirySeconds, refreshEndpoint)); // the refresh token information must be returned in the EDR var edrAdditionalData = new HashMap<>(additionalTokenData); - edrAdditionalData.put("refreshToken", refreshTokenResult.getContent().tokenRepresentation().getToken()); - edrAdditionalData.put("expiresIn", String.valueOf(DEFAULT_EXPIRY_IN_SECONDS)); - edrAdditionalData.put("refreshEndpoint", refreshEndpoint); + edrAdditionalData.put(EDR_PROPERTY_REFRESH_TOKEN, refreshTokenResult.getContent().tokenRepresentation().getToken()); + edrAdditionalData.put(EDR_PROPERTY_EXPIRES_IN, String.valueOf(tokenExpirySeconds)); + edrAdditionalData.put(EDR_PROPERTY_REFRESH_ENDPOINT, refreshEndpoint); var edrTokenRepresentation = TokenRepresentation.Builder.newInstance() .token(accessTokenResult.getContent().tokenRepresentation().getToken()) // the access token .additional(edrAdditionalData) //contains additional properties and the refresh token - .expiresIn(DEFAULT_EXPIRY_IN_SECONDS) //todo: needed? + .expiresIn(tokenExpirySeconds) //todo: needed? .build(); @@ -223,7 +235,12 @@ public Result obtainToken(TokenParameters tokenParameters, @Override public Result resolve(String token) { - return resolveToken(token, accessTokenRules); + return tokenValidationService.validate(token, publicKeyResolver, accessTokenAuthorizationRules) + .compose(claimToken -> { + var id = claimToken.getStringClaim(JWTClaimNames.JWT_ID); + var tokenData = accessTokenDataStore.getById(id); + return tokenData != null ? Result.success(tokenData) : Result.failure("AccessTokenData with ID '%s' does not exist.".formatted(id)); + }); } @Override @@ -270,8 +287,8 @@ private Result createToken(TokenParameters tokenParam } //if there is not "exp" header on the token params, we'll configure one if (!tokenParameters.getClaims().containsKey(JwtRegisteredClaimNames.EXPIRATION_TIME)) { - monitor.info("No '%s' claim found on TokenParameters. Will use the default of %d seconds".formatted(EXPIRATION_TIME, DEFAULT_EXPIRY_IN_SECONDS)); - var exp = clock.instant().plusSeconds(DEFAULT_EXPIRY_IN_SECONDS).getEpochSecond(); + monitor.info("No '%s' claim found on TokenParameters. Will use the configured default of %d seconds".formatted(EXPIRATION_TIME, tokenExpirySeconds)); + var exp = clock.instant().plusSeconds(tokenExpirySeconds).getEpochSecond(); allDecorators.add(tp -> tp.claims(JwtRegisteredClaimNames.EXPIRATION_TIME, exp)); } @@ -279,24 +296,6 @@ private Result createToken(TokenParameters tokenParam .map(tr -> new TokenRepresentationWithId(tokenId.get(), tr)); } - /** - * Parses the given token, and validates it against the given rules. For that, the publicKeyResolver is used. - * Once the token is deemed valid, the "jti" claim (which is mandatory) is extracted and used as key for a lookup in the - * {@link AccessTokenDataStore}. The result of that is then returned. - */ - private Result resolveToken(String token, List rules) { - var validationResult = tokenValidationService.validate(token, publicKeyResolver, rules); - if (validationResult.failed()) { - return validationResult.mapTo(); - } - var tokenId = validationResult.getContent().getStringClaim(TOKEN_ID_CLAIM); - var existingAccessToken = accessTokenDataStore.getById(tokenId); - - return existingAccessToken == null ? - Result.failure("AccessTokenData with ID '%s' does not exist.".formatted(tokenId)) : - Result.success(existingAccessToken); - } - private Result storeRefreshToken(String id, RefreshToken refreshToken) { try { return vault.storeSecret(id, objectMapper.writeValueAsString(refreshToken)); diff --git a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/TokenFunctions.java b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/TokenFunctions.java new file mode 100644 index 000000000..30bd1f1be --- /dev/null +++ b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/TokenFunctions.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.eclipse.tractusx.edc.dataplane.tokenrefresh.core; + +import com.nimbusds.jwt.SignedJWT; +import org.eclipse.edc.jwt.spi.JwtRegisteredClaimNames; +import org.jetbrains.annotations.Nullable; + +import java.text.ParseException; + +public class TokenFunctions { + + /** + * Returns the "jti" claim of a JWT in serialized format. Will throw a {@link RuntimeException} if the token is not in valid + * serialized JWT format. + */ + public static @Nullable String getTokenId(String serializedJwt) { + try { + return SignedJWT.parse(serializedJwt).getJWTClaimsSet().getStringClaim(JwtRegisteredClaimNames.JWT_ID); + } catch (ParseException e) { + throw new RuntimeException(e); + } + } +} diff --git a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/rules/AuthTokenAudienceRule.java b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/rules/AuthTokenAudienceRule.java index 3fce42497..84acf8f7e 100644 --- a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/rules/AuthTokenAudienceRule.java +++ b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/rules/AuthTokenAudienceRule.java @@ -29,6 +29,9 @@ import java.util.Map; +import static org.eclipse.tractusx.edc.dataplane.tokenrefresh.core.TokenFunctions.getTokenId; + + /** * Validates that the {@code iss} claim of a token is equal to the {@code audience} property found on the {@link org.eclipse.edc.connector.dataplane.spi.AccessTokenData} * that is associated with that token (using the {@code jti} claim). @@ -42,9 +45,13 @@ public AuthTokenAudienceRule(AccessTokenDataStore store) { } @Override - public Result checkRule(@NotNull ClaimToken claimToken, @Nullable Map map) { - var issuer = claimToken.getStringClaim(JWTClaimNames.ISSUER); - var tokenId = claimToken.getStringClaim(JWTClaimNames.JWT_ID); + public Result checkRule(@NotNull ClaimToken authenticationToken, @Nullable Map map) { + var issuer = authenticationToken.getStringClaim(JWTClaimNames.ISSUER); + var accessToken = authenticationToken.getStringClaim("token"); + if (accessToken == null) { + return Result.failure("Authentication token must contain a 'token' claim"); + } + var tokenId = getTokenId(accessToken); var accessTokenData = store.getById(tokenId); var expectedAudience = accessTokenData.additionalProperties().getOrDefault(AUDIENCE_PROPERTY, null); diff --git a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/rules/RefreshTokenValidationRule.java b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/rules/RefreshTokenValidationRule.java index b6eb4a1bb..be7ad813b 100644 --- a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/rules/RefreshTokenValidationRule.java +++ b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/rules/RefreshTokenValidationRule.java @@ -51,9 +51,9 @@ public RefreshTokenValidationRule(Vault vault, String incomingRefreshToken, Obje } @Override - public Result checkRule(@NotNull ClaimToken toVerify, @Nullable Map additional) { - var tokenId = toVerify.getStringClaim(JWTClaimNames.JWT_ID); + public Result checkRule(@NotNull ClaimToken accessToken, @Nullable Map additional) { + var tokenId = accessToken.getStringClaim(JWTClaimNames.JWT_ID); var storedRefreshTokenJson = vault.resolveSecret(tokenId); if (storedRefreshTokenJson == null) { return failure("No refresh token with the ID '%s' was found in the vault.".formatted(tokenId)); diff --git a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImplComponentTest.java b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImplComponentTest.java index be0889076..55e4aaca1 100644 --- a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImplComponentTest.java +++ b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImplComponentTest.java @@ -53,6 +53,9 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.eclipse.edc.junit.assertions.AbstractResultAssert.assertThat; +import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.EDR_PROPERTY_EXPIRES_IN; +import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.EDR_PROPERTY_REFRESH_ENDPOINT; +import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.EDR_PROPERTY_REFRESH_TOKEN; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -89,6 +92,7 @@ void setup() throws JOSEException { mock(), TEST_REFRESH_ENDPOINT, 1, + 300L, () -> providerKey.getKeyID(), new InMemoryVault(mock()), new ObjectMapper()); @@ -112,9 +116,9 @@ void obtainToken() { // assert additional properties -> refresh token assertThat(edr.getContent().getAdditional()) - .containsEntry("refreshEndpoint", TEST_REFRESH_ENDPOINT) - .containsKey("refreshToken") - .containsKey("expiresIn"); + .containsEntry(EDR_PROPERTY_REFRESH_ENDPOINT, TEST_REFRESH_ENDPOINT) + .containsKey(EDR_PROPERTY_REFRESH_TOKEN) + .containsKey(EDR_PROPERTY_EXPIRES_IN); // verify that the correct data was stored var storedData = tokenDataStore.getById(tokenId); @@ -140,7 +144,7 @@ void refresh_success() throws JOSEException { var signedAuthToken = new SignedJWT(jwsHeader, claimsSet); signedAuthToken.sign(CryptoConverter.createSigner(consumerKey)); - var tokenResponse = tokenRefreshService.refreshToken(edr.getAdditional().get("refreshToken").toString(), signedAuthToken.serialize()); + var tokenResponse = tokenRefreshService.refreshToken(edr.getAdditional().get(EDR_PROPERTY_REFRESH_TOKEN).toString(), signedAuthToken.serialize()); assertThat(tokenResponse).withFailMessage(tokenResponse::getFailureDetail).isSucceeded() .satisfies(tr -> assertThat(tr.refreshToken()).isNotNull()) @@ -151,7 +155,7 @@ void refresh_success() throws JOSEException { .doesNotContainKey("refreshToken"); } - @DisplayName("Verify that a refresh token can only be refreshed by the original recipient") + @DisplayName("Verify that a stolen refresh token cannot be used to refresh an access token") @Test void refresh_originalTokenWasIssuedToDifferentPrincipal() throws JOSEException { var trudyKey = new ECKeyGenerator(Curve.P_256).keyID("did:web:trudy#trudy-key").generate(); @@ -169,9 +173,10 @@ void refresh_originalTokenWasIssuedToDifferentPrincipal() throws JOSEException { var signedAuthToken = new SignedJWT(jwsHeader, claimsSet); signedAuthToken.sign(CryptoConverter.createSigner(consumerKey)); - var tokenResponse = tokenRefreshService.refreshToken(edr.getAdditional().get("refreshToken").toString(), signedAuthToken.serialize()); + var tokenResponse = tokenRefreshService.refreshToken(edr.getAdditional().get(EDR_PROPERTY_REFRESH_TOKEN).toString(), signedAuthToken.serialize()); - assertThat(tokenResponse).isFailed().detail().isEqualTo("Principal 'did:web:bob' is not authorized to refresh this token."); + // todo: once the AuthTokenAudienceRule is re-enabled in the DataPlaneTokenRefreshServiceImpl the following assertion needs to be uncommented + // assertThat(tokenResponse).isFailed().detail().isEqualTo("Authentication token validation failed: Principal 'did:web:bob' is not authorized to refresh this token."); } @DisplayName("Verify that a spoofed refresh attempt is rejected ") @@ -191,12 +196,12 @@ void refresh_issuerNotVerifiable() throws JOSEException { var signedAuthToken = new SignedJWT(jwsHeader, claimsSet); signedAuthToken.sign(CryptoConverter.createSigner(consumerKey)); - var tokenResponse = tokenRefreshService.refreshToken(edr.getAdditional().get("refreshToken").toString(), signedAuthToken.serialize()); + var tokenResponse = tokenRefreshService.refreshToken(edr.getAdditional().get(EDR_PROPERTY_REFRESH_TOKEN).toString(), signedAuthToken.serialize()); - assertThat(tokenResponse).isFailed().detail().isEqualTo("Token verification failed"); + assertThat(tokenResponse).isFailed().detail().isEqualTo("Authentication token validation failed: Token verification failed"); } - @DisplayName("Verify that a refresh attempt fails if no \"access_token\" claim is present") + @DisplayName("Verify that a refresh attempt fails if no \"token\" claim is present") @Test void refresh_whenNoAccessTokenClaim() throws JOSEException { var tokenId = "test-token-id"; @@ -205,15 +210,15 @@ void refresh_whenNoAccessTokenClaim() throws JOSEException { var accessToken = edr.getToken(); var jwsHeader = new JWSHeader.Builder(JWSAlgorithm.ES384).keyID(consumerKey.getKeyID()).build(); - var claimsSet = getAuthTokenClaims(tokenId, accessToken).claim("access_token", null).build(); + var claimsSet = getAuthTokenClaims(tokenId, accessToken).claim("token", null).build(); var signedAuthToken = new SignedJWT(jwsHeader, claimsSet); signedAuthToken.sign(CryptoConverter.createSigner(consumerKey)); - var tokenResponse = tokenRefreshService.refreshToken(edr.getAdditional().get("refreshToken").toString(), signedAuthToken.serialize()); + var tokenResponse = tokenRefreshService.refreshToken(edr.getAdditional().get(EDR_PROPERTY_REFRESH_TOKEN).toString(), signedAuthToken.serialize()); assertThat(tokenResponse).isFailed() .detail() - .isEqualTo("Required claim 'access_token' not present on token."); + .contains(" Required claim 'token' not present on token."); } @DisplayName("Verify that the equality of the 'iss' and the 'sub' claim of the authentication token") @@ -232,11 +237,11 @@ void refresh_whenIssNotEqualToSub() throws JOSEException { var signedAuthToken = new SignedJWT(jwsHeader, claimsSet); signedAuthToken.sign(CryptoConverter.createSigner(consumerKey)); - var tokenResponse = tokenRefreshService.refreshToken(edr.getAdditional().get("refreshToken").toString(), signedAuthToken.serialize()); + var tokenResponse = tokenRefreshService.refreshToken(edr.getAdditional().get(EDR_PROPERTY_REFRESH_TOKEN).toString(), signedAuthToken.serialize()); assertThat(tokenResponse).isFailed() .detail() - .isEqualTo("The 'iss' and 'sub' claims must be non-null and identical."); + .isEqualTo("Authentication token validation failed: The 'iss' and 'sub' claims must be non-null and identical."); } @DisplayName("Verify that resolving an expired token fails") @@ -291,7 +296,7 @@ private JWTClaimsSet.Builder getAuthTokenClaims(String tokenId, String accessTok .issuer(CONSUMER_DID) .subject(CONSUMER_DID) .audience(PROVIDER_DID) - .claim("access_token", accessToken); + .claim("token", accessToken); } private TokenParameters tokenParams(String id) { diff --git a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImplTest.java b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImplTest.java index e619fa452..64c92f65b 100644 --- a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImplTest.java +++ b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImplTest.java @@ -31,6 +31,7 @@ import org.eclipse.edc.spi.types.domain.DataAddress; import org.eclipse.edc.token.spi.TokenDecorator; import org.eclipse.edc.token.spi.TokenGenerationService; +import org.eclipse.edc.token.spi.TokenValidationRule; import org.eclipse.edc.token.spi.TokenValidationService; import org.junit.jupiter.api.Test; @@ -41,6 +42,10 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.eclipse.edc.junit.assertions.AbstractResultAssert.assertThat; +import static org.eclipse.tractusx.edc.dataplane.tokenrefresh.core.TestFunctions.createJwt; +import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.EDR_PROPERTY_EXPIRES_IN; +import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.EDR_PROPERTY_REFRESH_ENDPOINT; +import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.EDR_PROPERTY_REFRESH_TOKEN; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyList; import static org.mockito.ArgumentMatchers.anyString; @@ -60,7 +65,8 @@ class DataPlaneTokenRefreshServiceImplTest { private final TokenValidationService tokenValidationService = mock(); private final DidPublicKeyResolver didPublicKeyResolver = mock(); - private final DataPlaneTokenRefreshServiceImpl accessTokenService = new DataPlaneTokenRefreshServiceImpl(Clock.systemUTC(), tokenValidationService, didPublicKeyResolver, accessTokenDataStore, tokenGenService, mock(), mock(), "https://example.com", 1, + private final DataPlaneTokenRefreshServiceImpl accessTokenService = new DataPlaneTokenRefreshServiceImpl(Clock.systemUTC(), tokenValidationService, didPublicKeyResolver, accessTokenDataStore, tokenGenService, mock(), mock(), + "https://example.com", 1, 300L, () -> "keyid", mock(), new ObjectMapper()); @@ -75,8 +81,8 @@ void obtainToken() { var result = accessTokenService.obtainToken(params, address, Map.of("fizz", "buzz", "refreshToken", "getsOverwritten")); assertThat(result).isSucceeded().extracting(TokenRepresentation::getToken).isEqualTo("foo-token"); assertThat(result.getContent().getAdditional()) - .containsKeys("fizz", "refreshToken", "expiresIn", "refreshEndpoint") - .containsEntry("refreshToken", "foo-token"); + .containsKeys("fizz", EDR_PROPERTY_REFRESH_TOKEN, EDR_PROPERTY_EXPIRES_IN, EDR_PROPERTY_REFRESH_ENDPOINT) + .containsEntry(EDR_PROPERTY_REFRESH_TOKEN, "foo-token"); verify(tokenGenService, times(2)).generate(any(), any(TokenDecorator[].class)); verify(accessTokenDataStore).store(any(AccessTokenData.class)); @@ -205,7 +211,7 @@ void refresh_whenAccessTokenDataNotResolved() { assertThat(accessTokenService.refreshToken(refreshToken, accessToken)) .isFailed() .detail() - .isEqualTo("test-failure"); + .isEqualTo("Authentication token validation failed: test-failure"); verify(tokenValidationService).validate(eq(accessToken), any(), anyList()); verifyNoMoreInteractions(tokenValidationService, tokenGenService, didPublicKeyResolver, accessTokenDataStore); @@ -213,10 +219,15 @@ void refresh_whenAccessTokenDataNotResolved() { @Test void refresh_whenRegeneratingTokenFails() { - var accessToken = "foo-bar"; - var refreshToken = "fizz-buzz"; + var accessToken = createJwt("quizz-quazz"); + var authenticationToken = createJwt("foo-bar"); + var refreshToken = createJwt("fizz-buzz"); + var tokenId = "token-id"; - when(tokenValidationService.validate(eq(accessToken), any(), anyList())) + when(tokenValidationService.validate(eq(authenticationToken), any(), anyList())) + .thenReturn(Result.success(ClaimToken.Builder.newInstance().claim("token", accessToken).build())); + + when(tokenValidationService.validate(eq(accessToken), any(), any(TokenValidationRule[].class))) .thenReturn(Result.success(ClaimToken.Builder.newInstance().claim("jti", tokenId).build())); when(accessTokenDataStore.getById(eq(tokenId))).thenReturn(new AccessTokenData(tokenId, ClaimToken.Builder.newInstance().claim("claim1", "value1").build(), @@ -225,12 +236,13 @@ void refresh_whenRegeneratingTokenFails() { when(tokenGenService.generate(any(), any(TokenDecorator[].class))).thenReturn(Result.failure("generator-failure")); - assertThat(accessTokenService.refreshToken(refreshToken, accessToken)) + assertThat(accessTokenService.refreshToken(refreshToken, authenticationToken)) .isFailed() .detail() .startsWith("Failed to regenerate access/refresh token pair: "); - verify(tokenValidationService).validate(eq(accessToken), any(), anyList()); + verify(tokenValidationService).validate(eq(accessToken), any(), any(TokenValidationRule[].class)); + verify(tokenValidationService).validate(eq(authenticationToken), any(), anyList()); verify(accessTokenDataStore).getById(tokenId); verify(tokenGenService, times(2)).generate(any(), any(TokenDecorator[].class)); verifyNoMoreInteractions(tokenValidationService, tokenGenService, didPublicKeyResolver, accessTokenDataStore); @@ -238,12 +250,18 @@ void refresh_whenRegeneratingTokenFails() { @Test void refresh_whenStoreFails() { - var accessToken = "foo-bar"; - var refreshToken = "fizz-buzz"; + var accessToken = createJwt("quizz-quazz"); + var authenticationToken = createJwt("foo-bar"); + var refreshToken = createJwt("fizz-buzz"); + var tokenId = "token-id"; - when(tokenValidationService.validate(eq(accessToken), any(), anyList())) + when(tokenValidationService.validate(eq(authenticationToken), any(), anyList())) + .thenReturn(Result.success(ClaimToken.Builder.newInstance().claim("token", accessToken).build())); + + when(tokenValidationService.validate(eq(accessToken), any(), any(TokenValidationRule[].class))) .thenReturn(Result.success(ClaimToken.Builder.newInstance().claim("jti", tokenId).build())); + when(accessTokenDataStore.getById(eq(tokenId))).thenReturn(new AccessTokenData(tokenId, ClaimToken.Builder.newInstance().claim("claim1", "value1").build(), DataAddress.Builder.newInstance().type("type").build(), Map.of("fizz", "buzz"))); @@ -251,12 +269,13 @@ void refresh_whenStoreFails() { when(accessTokenDataStore.update(any())).thenReturn(StoreResult.alreadyExists("test-failure")); - assertThat(accessTokenService.refreshToken(refreshToken, accessToken)) + assertThat(accessTokenService.refreshToken(refreshToken, authenticationToken)) .isFailed() .detail() .startsWith("test-failure"); - verify(tokenValidationService).validate(eq(accessToken), any(), anyList()); + verify(tokenValidationService).validate(eq(authenticationToken), any(), anyList()); + verify(tokenValidationService).validate(eq(accessToken), any(), any(TokenValidationRule[].class)); verify(accessTokenDataStore).getById(tokenId); verify(tokenGenService, times(2)).generate(any(), any(TokenDecorator[].class)); verify(accessTokenDataStore).update(any()); @@ -265,10 +284,15 @@ void refresh_whenStoreFails() { @Test void refresh_successful() { - var accessToken = "foo-bar"; - var refreshToken = "fizz-buzz"; + var accessToken = createJwt("quizz-quazz"); + var authenticationToken = createJwt("foo-bar"); + var refreshToken = createJwt("fizz-buzz"); + var tokenId = "token-id"; - when(tokenValidationService.validate(eq(accessToken), any(), anyList())) + when(tokenValidationService.validate(eq(authenticationToken), any(), anyList())) + .thenReturn(Result.success(ClaimToken.Builder.newInstance().claim("token", accessToken).build())); + + when(tokenValidationService.validate(eq(accessToken), any(), any(TokenValidationRule[].class))) .thenReturn(Result.success(ClaimToken.Builder.newInstance().claim("jti", tokenId).build())); when(accessTokenDataStore.getById(eq(tokenId))).thenReturn(new AccessTokenData(tokenId, ClaimToken.Builder.newInstance().claim("claim1", "value1").build(), @@ -280,14 +304,15 @@ void refresh_successful() { when(accessTokenDataStore.update(any())).thenReturn(StoreResult.success()); - assertThat(accessTokenService.refreshToken(refreshToken, accessToken)) + assertThat(accessTokenService.refreshToken(refreshToken, authenticationToken)) .isSucceeded() .satisfies(tr -> { assertThat(tr.accessToken()).isEqualTo("fizz-token"); assertThat(tr.refreshToken()).isEqualTo("buzz-token"); }); - verify(tokenValidationService).validate(eq(accessToken), any(), anyList()); + verify(tokenValidationService).validate(eq(authenticationToken), any(), anyList()); + verify(tokenValidationService).validate(eq(accessToken), any(), any(TokenValidationRule[].class)); verify(accessTokenDataStore).getById(tokenId); verify(tokenGenService, times(2)).generate(any(), any(TokenDecorator[].class)); verify(accessTokenDataStore).update(any()); diff --git a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/TestFunctions.java b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/TestFunctions.java index f67ab2ad7..c0e43d771 100644 --- a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/TestFunctions.java +++ b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/TestFunctions.java @@ -19,14 +19,42 @@ package org.eclipse.tractusx.edc.dataplane.tokenrefresh.core; +import com.nimbusds.jose.JOSEException; +import com.nimbusds.jose.JWSAlgorithm; +import com.nimbusds.jose.JWSHeader; +import com.nimbusds.jose.crypto.ECDSASigner; +import com.nimbusds.jose.jwk.Curve; +import com.nimbusds.jose.jwk.gen.ECKeyGenerator; +import com.nimbusds.jwt.JWTClaimsSet; +import com.nimbusds.jwt.SignedJWT; import org.eclipse.edc.spi.iam.ClaimToken; +import java.util.UUID; + public class TestFunctions { - public static ClaimToken createToken(String id) { + public static ClaimToken createAuthenticationToken(String id) { + return ClaimToken.Builder.newInstance() + .claim("token", createJwt(id)) + .claim("jti", UUID.randomUUID().toString()) + .claim("iss", "did:web:bob") + .build(); + } + + public static ClaimToken createAccessToken(String id) { return ClaimToken.Builder.newInstance() - .claim("access_token", "test-access-token") .claim("jti", id) .claim("iss", "did:web:bob") .build(); } + + public static String createJwt(String id) { + try { + var key = new ECKeyGenerator(Curve.P_256).generate(); + var jwt = new SignedJWT(new JWSHeader(JWSAlgorithm.ES256), new JWTClaimsSet.Builder().jwtID(id).build()); + jwt.sign(new ECDSASigner(key)); + return jwt.serialize(); + } catch (JOSEException e) { + throw new RuntimeException(e); + } + } } diff --git a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/rules/AuthTokenAudienceRuleTest.java b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/rules/AuthTokenAudienceRuleTest.java index 635e0ee71..da71521bd 100644 --- a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/rules/AuthTokenAudienceRuleTest.java +++ b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/rules/AuthTokenAudienceRuleTest.java @@ -28,7 +28,7 @@ import java.util.Map; import static org.eclipse.edc.junit.assertions.AbstractResultAssert.assertThat; -import static org.eclipse.tractusx.edc.dataplane.tokenrefresh.core.TestFunctions.createToken; +import static org.eclipse.tractusx.edc.dataplane.tokenrefresh.core.TestFunctions.createAuthenticationToken; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -46,7 +46,7 @@ void checkRule_issuerDoesNotMatchAudience() { DataAddress.Builder.newInstance().type("test-type").build(), Map.of("audience", "did:web:alice"))); - assertThat(rule.checkRule(createToken(TEST_TOKEN_ID), Map.of())) + assertThat(rule.checkRule(createAuthenticationToken(TEST_TOKEN_ID), Map.of())) .isFailed() .detail() .isEqualTo("Principal 'did:web:bob' is not authorized to refresh this token."); @@ -59,7 +59,7 @@ void checkRule_audienceNotString() { DataAddress.Builder.newInstance().type("test-type").build(), Map.of("audience", 42L))); - assertThat(rule.checkRule(createToken(TEST_TOKEN_ID), Map.of())) + assertThat(rule.checkRule(createAuthenticationToken(TEST_TOKEN_ID), Map.of())) .isFailed() .detail() .isEqualTo("Property 'audience' was expected to be java.lang.String but was class java.lang.Long."); @@ -72,7 +72,7 @@ void checkRule_audienceNotPresent() { DataAddress.Builder.newInstance().type("test-type").build(), Map.of())); - assertThat(rule.checkRule(createToken(TEST_TOKEN_ID), Map.of())) + assertThat(rule.checkRule(createAuthenticationToken(TEST_TOKEN_ID), Map.of())) .isFailed() .detail() .isEqualTo("Property 'audience' was expected to be java.lang.String but was null."); diff --git a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/rules/RefreshTokenValidationRuleTest.java b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/rules/RefreshTokenValidationRuleTest.java index 60022ac35..2de8f641e 100644 --- a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/rules/RefreshTokenValidationRuleTest.java +++ b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/rules/RefreshTokenValidationRuleTest.java @@ -26,7 +26,7 @@ import java.util.Map; import static org.eclipse.edc.junit.assertions.AbstractResultAssert.assertThat; -import static org.eclipse.tractusx.edc.dataplane.tokenrefresh.core.TestFunctions.createToken; +import static org.eclipse.tractusx.edc.dataplane.tokenrefresh.core.TestFunctions.createAccessToken; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -41,7 +41,7 @@ class RefreshTokenValidationRuleTest { void checkRule_noAccessTokenDataEntryFound() { when(vault.resolveSecret(TEST_TOKEN_ID)).thenReturn(null); - assertThat(rule.checkRule(createToken(TEST_TOKEN_ID), Map.of())) + assertThat(rule.checkRule(createAccessToken(TEST_TOKEN_ID), Map.of())) .isFailed() .detail() .isEqualTo("No refresh token with the ID '%s' was found in the vault.".formatted(TEST_TOKEN_ID)); @@ -51,7 +51,7 @@ void checkRule_noAccessTokenDataEntryFound() { void checkRule_noRefreshTokenStored() { when(vault.resolveSecret(TEST_TOKEN_ID)).thenReturn(null); - assertThat(rule.checkRule(createToken(TEST_TOKEN_ID), Map.of())) + assertThat(rule.checkRule(createAccessToken(TEST_TOKEN_ID), Map.of())) .isFailed() .detail() .isEqualTo("No refresh token with the ID 'test-jti' was found in the vault."); @@ -66,7 +66,7 @@ void checkRule_refreshTokenNotString() { } """); - assertThat(rule.checkRule(createToken(TEST_TOKEN_ID), Map.of())) + assertThat(rule.checkRule(createAccessToken(TEST_TOKEN_ID), Map.of())) .isFailed() .detail() .isEqualTo("Provided refresh token does not match the stored refresh token."); @@ -81,7 +81,7 @@ void checkRule_refreshTokenDoesNotMatch() { } """); - assertThat(rule.checkRule(createToken(TEST_TOKEN_ID), Map.of())) + assertThat(rule.checkRule(createAccessToken(TEST_TOKEN_ID), Map.of())) .isFailed() .detail() .isEqualTo("Provided refresh token does not match the stored refresh token."); @@ -96,7 +96,7 @@ void checkRule_success() { } """.formatted(TEST_REFRESH_TOKEN)); - assertThat(rule.checkRule(createToken(TEST_TOKEN_ID), Map.of())) + assertThat(rule.checkRule(createAccessToken(TEST_TOKEN_ID), Map.of())) .isSucceeded(); } @@ -105,7 +105,7 @@ void checkRule_invalidJson() { when(vault.resolveSecret(TEST_TOKEN_ID)).thenReturn( "nope-thats-not-json"); - assertThat(rule.checkRule(createToken(TEST_TOKEN_ID), Map.of())) + assertThat(rule.checkRule(createAccessToken(TEST_TOKEN_ID), Map.of())) .isFailed() .detail() .startsWith("Failed to parse stored secret"); diff --git a/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/EdrCacheApiController.java b/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/EdrCacheApiController.java index 68eaf8ca1..76c98c946 100644 --- a/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/EdrCacheApiController.java +++ b/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/EdrCacheApiController.java @@ -54,7 +54,7 @@ import static org.eclipse.edc.spi.query.QuerySpec.EDC_QUERY_SPEC_TYPE; import static org.eclipse.edc.spi.result.ServiceResult.success; import static org.eclipse.edc.web.spi.exception.ServiceResultHandler.exceptionMapper; -import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.TX_AUTH_NS; +import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.EDR_PROPERTY_EXPIRES_IN; @Consumes({ MediaType.APPLICATION_JSON }) @Produces({ MediaType.APPLICATION_JSON }) @@ -178,7 +178,7 @@ private ServiceResult refreshAndUpdateToken(DataAddress edr, String // todo: move this method into a service once the "old" EDR api,service,etc. is removed private boolean isExpired(DataAddress edr, org.eclipse.edc.edr.spi.types.EndpointDataReferenceEntry metadata) { - var expiresInString = edr.getStringProperty(TX_AUTH_NS + "expiresIn"); + var expiresInString = edr.getStringProperty(EDR_PROPERTY_EXPIRES_IN); if (expiresInString == null) { return false; } diff --git a/edc-extensions/tokenrefresh-handler/src/main/java/org/eclipse/tractusx/edc/common/tokenrefresh/TokenRefreshHandlerImpl.java b/edc-extensions/tokenrefresh-handler/src/main/java/org/eclipse/tractusx/edc/common/tokenrefresh/TokenRefreshHandlerImpl.java index 126f5377b..819574061 100644 --- a/edc-extensions/tokenrefresh-handler/src/main/java/org/eclipse/tractusx/edc/common/tokenrefresh/TokenRefreshHandlerImpl.java +++ b/edc-extensions/tokenrefresh-handler/src/main/java/org/eclipse/tractusx/edc/common/tokenrefresh/TokenRefreshHandlerImpl.java @@ -45,16 +45,14 @@ import static org.eclipse.edc.jwt.spi.JwtRegisteredClaimNames.ISSUER; import static org.eclipse.edc.jwt.spi.JwtRegisteredClaimNames.JWT_ID; import static org.eclipse.edc.jwt.spi.JwtRegisteredClaimNames.SUBJECT; -import static org.eclipse.edc.spi.CoreConstants.EDC_NAMESPACE; import static org.eclipse.edc.spi.result.Result.success; import static org.eclipse.edc.util.string.StringUtils.isNullOrBlank; -import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.TX_AUTH_NS; +import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.EDR_PROPERTY_AUTHORIZATION; +import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.EDR_PROPERTY_EXPIRES_IN; +import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.EDR_PROPERTY_REFRESH_ENDPOINT; +import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.EDR_PROPERTY_REFRESH_TOKEN; public class TokenRefreshHandlerImpl implements TokenRefreshHandler { - public static final String PROPERTY_AUTHORIZATION = EDC_NAMESPACE + "authorization"; - public static final String PROPERTY_REFRESH_TOKEN = TX_AUTH_NS + "refreshToken"; - public static final String PROPERTY_REFRESH_ENDPOINT = TX_AUTH_NS + "refreshEndpoint"; - public static final String PROPERTY_EXPIRES_IN = TX_AUTH_NS + "expiresIn"; private final EndpointDataReferenceCache edrCache; private final EdcHttpClient httpClient; private final String ownDid; @@ -97,9 +95,9 @@ public ServiceResult refreshToken(String tokenId) { @Override public ServiceResult refreshToken(String tokenId, DataAddress edr) { - var accessToken = edr.getStringProperty(PROPERTY_AUTHORIZATION); - var refreshToken = edr.getProperties().get(PROPERTY_REFRESH_TOKEN); - var refreshEndpoint = edr.getProperties().get(PROPERTY_REFRESH_ENDPOINT); + var accessToken = edr.getStringProperty(EDR_PROPERTY_AUTHORIZATION); + var refreshToken = edr.getProperties().get(EDR_PROPERTY_REFRESH_TOKEN); + var refreshEndpoint = edr.getProperties().get(EDR_PROPERTY_REFRESH_ENDPOINT); if (isNullOrBlank(accessToken)) { return ServiceResult.badRequest("Cannot perform token refresh: required property 'authorization' not found on EDR."); @@ -116,9 +114,10 @@ public ServiceResult refreshToken(String tokenId, DataAddress edr) JWT_ID, tokenId, ISSUER, ownDid, SUBJECT, ownDid, - AUDIENCE, audience + AUDIENCE, audience, + "token", accessToken )) - .compose(claims -> secureTokenService.createToken(claims, accessToken)) + .compose(claims -> secureTokenService.createToken(claims, null)) .compose(authToken -> createTokenRefreshRequest(refreshEndpoint.toString(), refreshToken.toString(), "Bearer %s".formatted(authToken.getToken()))); if (result.failed()) { @@ -134,9 +133,9 @@ private ServiceResult update(String id, DataAddress oldEdr, TokenRe var newEdr = DataAddress.Builder.newInstance() .type(oldEdr.getType()) .properties(oldEdr.getProperties()) - .property(PROPERTY_AUTHORIZATION, tokenResponse.accessToken()) - .property(PROPERTY_REFRESH_TOKEN, tokenResponse.refreshToken()) - .property(PROPERTY_EXPIRES_IN, String.valueOf(tokenResponse.expiresInSeconds())) + .property(EDR_PROPERTY_AUTHORIZATION, tokenResponse.accessToken()) + .property(EDR_PROPERTY_REFRESH_TOKEN, tokenResponse.refreshToken()) + .property(EDR_PROPERTY_EXPIRES_IN, String.valueOf(tokenResponse.expiresInSeconds())) .build(); return ServiceResult.from(edrCache.put(id, newEdr)).map(u -> newEdr); } diff --git a/edc-extensions/tokenrefresh-handler/src/test/java/org/eclipse/tractusx/edc/common/tokenrefresh/TokenRefreshHandlerImplTest.java b/edc-extensions/tokenrefresh-handler/src/test/java/org/eclipse/tractusx/edc/common/tokenrefresh/TokenRefreshHandlerImplTest.java index e8e340b8d..83fb5341a 100644 --- a/edc-extensions/tokenrefresh-handler/src/test/java/org/eclipse/tractusx/edc/common/tokenrefresh/TokenRefreshHandlerImplTest.java +++ b/edc-extensions/tokenrefresh-handler/src/test/java/org/eclipse/tractusx/edc/common/tokenrefresh/TokenRefreshHandlerImplTest.java @@ -56,20 +56,22 @@ import java.util.stream.Stream; import static org.eclipse.edc.junit.assertions.AbstractResultAssert.assertThat; -import static org.eclipse.tractusx.edc.common.tokenrefresh.TokenRefreshHandlerImpl.PROPERTY_AUTHORIZATION; -import static org.eclipse.tractusx.edc.common.tokenrefresh.TokenRefreshHandlerImpl.PROPERTY_EXPIRES_IN; -import static org.eclipse.tractusx.edc.common.tokenrefresh.TokenRefreshHandlerImpl.PROPERTY_REFRESH_ENDPOINT; -import static org.eclipse.tractusx.edc.common.tokenrefresh.TokenRefreshHandlerImpl.PROPERTY_REFRESH_TOKEN; +import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.EDR_PROPERTY_AUTHORIZATION; +import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.EDR_PROPERTY_EXPIRES_IN; +import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.EDR_PROPERTY_REFRESH_ENDPOINT; +import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.EDR_PROPERTY_REFRESH_TOKEN; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyMap; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.isNull; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoInteractions; import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; + class TokenRefreshHandlerImplTest { public static final String REFRESH_ENDPOINT = "http://fizz.buzz/quazz"; private static final String CONSUMER_DID = "did:web:bob"; @@ -102,17 +104,17 @@ void setup() { void refresh_validateCorrectRequest() throws IOException { when(edrCache.get(anyString())).thenReturn(StoreResult.success(createEdr().build())); when(edrCache.put(any(), any())).thenReturn(StoreResult.success()); - when(mockedTokenService.createToken(anyMap(), anyString())).thenReturn(Result.success(TokenRepresentation.Builder.newInstance().token("foo-auth-token").build())); + when(mockedTokenService.createToken(anyMap(), isNull())).thenReturn(Result.success(TokenRepresentation.Builder.newInstance().token("foo-auth-token").build())); var tokenResponse = new TokenResponse("new-access-token", "new-refresh-token", 60 * 5L, "bearer"); var successResponse = createResponse(tokenResponse, 200, ""); when(mockedHttpClient.execute(any())).thenReturn(successResponse); var res = tokenRefreshHandler.refreshToken("token-id"); assertThat(res).isSucceeded() .satisfies(tr -> { - Assertions.assertThat(tr.getProperties()).containsEntry(PROPERTY_AUTHORIZATION, "new-access-token"); - Assertions.assertThat(tr.getProperties()).containsEntry(PROPERTY_EXPIRES_IN, "300"); - Assertions.assertThat(tr.getProperties()).containsEntry(PROPERTY_REFRESH_TOKEN, "new-refresh-token"); - Assertions.assertThat(tr.getProperties()).containsEntry(PROPERTY_REFRESH_ENDPOINT, REFRESH_ENDPOINT); + Assertions.assertThat(tr.getProperties()).containsEntry(EDR_PROPERTY_AUTHORIZATION, "new-access-token"); + Assertions.assertThat(tr.getProperties()).containsEntry(EDR_PROPERTY_EXPIRES_IN, "300"); + Assertions.assertThat(tr.getProperties()).containsEntry(EDR_PROPERTY_REFRESH_TOKEN, "new-refresh-token"); + Assertions.assertThat(tr.getProperties()).containsEntry(EDR_PROPERTY_REFRESH_ENDPOINT, REFRESH_ENDPOINT); }); } @@ -132,9 +134,9 @@ void refresh_edrNotFound() { @ArgumentsSource(InvalidEdrProvider.class) void refresh_edrLacksRequiredProperties(String authorization, String refreshToken, String refreshEndpoint, String desc) { var invalidEdr = DataAddress.Builder.newInstance().type("test-type") - .property("authorization", authorization) - .property("refreshToken", refreshToken) - .property("refreshEndpoint", refreshEndpoint) + .property(EDR_PROPERTY_AUTHORIZATION, authorization) + .property(EDR_PROPERTY_REFRESH_TOKEN, refreshToken) + .property(EDR_PROPERTY_REFRESH_ENDPOINT, refreshEndpoint) .build(); when(edrCache.get(anyString())).thenReturn(StoreResult.success(invalidEdr)); @@ -146,7 +148,7 @@ void refresh_edrLacksRequiredProperties(String authorization, String refreshToke @Test void refresh_endpointReturnsFailure() throws IOException { when(edrCache.get(anyString())).thenReturn(StoreResult.success(createEdr().build())); - when(mockedTokenService.createToken(anyMap(), anyString())).thenReturn(Result.success(TokenRepresentation.Builder.newInstance().token("foo-auth-token").build())); + when(mockedTokenService.createToken(anyMap(), isNull())).thenReturn(Result.success(TokenRepresentation.Builder.newInstance().token("foo-auth-token").build())); var response401 = createResponse(null, 401, "Not authorized"); when(mockedHttpClient.execute(any())).thenReturn(response401); @@ -159,9 +161,10 @@ void refresh_endpointReturnsFailure() throws IOException { @Test void refresh_endpointReturnsEmptyBody() throws IOException { when(edrCache.get(anyString())).thenReturn(StoreResult.success(createEdr().build())); - when(mockedTokenService.createToken(anyMap(), anyString())).thenReturn(Result.success(TokenRepresentation.Builder.newInstance().token("foo-auth-token").build())); + when(mockedTokenService.createToken(anyMap(), isNull())).thenReturn(Result.success(TokenRepresentation.Builder.newInstance().token("foo-auth-token").build())); var successResponse = createResponse(null, 200, ""); when(mockedHttpClient.execute(any())).thenReturn(successResponse); + var res = tokenRefreshHandler.refreshToken("token-id"); assertThat(res).isFailed() .detail().isEqualTo("Token refresh successful, but body was empty."); @@ -170,7 +173,7 @@ void refresh_endpointReturnsEmptyBody() throws IOException { @Test void refresh_ioException() throws IOException { when(edrCache.get(anyString())).thenReturn(StoreResult.success(createEdr().build())); - when(mockedTokenService.createToken(anyMap(), anyString())).thenReturn(Result.success(TokenRepresentation.Builder.newInstance().token("foo-auth-token").build())); + when(mockedTokenService.createToken(anyMap(), isNull())).thenReturn(Result.success(TokenRepresentation.Builder.newInstance().token("foo-auth-token").build())); when(mockedHttpClient.execute(any())).thenThrow(new IOException("test exception")); assertThat(tokenRefreshHandler.refreshToken("token-id")).isFailed() @@ -179,7 +182,7 @@ void refresh_ioException() throws IOException { @Test void refresh_accessTokenIsNotJwt() { - when(edrCache.get(anyString())).thenReturn(StoreResult.success(createEdr().property(PROPERTY_AUTHORIZATION, "not-jwt").build())); + when(edrCache.get(anyString())).thenReturn(StoreResult.success(createEdr().property(EDR_PROPERTY_AUTHORIZATION, "not-jwt").build())); assertThat(tokenRefreshHandler.refreshToken("token-id")).isFailed() .detail().startsWith("Could not execute token refresh: Failed to parse string claim 'iss'"); } @@ -187,7 +190,7 @@ void refresh_accessTokenIsNotJwt() { @Test void refresh_tokenGenerationFailed() { when(edrCache.get(anyString())).thenReturn(StoreResult.success(createEdr().build())); - when(mockedTokenService.createToken(anyMap(), anyString())).thenReturn(Result.failure("foobar")); + when(mockedTokenService.createToken(anyMap(), isNull())).thenReturn(Result.failure("foobar")); assertThat(tokenRefreshHandler.refreshToken("token-id")).isFailed() .detail().isEqualTo("Could not execute token refresh: foobar"); } @@ -207,9 +210,9 @@ private Response createResponse(Object responseBodyObject, int statusCode, Strin private DataAddress.Builder createEdr() { return DataAddress.Builder.newInstance() .type("HttpData") - .property(PROPERTY_AUTHORIZATION, createJwt()) - .property(PROPERTY_REFRESH_TOKEN, "foo-refresh-token") - .property(PROPERTY_REFRESH_ENDPOINT, REFRESH_ENDPOINT); + .property(EDR_PROPERTY_AUTHORIZATION, createJwt()) + .property(EDR_PROPERTY_REFRESH_TOKEN, "foo-refresh-token") + .property(EDR_PROPERTY_REFRESH_ENDPOINT, REFRESH_ENDPOINT); } private static class InvalidEdrProvider implements ArgumentsProvider { diff --git a/edc-tests/edc-controlplane/edr-api-tests/src/test/java/org/eclipse/tractusx/edc/tests/edrv2/EdrCacheApiEndToEndTest.java b/edc-tests/edc-controlplane/edr-api-tests/src/test/java/org/eclipse/tractusx/edc/tests/edrv2/EdrCacheApiEndToEndTest.java index 27729eb6d..74486302e 100644 --- a/edc-tests/edc-controlplane/edr-api-tests/src/test/java/org/eclipse/tractusx/edc/tests/edrv2/EdrCacheApiEndToEndTest.java +++ b/edc-tests/edc-controlplane/edr-api-tests/src/test/java/org/eclipse/tractusx/edc/tests/edrv2/EdrCacheApiEndToEndTest.java @@ -57,7 +57,9 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.eclipse.edc.spi.CoreConstants.EDC_NAMESPACE; import static org.eclipse.edc.util.io.Ports.getFreePort; -import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.TX_AUTH_NS; +import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.EDR_PROPERTY_EXPIRES_IN; +import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.EDR_PROPERTY_REFRESH_ENDPOINT; +import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.EDR_PROPERTY_REFRESH_TOKEN; import static org.mockserver.integration.ClientAndServer.startClientAndServer; import static org.mockserver.matchers.Times.exactly; import static org.mockserver.model.HttpRequest.request; @@ -300,9 +302,9 @@ private void storeEdr(String transferProcessId, boolean isExpired) { .type("test-type") .property(EDC_NAMESPACE + "authorization", createJwt(providerSigningKey, claims)) .property(EDC_NAMESPACE + "authType", "bearer") - .property(TX_AUTH_NS + "refreshToken", createJwt(providerSigningKey, new JWTClaimsSet.Builder().build())) - .property(TX_AUTH_NS + "expiresIn", "300") - .property(TX_AUTH_NS + "refreshEndpoint", refreshEndpoint) + .property(EDR_PROPERTY_REFRESH_TOKEN, createJwt(providerSigningKey, new JWTClaimsSet.Builder().build())) + .property(EDR_PROPERTY_EXPIRES_IN, "300") + .property(EDR_PROPERTY_REFRESH_ENDPOINT, refreshEndpoint) .build(); var entry = EndpointDataReferenceEntry.Builder.newInstance() .clock(isExpired ? // defaults to an expired token diff --git a/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/ParticipantDataApi.java b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/ParticipantDataApi.java index 1d3e4935e..a7efd4de6 100644 --- a/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/ParticipantDataApi.java +++ b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/ParticipantDataApi.java @@ -53,4 +53,5 @@ public String pullData(JsonObject edr, Map queryParams) { assertThat(response.statusCode()).isBetween(200, 300); return response.body().asString(); } + } diff --git a/edc-tests/edc-controlplane/transfer-tests/build.gradle.kts b/edc-tests/edc-controlplane/transfer-tests/build.gradle.kts index d0de250c2..42771ae1d 100644 --- a/edc-tests/edc-controlplane/transfer-tests/build.gradle.kts +++ b/edc-tests/edc-controlplane/transfer-tests/build.gradle.kts @@ -29,7 +29,6 @@ dependencies { testImplementation(libs.edc.junit) testImplementation(libs.restAssured) testImplementation(libs.awaitility) - testImplementation(libs.okhttp.mockwebserver) } // do not publish diff --git a/edc-tests/edc-controlplane/transfer-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/AbstractHttpConsumerPullWithProxyTest.java b/edc-tests/edc-controlplane/transfer-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/AbstractHttpConsumerPullWithProxyTest.java index 73b2063ff..8e41f23df 100644 --- a/edc-tests/edc-controlplane/transfer-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/AbstractHttpConsumerPullWithProxyTest.java +++ b/edc-tests/edc-controlplane/transfer-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/AbstractHttpConsumerPullWithProxyTest.java @@ -21,21 +21,21 @@ import jakarta.json.Json; import jakarta.json.JsonObject; -import okhttp3.mockwebserver.MockResponse; -import okhttp3.mockwebserver.MockWebServer; import org.eclipse.edc.connector.transfer.spi.types.TransferProcessStates; import org.eclipse.tractusx.edc.tests.TxParticipant; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.mockserver.integration.ClientAndServer; +import org.mockserver.verify.VerificationTimes; -import java.io.IOException; import java.util.Map; import java.util.concurrent.atomic.AtomicReference; import static org.assertj.core.api.Assertions.assertThat; import static org.awaitility.Awaitility.await; import static org.awaitility.pollinterval.FibonacciPollInterval.fibonacci; +import static org.eclipse.edc.util.io.Ports.getFreePort; import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.PLATO_BPN; import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.PLATO_NAME; import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.SOKRATES_BPN; @@ -43,35 +43,37 @@ import static org.eclipse.tractusx.edc.tests.TxParticipant.ASYNC_TIMEOUT; import static org.eclipse.tractusx.edc.tests.helpers.PolicyHelperFunctions.bnpPolicy; import static org.eclipse.tractusx.edc.tests.transfer.TransferProcessHelperFunctions.createProxyRequest; +import static org.mockserver.model.HttpRequest.request; +import static org.mockserver.model.HttpResponse.response; public abstract class AbstractHttpConsumerPullWithProxyTest { + public static final String MOCK_BACKEND_REMOTEHOST = "localhost"; + public static final String MOCK_BACKEND_PATH = "/mock/api"; protected static final TxParticipant SOKRATES = TxParticipant.Builder.newInstance() .name(SOKRATES_NAME) .id(SOKRATES_BPN) .build(); - protected static final TxParticipant PLATO = TxParticipant.Builder.newInstance() .name(PLATO_NAME) .id(PLATO_BPN) .build(); - - protected MockWebServer server; + protected ClientAndServer server; + private String privateBackendUrl; @BeforeEach - void setup() throws IOException { - server = new MockWebServer(); + void setup() { + server = ClientAndServer.startClientAndServer(MOCK_BACKEND_REMOTEHOST, getFreePort()); + privateBackendUrl = "http://%s:%d%s".formatted(MOCK_BACKEND_REMOTEHOST, server.getPort(), MOCK_BACKEND_PATH); } @Test - void transferData_privateBackend() throws IOException, InterruptedException { + void transferData_privateBackend() { var assetId = "api-asset-1"; - var url = server.url("/mock/api"); - server.start(); Map dataAddress = Map.of( - "baseUrl", url.toString(), + "baseUrl", privateBackendUrl, "type", "HttpData", "contentType", "application/json" ); @@ -83,7 +85,6 @@ void transferData_privateBackend() throws IOException, InterruptedException { PLATO.createContractDefinition(assetId, "def-1", accessPolicyId, contractPolicyId); var transferProcessId = SOKRATES.requestAsset(PLATO, assetId, Json.createObjectBuilder().build(), createProxyRequest()); - var contractAgreementId = new AtomicReference(); var edr = new AtomicReference(); // wait until transfer process completes @@ -95,7 +96,7 @@ void transferData_privateBackend() throws IOException, InterruptedException { }); // wait until EDC is available on the consumer side - server.enqueue(new MockResponse().setBody("test response").setResponseCode(200)); + server.when(request().withMethod("GET").withPath(MOCK_BACKEND_PATH)).respond(response().withStatusCode(200).withBody("test response")); await().pollInterval(fibonacci()) .atMost(ASYNC_TIMEOUT) .untilAsserted(() -> { @@ -106,15 +107,18 @@ void transferData_privateBackend() throws IOException, InterruptedException { // pull data out of provider's backend service: // Prov-DP -> Prov-backend assertThat(SOKRATES.data().pullData(edr.get(), Map.of())).isEqualTo("test response"); - var rq = server.takeRequest(); - assertThat(rq.getHeader("Edc-Contract-Agreement-Id")).isNotNull(); - assertThat(rq.getHeader("Edc-Bpn")).isEqualTo(SOKRATES.getBpn()); - assertThat(rq.getMethod()).isEqualToIgnoringCase("GET"); + + server.verify(request() + .withPath(MOCK_BACKEND_PATH) + .withHeader("Edc-Contract-Agreement-Id") + .withHeader("Edc-Bpn", SOKRATES_BPN) + .withMethod("GET"), VerificationTimes.exactly(1)); + } @AfterEach - void teardown() throws IOException { - server.shutdown(); + void teardown() { + server.stop(); } protected JsonObject createAccessPolicy(String bpn) { diff --git a/edc-tests/edc-controlplane/transfer-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/AbstractHttpProviderPushTest.java b/edc-tests/edc-controlplane/transfer-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/AbstractHttpProviderPushTest.java index 3be0fbbf0..bb6e51c46 100644 --- a/edc-tests/edc-controlplane/transfer-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/AbstractHttpProviderPushTest.java +++ b/edc-tests/edc-controlplane/transfer-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/AbstractHttpProviderPushTest.java @@ -20,17 +20,13 @@ package org.eclipse.tractusx.edc.tests.transfer; import jakarta.json.JsonObject; -import okhttp3.mockwebserver.Dispatcher; -import okhttp3.mockwebserver.MockResponse; -import okhttp3.mockwebserver.MockWebServer; -import okhttp3.mockwebserver.RecordedRequest; import org.eclipse.tractusx.edc.tests.TxParticipant; -import org.jetbrains.annotations.NotNull; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.mockserver.integration.ClientAndServer; +import org.mockserver.model.HttpResponse; -import java.io.IOException; import java.util.Map; import java.util.UUID; @@ -40,15 +36,17 @@ import static org.eclipse.edc.connector.transfer.spi.types.TransferProcessStates.COMPLETED; import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.TYPE; import static org.eclipse.edc.spi.CoreConstants.EDC_NAMESPACE; +import static org.eclipse.edc.util.io.Ports.getFreePort; import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.PLATO_BPN; import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.PLATO_NAME; import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.SOKRATES_BPN; import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.SOKRATES_NAME; import static org.eclipse.tractusx.edc.tests.TxParticipant.ASYNC_TIMEOUT; import static org.eclipse.tractusx.edc.tests.helpers.PolicyHelperFunctions.bnpPolicy; +import static org.mockserver.model.HttpRequest.request; public abstract class AbstractHttpProviderPushTest { - + public static final String MOCK_BACKEND_REMOTEHOST = "localhost"; protected static final TxParticipant SOKRATES = TxParticipant.Builder.newInstance() .name(SOKRATES_NAME) .id(SOKRATES_BPN) @@ -59,37 +57,28 @@ public abstract class AbstractHttpProviderPushTest { .id(PLATO_BPN) .build(); - private MockWebServer server; + private ClientAndServer server; @BeforeEach void setup() { - server = new MockWebServer(); + server = ClientAndServer.startClientAndServer(MOCK_BACKEND_REMOTEHOST, getFreePort()); } @Test - void httpPushDataTransfer() throws IOException { + void httpPushDataTransfer() { var assetId = UUID.randomUUID().toString(); - var providerUrl = server.url("/mock/api/provider"); - var consumerUrl = server.url("/mock/api/consumer"); - - server.setDispatcher(new Dispatcher() { - @NotNull - @Override - public MockResponse dispatch(@NotNull RecordedRequest recordedRequest) throws InterruptedException { - return switch (recordedRequest.getPath().split("\\?")[0]) { - case "/mock/api/provider" -> new MockResponse().setResponseCode(200); - case "/mock/api/consumer" -> new MockResponse().setResponseCode(200); - default -> new MockResponse().setResponseCode(404); - }; - } - }); + var providerUrl = "http://%s:%d%s".formatted(MOCK_BACKEND_REMOTEHOST, server.getPort(), "/mock/api/provider"); + var consumerUrl = "http://%s:%d%s".formatted(MOCK_BACKEND_REMOTEHOST, server.getPort(), "/mock/api/consumer"); - server.start(); + server.when(request().withPath("/mock/api/provider")) + .respond(HttpResponse.response().withStatusCode(200)); + server.when(request().withPath("/mock/api/consumer")) + .respond(HttpResponse.response().withStatusCode(200)); Map dataAddress = Map.of( "name", "transfer-test", - "baseUrl", providerUrl.toString(), + "baseUrl", providerUrl, "type", "HttpData", "contentType", "application/json" ); @@ -98,7 +87,7 @@ public MockResponse dispatch(@NotNull RecordedRequest recordedRequest) throws In var policyId = PLATO.createPolicyDefinition(bnpPolicy(SOKRATES.getBpn())); PLATO.createContractDefinition(assetId, "def-1", policyId, policyId); - var destination = httpDataAddress(consumerUrl.toString()); + var destination = httpDataAddress(consumerUrl); var transferProcessId = SOKRATES.requestAsset(PLATO, assetId, createObjectBuilder().build(), destination, "HttpData-PUSH"); await().atMost(ASYNC_TIMEOUT).untilAsserted(() -> { @@ -108,8 +97,8 @@ public MockResponse dispatch(@NotNull RecordedRequest recordedRequest) throws In } @AfterEach - void teardown() throws IOException { - server.shutdown(); + void teardown() { + server.stop(); } private JsonObject httpDataAddress(String baseUrl) { diff --git a/edc-tests/edc-controlplane/transfer-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/TransferWithTokenRefreshTest.java b/edc-tests/edc-controlplane/transfer-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/TransferWithTokenRefreshTest.java new file mode 100644 index 000000000..2134525c5 --- /dev/null +++ b/edc-tests/edc-controlplane/transfer-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/TransferWithTokenRefreshTest.java @@ -0,0 +1,271 @@ +/******************************************************************************** + * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +package org.eclipse.tractusx.edc.tests.transfer; + +import com.nimbusds.jose.util.Base64; +import jakarta.json.Json; +import jakarta.json.JsonObject; +import org.eclipse.edc.connector.transfer.spi.types.TransferProcessStates; +import org.eclipse.edc.junit.annotations.EndToEndTest; +import org.eclipse.edc.spi.security.Vault; +import org.eclipse.tractusx.edc.tests.TxParticipant; +import org.eclipse.tractusx.edc.tests.runtimes.ParticipantRuntime; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; +import org.mockserver.integration.ClientAndServer; +import org.mockserver.verify.VerificationTimes; + +import java.security.SecureRandom; +import java.time.Duration; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.atomic.AtomicReference; + +import static io.restassured.RestAssured.given; +import static org.assertj.core.api.Assertions.assertThat; +import static org.awaitility.Awaitility.await; +import static org.awaitility.pollinterval.FibonacciPollInterval.fibonacci; +import static org.eclipse.edc.util.io.Ports.getFreePort; +import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.PLATO_BPN; +import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.PLATO_NAME; +import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.SOKRATES_BPN; +import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.SOKRATES_NAME; +import static org.eclipse.tractusx.edc.tests.TxParticipant.ASYNC_TIMEOUT; +import static org.eclipse.tractusx.edc.tests.helpers.PolicyHelperFunctions.bnpPolicy; +import static org.eclipse.tractusx.edc.tests.transfer.TransferProcessHelperFunctions.createProxyRequest; +import static org.mockserver.model.HttpRequest.request; +import static org.mockserver.model.HttpResponse.response; + +/** + * this test uses in-mem runtimes to negotiate and perform a data transfer, but the EDR expires before the consumer has a + * chance to obtain the data. + * The test asserts that the automatic token refresh mechanism renews the token, and the transfer can be completed afterward. + */ +@EndToEndTest +public class TransferWithTokenRefreshTest { + + public static final String MOCK_BACKEND_REMOTEHOST = "localhost"; + public static final String MOCK_BACKEND_PATH = "/mock/api"; + protected static final TxParticipant SOKRATES = TxParticipant.Builder.newInstance() + .name(SOKRATES_NAME) + .id(SOKRATES_BPN) + .build(); + protected static final TxParticipant PLATO = TxParticipant.Builder.newInstance() + .name(PLATO_NAME) + .id(PLATO_BPN) + .build(); + @RegisterExtension + protected static final ParticipantRuntime SOKRATES_RUNTIME = new ParticipantRuntime( + ":edc-tests:runtime:runtime-memory", + SOKRATES.getName(), + SOKRATES.getBpn(), + SOKRATES.getConfiguration() + ); + private static final Long VERY_SHORT_TOKEN_EXPIRY = 3L; + @RegisterExtension + protected static final ParticipantRuntime PLATO_RUNTIME = new ParticipantRuntime( + ":edc-tests:runtime:runtime-memory", + PLATO.getName(), + PLATO.getBpn(), + forConfig(PLATO.getConfiguration()) + ); + protected ClientAndServer server; + private String privateBackendUrl; + + @BeforeAll + static void prepare() { + var bytes = new byte[32]; + + new SecureRandom().nextBytes(bytes); + var value = Base64.encode(bytes).toString(); + var vault = SOKRATES_RUNTIME.getContext().getService(Vault.class); + vault.storeSecret("test-alias", value); + vault = PLATO_RUNTIME.getContext().getService(Vault.class); + vault.storeSecret("test-alias", value); + + } + + private static Map forConfig(Map originalConfig) { + var newConfig = new HashMap<>(originalConfig); + newConfig.put("edc.dataplane.token.expiry", String.valueOf(VERY_SHORT_TOKEN_EXPIRY)); + newConfig.put("edc.dataplane.token.expiry.tolerance", "0"); + return newConfig; + } + + @BeforeEach + void setup() { + server = ClientAndServer.startClientAndServer(MOCK_BACKEND_REMOTEHOST, getFreePort()); + privateBackendUrl = "http://%s:%d%s".formatted(MOCK_BACKEND_REMOTEHOST, server.getPort(), MOCK_BACKEND_PATH); + } + + @Test + void transferData_withExpiredEdr_shouldReturn4xx() { + var assetId = "api-asset-1"; + + Map dataAddress = Map.of( + "baseUrl", privateBackendUrl, + "type", "HttpData", + "contentType", "application/json" + ); + + PLATO.createAsset(assetId, Map.of(), dataAddress); + + var accessPolicyId = PLATO.createPolicyDefinition(createAccessPolicy(SOKRATES.getBpn())); + var contractPolicyId = PLATO.createPolicyDefinition(createContractPolicy(SOKRATES.getBpn())); + PLATO.createContractDefinition(assetId, "def-1", accessPolicyId, contractPolicyId); + var transferProcessId = SOKRATES.requestAsset(PLATO, assetId, Json.createObjectBuilder().build(), createProxyRequest()); + + var edr = new AtomicReference(); + + // wait until transfer process completes + await().pollInterval(fibonacci()) + .atMost(ASYNC_TIMEOUT) + .untilAsserted(() -> { + var tpState = SOKRATES.getTransferProcessState(transferProcessId); + assertThat(tpState).isNotNull().isEqualTo(TransferProcessStates.STARTED.toString()); + }); + + // wait until EDC is available on the consumer side + server.when(request().withMethod("GET").withPath(MOCK_BACKEND_PATH)).respond(response().withStatusCode(200).withBody("test response")); + await().pollInterval(fibonacci()) + .atMost(ASYNC_TIMEOUT) + .untilAsserted(() -> { + edr.set(SOKRATES.edrs().getEdr(transferProcessId)); + assertThat(edr).isNotNull(); + }); + + + // wait until the EDR expires + await().pollDelay(Duration.ofSeconds(VERY_SHORT_TOKEN_EXPIRY + 1)) + .pollInterval(fibonacci()) + .atMost(ASYNC_TIMEOUT) + .untilAsserted(() -> { + var endpoint = edr.get().getString("endpoint"); + var token = edr.get().getString("authorization"); + given() + .baseUri(endpoint) + .header("Authorization", token) + .when() + .get() + .then() + .statusCode(403); + }); + + // assert the data has not been fetched + server.verify(request().withPath(MOCK_BACKEND_PATH), VerificationTimes.never()); + + // renew EDR explicitly + var renewedEdr = SOKRATES.edrs().refreshEdr(transferProcessId) + .statusCode(200) + .extract().body() + .as(JsonObject.class); + + // make sure the consumer has now been able to fetch the data. + var data = SOKRATES.data().pullData(renewedEdr, Map.of()); + assertThat(data).isNotNull().isEqualTo("test response"); + + server.verify(request().withPath(MOCK_BACKEND_PATH), VerificationTimes.exactly(1)); + } + + @Test + void transferData_withAutomaticRefresh() { + var assetId = "api-asset-1"; + + Map dataAddress = Map.of( + "baseUrl", privateBackendUrl, + "type", "HttpData", + "contentType", "application/json" + ); + + PLATO.createAsset(assetId, Map.of(), dataAddress); + + var accessPolicyId = PLATO.createPolicyDefinition(createAccessPolicy(SOKRATES.getBpn())); + var contractPolicyId = PLATO.createPolicyDefinition(createContractPolicy(SOKRATES.getBpn())); + PLATO.createContractDefinition(assetId, "def-1", accessPolicyId, contractPolicyId); + var transferProcessId = SOKRATES.requestAsset(PLATO, assetId, Json.createObjectBuilder().build(), createProxyRequest()); + + var edr = new AtomicReference(); + + // wait until transfer process completes + await().pollInterval(fibonacci()) + .atMost(ASYNC_TIMEOUT) + .untilAsserted(() -> { + var tpState = SOKRATES.getTransferProcessState(transferProcessId); + assertThat(tpState).isNotNull().isEqualTo(TransferProcessStates.STARTED.toString()); + }); + + // wait until EDC is available on the consumer side + server.when(request().withMethod("GET").withPath(MOCK_BACKEND_PATH)).respond(response().withStatusCode(200).withBody("test response")); + await().pollInterval(fibonacci()) + .atMost(ASYNC_TIMEOUT) + .untilAsserted(() -> { + edr.set(SOKRATES.edrs().getEdr(transferProcessId)); + assertThat(edr).isNotNull(); + }); + + + // wait until the EDR expires + await().pollDelay(Duration.ofSeconds(VERY_SHORT_TOKEN_EXPIRY + 1)) + .pollInterval(fibonacci()) + .atMost(ASYNC_TIMEOUT) + .untilAsserted(() -> { + var endpoint = edr.get().getString("endpoint"); + var token = edr.get().getString("authorization"); + given() + .baseUri(endpoint) + .header("Authorization", token) + .when() + .get() + .then() + .statusCode(403); + }); + + // assert the data has not been fetched + server.verify(request().withPath(MOCK_BACKEND_PATH), VerificationTimes.never()); + + // get EDR with automatic refresh + var renewedEdr = SOKRATES.edrs().getEdrWithRefresh(transferProcessId, true) + .statusCode(200) + .extract().body() + .as(JsonObject.class); + + // make sure the consumer has now been able to fetch the data. + var data = SOKRATES.data().pullData(renewedEdr, Map.of()); + assertThat(data).isNotNull().isEqualTo("test response"); + + server.verify(request().withPath(MOCK_BACKEND_PATH), VerificationTimes.exactly(1)); + } + + @AfterEach + void teardown() { + server.stop(); + } + + protected JsonObject createAccessPolicy(String bpn) { + return bnpPolicy(bpn); + } + + protected JsonObject createContractPolicy(String bpn) { + return bnpPolicy(bpn); + } +} diff --git a/spi/core-spi/src/main/java/org/eclipse/tractusx/edc/edr/spi/CoreConstants.java b/spi/core-spi/src/main/java/org/eclipse/tractusx/edc/edr/spi/CoreConstants.java index 5391a2b34..29d3c7a32 100644 --- a/spi/core-spi/src/main/java/org/eclipse/tractusx/edc/edr/spi/CoreConstants.java +++ b/spi/core-spi/src/main/java/org/eclipse/tractusx/edc/edr/spi/CoreConstants.java @@ -19,6 +19,8 @@ package org.eclipse.tractusx.edc.edr.spi; +import static org.eclipse.edc.spi.CoreConstants.EDC_NAMESPACE; + public final class CoreConstants { public static final String TX_PREFIX = "tx"; @@ -30,6 +32,12 @@ public final class CoreConstants { public static final String CX_POLICY_NS = "https://w3id.org/catenax/policy/"; public static final String TX_CREDENTIAL_NAMESPACE = "https://w3id.org/tractusx/credentials/v0.0.1/ns/"; + // constants related to token refresh/renewal + public static final String EDR_PROPERTY_AUTHORIZATION = EDC_NAMESPACE + "authorization"; + public static final String EDR_PROPERTY_REFRESH_TOKEN = TX_AUTH_NS + "refreshToken"; + public static final String EDR_PROPERTY_REFRESH_ENDPOINT = TX_AUTH_NS + "refreshEndpoint"; + public static final String EDR_PROPERTY_EXPIRES_IN = TX_AUTH_NS + "expiresIn"; + private CoreConstants() { } } From 1fa8390f7d30c64eba37765a151d0364cf95cdf4 Mon Sep 17 00:00:00 2001 From: Paul Latzelsperger <43503240+paullatzelsperger@users.noreply.github.com> Date: Wed, 27 Mar 2024 09:41:33 +0100 Subject: [PATCH 074/100] fix: compile errors after upstream refactor (#1166) * fix: compile errors after upstream refactor * trigger CI * DEPENDENCIES * trigger CI * refresh deps * fix test, cleanup --- DEPENDENCIES | 23 ++++++++++++------ build.gradle.kts | 24 ++++++++++++------- .../templates/deployment-controlplane.yaml | 10 -------- .../templates/deployment-runtime.yaml | 10 -------- .../templates/deployment-controlplane.yaml | 10 -------- core/edr-cache-core/build.gradle.kts | 1 + ...nMemoryEndpointDataReferenceCacheTest.java | 2 +- .../edc-controlplane-base/build.gradle.kts | 1 + .../edc-runtime-memory/build.gradle.kts | 4 +--- .../token-refresh-core/build.gradle.kts | 1 + ...eTokenRefreshServiceImplComponentTest.java | 2 +- edc-tests/miw-tests/build.gradle.kts | 1 + .../build.gradle.kts | 4 +++- .../runtime-memory-iatp-dim/build.gradle.kts | 1 - .../runtime-memory-iatp-ih/build.gradle.kts | 1 - .../iatp/runtime-memory-sts/build.gradle.kts | 1 - .../runtime-memory-ssi/build.gradle.kts | 4 +--- .../runtime-postgresql/build.gradle.kts | 1 - gradle/libs.versions.toml | 3 +++ samples/multi-tenancy/build.gradle.kts | 1 - .../multitenancy/MultiTenantRuntime.java | 5 ++++ spi/ssi-spi/build.gradle.kts | 1 + 22 files changed, 51 insertions(+), 60 deletions(-) diff --git a/DEPENDENCIES b/DEPENDENCIES index 2f65c868e..00d0595c0 100644 --- a/DEPENDENCIES +++ b/DEPENDENCIES @@ -53,13 +53,13 @@ maven/mavencentral/com.fasterxml.jackson.dataformat/jackson-dataformat-yaml/2.15 maven/mavencentral/com.fasterxml.jackson.dataformat/jackson-dataformat-yaml/2.15.2, Apache-2.0, approved, #8802 maven/mavencentral/com.fasterxml.jackson.dataformat/jackson-dataformat-yaml/2.16.2, Apache-2.0, approved, #11855 maven/mavencentral/com.fasterxml.jackson.datatype/jackson-datatype-jakarta-jsonp/2.16.2, Apache-2.0, approved, #11854 -maven/mavencentral/com.fasterxml.jackson.datatype/jackson-datatype-jakarta-jsonp/2.17.0, , restricted, clearlydefined +maven/mavencentral/com.fasterxml.jackson.datatype/jackson-datatype-jakarta-jsonp/2.17.0, Apache-2.0, approved, #14161 maven/mavencentral/com.fasterxml.jackson.datatype/jackson-datatype-jsr310/2.13.5, Apache-2.0, approved, clearlydefined maven/mavencentral/com.fasterxml.jackson.datatype/jackson-datatype-jsr310/2.14.0, Apache-2.0, approved, #4699 maven/mavencentral/com.fasterxml.jackson.datatype/jackson-datatype-jsr310/2.15.1, Apache-2.0, approved, #7930 maven/mavencentral/com.fasterxml.jackson.datatype/jackson-datatype-jsr310/2.15.2, Apache-2.0, approved, #7930 maven/mavencentral/com.fasterxml.jackson.datatype/jackson-datatype-jsr310/2.16.2, Apache-2.0, approved, #11853 -maven/mavencentral/com.fasterxml.jackson.datatype/jackson-datatype-jsr310/2.17.0, , restricted, clearlydefined +maven/mavencentral/com.fasterxml.jackson.datatype/jackson-datatype-jsr310/2.17.0, Apache-2.0, approved, #14160 maven/mavencentral/com.fasterxml.jackson.jakarta.rs/jackson-jakarta-rs-base/2.16.2, Apache-2.0, approved, #11851 maven/mavencentral/com.fasterxml.jackson.jakarta.rs/jackson-jakarta-rs-json-provider/2.15.1, Apache-2.0, approved, #9236 maven/mavencentral/com.fasterxml.jackson.jakarta.rs/jackson-jakarta-rs-json-provider/2.15.2, Apache-2.0, approved, #9236 @@ -68,7 +68,7 @@ maven/mavencentral/com.fasterxml.jackson.module/jackson-module-jakarta-xmlbind-a maven/mavencentral/com.fasterxml.jackson.module/jackson-module-jakarta-xmlbind-annotations/2.16.2, Apache-2.0, approved, #11856 maven/mavencentral/com.fasterxml.jackson/jackson-bom/2.15.1, Apache-2.0, approved, #7929 maven/mavencentral/com.fasterxml.jackson/jackson-bom/2.16.2, Apache-2.0, approved, #11852 -maven/mavencentral/com.fasterxml.jackson/jackson-bom/2.17.0, , restricted, clearlydefined +maven/mavencentral/com.fasterxml.jackson/jackson-bom/2.17.0, Apache-2.0, approved, #14162 maven/mavencentral/com.fasterxml.uuid/java-uuid-generator/4.1.0, Apache-2.0, approved, clearlydefined maven/mavencentral/com.fasterxml.woodstox/woodstox-core/6.5.1, Apache-2.0, approved, #7950 maven/mavencentral/com.github.cliftonlabs/json-simple/3.0.2, Apache-2.0, approved, clearlydefined @@ -106,8 +106,8 @@ maven/mavencentral/com.jayway.jsonpath/json-path/2.7.0, Apache-2.0, approved, cl maven/mavencentral/com.jcraft/jzlib/1.1.3, BSD-2-Clause, approved, CQ6218 maven/mavencentral/com.lmax/disruptor/3.4.4, Apache-2.0, approved, clearlydefined maven/mavencentral/com.microsoft.azure/msal4j-persistence-extension/1.2.0, MIT, approved, clearlydefined -maven/mavencentral/com.microsoft.azure/msal4j/1.14.0, MIT, approved, clearlydefined -maven/mavencentral/com.microsoft.azure/msal4j/1.14.3, , restricted, clearlydefined +maven/mavencentral/com.microsoft.azure/msal4j/1.14.0, MIT, approved, #14159 +maven/mavencentral/com.microsoft.azure/msal4j/1.14.3, MIT, approved, #14159 maven/mavencentral/com.microsoft.azure/msal4j/1.4.0, MIT, approved, clearlydefined maven/mavencentral/com.networknt/json-schema-validator/1.0.76, Apache-2.0, approved, CQ22638 maven/mavencentral/com.nimbusds/content-type/2.2, Apache-2.0, approved, clearlydefined @@ -374,8 +374,10 @@ maven/mavencentral/org.eclipse.edc/control-plane-api-client-spi/0.5.2-SNAPSHOT, maven/mavencentral/org.eclipse.edc/control-plane-api-client/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/control-plane-api/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/control-plane-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/control-plane-policies-lib/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/control-plane-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/core-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/crypto-common-lib/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/crypto-common/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/data-address-http-data-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/data-plane-aws-s3/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc @@ -446,9 +448,11 @@ maven/mavencentral/org.eclipse.edc/identity-trust-sts-spi/0.5.2-SNAPSHOT, Apache maven/mavencentral/org.eclipse.edc/identity-trust-transform/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/jersey-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/jersey-micrometer/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/jersey-providers-lib/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/jersey-providers/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/jetty-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/jetty-micrometer/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/json-ld-lib/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/json-ld-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/json-ld/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/junit-base/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc @@ -467,20 +471,25 @@ maven/mavencentral/org.eclipse.edc/oauth2-client/0.5.2-SNAPSHOT, Apache-2.0, app maven/mavencentral/org.eclipse.edc/oauth2-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/policy-definition-api/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/policy-definition-store-sql/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/policy-engine-lib/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/policy-engine-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/policy-engine/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/policy-evaluator-lib/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/policy-evaluator/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/policy-model/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/policy-monitor-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/policy-monitor-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/policy-monitor-store-sql/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/policy-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/query-lib/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/runtime-metamodel/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/security/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/sql-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/sql-lease/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/sql-pool-apache-commons/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/state-machine-lib/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/state-machine/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/store-lib/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/token-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/token-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/transaction-datasource-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc @@ -524,8 +533,8 @@ maven/mavencentral/org.eclipse.jetty/jetty-servlet/11.0.20, EPL-2.0 OR Apache-2. maven/mavencentral/org.eclipse.jetty/jetty-util/11.0.20, EPL-2.0 OR Apache-2.0, approved, rt.jetty maven/mavencentral/org.eclipse.jetty/jetty-webapp/11.0.20, EPL-2.0 OR Apache-2.0, approved, rt.jetty maven/mavencentral/org.eclipse.jetty/jetty-xml/11.0.20, EPL-2.0 OR Apache-2.0, approved, rt.jetty -maven/mavencentral/org.flywaydb/flyway-core/10.10.0, , restricted, clearlydefined -maven/mavencentral/org.flywaydb/flyway-database-postgresql/10.10.0, , restricted, clearlydefined +maven/mavencentral/org.flywaydb/flyway-core/10.10.0, Apache-2.0, approved, #14163 +maven/mavencentral/org.flywaydb/flyway-database-postgresql/10.10.0, Apache-2.0, approved, #14158 maven/mavencentral/org.glassfish.hk2.external/aopalliance-repackaged/3.0.5, EPL-2.0 OR GPL-2.0-only with Classpath-exception-2.0, approved, ee4j.glassfish maven/mavencentral/org.glassfish.hk2/hk2-api/3.0.5, EPL-2.0 OR GPL-2.0-only with Classpath-exception-2.0, approved, ee4j.glassfish maven/mavencentral/org.glassfish.hk2/hk2-locator/3.0.5, EPL-2.0 OR GPL-2.0-only with Classpath-exception-2.0, approved, ee4j.glassfish diff --git a/build.gradle.kts b/build.gradle.kts index b0dd494bb..ba104b846 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -53,6 +53,11 @@ project.subprojects.forEach { } +configurations.all { + resolutionStrategy.cacheChangingModulesFor(10, "minutes") + resolutionStrategy.cacheDynamicVersionsFor(10, "minutes") +} + allprojects { apply(plugin = "org.eclipse.edc.edc-build") @@ -98,8 +103,8 @@ allprojects { swagger { title.set((project.findProperty("apiTitle") ?: "Tractus-X REST API") as String) description = - (project.findProperty("apiDescription") - ?: "Tractus-X REST APIs - merged by OpenApiMerger") as String + (project.findProperty("apiDescription") + ?: "Tractus-X REST APIs - merged by OpenApiMerger") as String outputFilename.set(project.name) outputDirectory.set(file("${rootProject.projectDir.path}/resources/openapi/yaml")) resourcePackages = setOf("org.eclipse.tractusx.edc") @@ -151,13 +156,14 @@ allprojects { subprojects { afterEvaluate { if (project.plugins.hasPlugin("com.github.johnrengelman.shadow") && - file("${project.projectDir}/src/main/docker/Dockerfile").exists() + file("${project.projectDir}/src/main/docker/Dockerfile").exists() ) { val buildDir = project.layout.buildDirectory.get().asFile val agentFile = buildDir.resolve("opentelemetry-javaagent.jar") // create task to download the opentelemetry agent - val openTelemetryAgentUrl = "https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/download/v1.32.0/opentelemetry-javaagent.jar" + val openTelemetryAgentUrl = + "https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/download/v1.32.0/opentelemetry-javaagent.jar" val downloadOtel = tasks.create("downloadOtel") { // only execute task if the opentelemetry agent does not exist. invoke the "clean" task to force onlyIf { @@ -171,8 +177,8 @@ subprojects { doLast { val download = { url: String, destFile: File -> ant.invokeMethod( - "get", - mapOf("src" to url, "dest" to destFile) + "get", + mapOf("src" to url, "dest" to destFile) ) } logger.lifecycle("Downloading OpenTelemetry Agent") @@ -206,9 +212,9 @@ subprojects { } // make sure always runs after "dockerize" and after "copyOtel" dockerTask - .dependsOn(tasks.named(ShadowJavaPlugin.SHADOW_JAR_TASK_NAME)) - .dependsOn(downloadOtel) - .dependsOn(copyLegalDocs) + .dependsOn(tasks.named(ShadowJavaPlugin.SHADOW_JAR_TASK_NAME)) + .dependsOn(downloadOtel) + .dependsOn(copyLegalDocs) } } } diff --git a/charts/tractusx-connector-azure-vault/templates/deployment-controlplane.yaml b/charts/tractusx-connector-azure-vault/templates/deployment-controlplane.yaml index 18e2500c4..cc533e5d1 100644 --- a/charts/tractusx-connector-azure-vault/templates/deployment-controlplane.yaml +++ b/charts/tractusx-connector-azure-vault/templates/deployment-controlplane.yaml @@ -337,16 +337,6 @@ spec: value: {{ .Values.vault.azure.certificate | quote }} {{- end }} - ##################### - ## DATA ENCRYPTION ## - ##################### - - # see extension https://github.com/eclipse-tractusx/tractusx-edc/tree/main/edc-extensions/data-encryption - - name: "EDC_DATA_ENCRYPTION_KEYS_ALIAS" - value: {{ .Values.vault.secretNames.transferProxyTokenEncryptionAesKey | quote }} - - name: "EDC_DATA_ENCRYPTION_ALGORITHM" - value: "AES" - ########################### ## AAS WRAPPER EXTENSION ## ########################### diff --git a/charts/tractusx-connector-memory/templates/deployment-runtime.yaml b/charts/tractusx-connector-memory/templates/deployment-runtime.yaml index 054e4bd91..8e8daf0fe 100644 --- a/charts/tractusx-connector-memory/templates/deployment-runtime.yaml +++ b/charts/tractusx-connector-memory/templates/deployment-runtime.yaml @@ -255,16 +255,6 @@ spec: - name: "EDC_VAULT_SECRETS" value: {{ .Values.vault.secrets | quote}} - ##################### - ## DATA ENCRYPTION ## - ##################### - - # see extension https://github.com/eclipse-tractusx/tractusx-edc/tree/develop/edc-extensions/data-encryption - - name: "EDC_DATA_ENCRYPTION_KEYS_ALIAS" - value: {{ .Values.vault.secretNames.transferProxyTokenEncryptionAesKey | quote }} - - name: "EDC_DATA_ENCRYPTION_ALGORITHM" - value: "AES" - ########################### ## AAS WRAPPER EXTENSION ## ########################### diff --git a/charts/tractusx-connector/templates/deployment-controlplane.yaml b/charts/tractusx-connector/templates/deployment-controlplane.yaml index 1cc371318..ad26c55e7 100644 --- a/charts/tractusx-connector/templates/deployment-controlplane.yaml +++ b/charts/tractusx-connector/templates/deployment-controlplane.yaml @@ -336,16 +336,6 @@ spec: - name: "EDC_VAULT_HASHICORP_API_HEALTH_CHECK_PATH" value: {{ .Values.vault.hashicorp.paths.health | quote }} - ##################### - ## DATA ENCRYPTION ## - ##################### - - # see extension https://github.com/eclipse-tractusx/tractusx-edc/tree/main/edc-extensions/data-encryption - - name: "EDC_DATA_ENCRYPTION_KEYS_ALIAS" - value: {{ .Values.vault.secretNames.transferProxyTokenEncryptionAesKey | quote }} - - name: "EDC_DATA_ENCRYPTION_ALGORITHM" - value: "AES" - ########################### ## AAS WRAPPER EXTENSION ## ########################### diff --git a/core/edr-cache-core/build.gradle.kts b/core/edr-cache-core/build.gradle.kts index 9312ef4b3..72b9dd51b 100644 --- a/core/edr-cache-core/build.gradle.kts +++ b/core/edr-cache-core/build.gradle.kts @@ -28,6 +28,7 @@ dependencies { implementation(project(":spi:edr-spi")) + testImplementation(libs.edc.lib.query) testImplementation(testFixtures(project(":spi:edr-spi"))) testImplementation(libs.edc.core.connector) diff --git a/core/edr-cache-core/src/test/java/org/eclipse/tractusx/edc/edr/core/defaults/InMemoryEndpointDataReferenceCacheTest.java b/core/edr-cache-core/src/test/java/org/eclipse/tractusx/edc/edr/core/defaults/InMemoryEndpointDataReferenceCacheTest.java index 42341777a..b10c2fe95 100644 --- a/core/edr-cache-core/src/test/java/org/eclipse/tractusx/edc/edr/core/defaults/InMemoryEndpointDataReferenceCacheTest.java +++ b/core/edr-cache-core/src/test/java/org/eclipse/tractusx/edc/edr/core/defaults/InMemoryEndpointDataReferenceCacheTest.java @@ -19,7 +19,7 @@ package org.eclipse.tractusx.edc.edr.core.defaults; -import org.eclipse.edc.connector.core.store.CriterionOperatorRegistryImpl; +import org.eclipse.edc.query.CriterionOperatorRegistryImpl; import org.eclipse.edc.spi.persistence.Lease; import org.eclipse.tractusx.edc.edr.spi.EndpointDataReferenceCacheTestBase; import org.eclipse.tractusx.edc.edr.spi.store.EndpointDataReferenceCache; diff --git a/edc-controlplane/edc-controlplane-base/build.gradle.kts b/edc-controlplane/edc-controlplane-base/build.gradle.kts index 4af418d2d..85fbd011c 100644 --- a/edc-controlplane/edc-controlplane-base/build.gradle.kts +++ b/edc-controlplane/edc-controlplane-base/build.gradle.kts @@ -47,6 +47,7 @@ dependencies { runtimeOnly(project(":edc-extensions:ssi:ssi-identity-extractor")) runtimeOnly(project(":edc-extensions:cx-policy-legacy")) + runtimeOnly(libs.edc.core.connector) runtimeOnly(libs.edc.core.controlplane) runtimeOnly(libs.edc.core.policy.monitor) runtimeOnly(libs.edc.config.filesystem) diff --git a/edc-controlplane/edc-runtime-memory/build.gradle.kts b/edc-controlplane/edc-runtime-memory/build.gradle.kts index 5e154d725..b3b9dc9a4 100644 --- a/edc-controlplane/edc-runtime-memory/build.gradle.kts +++ b/edc-controlplane/edc-runtime-memory/build.gradle.kts @@ -25,9 +25,7 @@ plugins { dependencies { implementation(libs.edc.spi.core) - runtimeOnly(project(":edc-controlplane:edc-controlplane-base")) { - exclude(module = "data-encryption") - } + runtimeOnly(project(":edc-controlplane:edc-controlplane-base")) runtimeOnly(project(":edc-dataplane:edc-dataplane-base")) runtimeOnly(libs.edc.core.controlplane) testImplementation(libs.edc.junit) diff --git a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/build.gradle.kts b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/build.gradle.kts index b51ab28dc..fc727dbbb 100644 --- a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/build.gradle.kts +++ b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/build.gradle.kts @@ -30,6 +30,7 @@ dependencies { implementation(libs.edc.spi.identity.did) implementation(libs.edc.spi.dataplane.dataplane) implementation(libs.edc.core.token) + implementation(libs.edc.lib.query) testImplementation(libs.edc.junit) testImplementation(libs.edc.dpf.core) diff --git a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImplComponentTest.java b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImplComponentTest.java index 55e4aaca1..6d511b525 100644 --- a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImplComponentTest.java +++ b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImplComponentTest.java @@ -30,11 +30,11 @@ import com.nimbusds.jwt.JWTClaimsSet; import com.nimbusds.jwt.SignedJWT; import org.eclipse.edc.boot.vault.InMemoryVault; -import org.eclipse.edc.connector.core.store.CriterionOperatorRegistryImpl; import org.eclipse.edc.connector.dataplane.framework.store.InMemoryAccessTokenDataStore; import org.eclipse.edc.iam.did.spi.resolution.DidPublicKeyResolver; import org.eclipse.edc.junit.annotations.ComponentTest; import org.eclipse.edc.jwt.spi.JwtRegisteredClaimNames; +import org.eclipse.edc.query.CriterionOperatorRegistryImpl; import org.eclipse.edc.security.token.jwt.CryptoConverter; import org.eclipse.edc.spi.iam.TokenParameters; import org.eclipse.edc.spi.result.Result; diff --git a/edc-tests/miw-tests/build.gradle.kts b/edc-tests/miw-tests/build.gradle.kts index 145375cb9..c721d0c53 100644 --- a/edc-tests/miw-tests/build.gradle.kts +++ b/edc-tests/miw-tests/build.gradle.kts @@ -43,6 +43,7 @@ dependencies { testImplementation(libs.edc.ext.jsonld) testImplementation(libs.edc.dsp) testImplementation(libs.edc.lib.http) + testImplementation(libs.edc.lib.jsonld) testImplementation(testFixtures(libs.edc.sql.core)) diff --git a/edc-tests/runtime/iatp/runtime-memory-iatp-dim-ih/build.gradle.kts b/edc-tests/runtime/iatp/runtime-memory-iatp-dim-ih/build.gradle.kts index 91147986a..336d021f4 100644 --- a/edc-tests/runtime/iatp/runtime-memory-iatp-dim-ih/build.gradle.kts +++ b/edc-tests/runtime/iatp/runtime-memory-iatp-dim-ih/build.gradle.kts @@ -26,7 +26,6 @@ dependencies { // use basic (all in-mem) control plane implementation(project(":edc-controlplane:edc-controlplane-base")) { - exclude(module = "data-encryption") exclude(module = "ssi-identity-core") exclude(module = "ssi-miw-credential-client") exclude(module = "ssi-identity-extractor") @@ -58,6 +57,9 @@ dependencies { // for the controller implementation(libs.jakarta.rsApi) + + runtimeOnly(libs.edc.lib.store) + } application { diff --git a/edc-tests/runtime/iatp/runtime-memory-iatp-dim/build.gradle.kts b/edc-tests/runtime/iatp/runtime-memory-iatp-dim/build.gradle.kts index 8ad020a26..373987e6a 100644 --- a/edc-tests/runtime/iatp/runtime-memory-iatp-dim/build.gradle.kts +++ b/edc-tests/runtime/iatp/runtime-memory-iatp-dim/build.gradle.kts @@ -26,7 +26,6 @@ dependencies { // use basic (all in-mem) control plane implementation(project(":edc-controlplane:edc-controlplane-base")) { - exclude(module = "data-encryption") exclude(module = "ssi-identity-core") exclude(module = "ssi-miw-credential-client") exclude(module = "ssi-identity-extractor") diff --git a/edc-tests/runtime/iatp/runtime-memory-iatp-ih/build.gradle.kts b/edc-tests/runtime/iatp/runtime-memory-iatp-ih/build.gradle.kts index e09deca89..94429bd90 100644 --- a/edc-tests/runtime/iatp/runtime-memory-iatp-ih/build.gradle.kts +++ b/edc-tests/runtime/iatp/runtime-memory-iatp-ih/build.gradle.kts @@ -26,7 +26,6 @@ dependencies { // use basic (all in-mem) control plane implementation(project(":edc-controlplane:edc-controlplane-base")) { - exclude(module = "data-encryption") exclude(module = "ssi-identity-core") exclude(module = "ssi-miw-credential-client") exclude(module = "ssi-identity-extractor") diff --git a/edc-tests/runtime/iatp/runtime-memory-sts/build.gradle.kts b/edc-tests/runtime/iatp/runtime-memory-sts/build.gradle.kts index 6b7213087..5bd47e714 100644 --- a/edc-tests/runtime/iatp/runtime-memory-sts/build.gradle.kts +++ b/edc-tests/runtime/iatp/runtime-memory-sts/build.gradle.kts @@ -26,7 +26,6 @@ dependencies { // use basic (all in-mem) control plane implementation(project(":edc-controlplane:edc-controlplane-base")) { - exclude(module = "data-encryption") exclude(module = "ssi-identity-core") exclude(module = "ssi-miw-credential-client") exclude(module = "ssi-identity-extractor") diff --git a/edc-tests/runtime/runtime-memory-ssi/build.gradle.kts b/edc-tests/runtime/runtime-memory-ssi/build.gradle.kts index 97ea2f255..fab744c27 100644 --- a/edc-tests/runtime/runtime-memory-ssi/build.gradle.kts +++ b/edc-tests/runtime/runtime-memory-ssi/build.gradle.kts @@ -26,9 +26,7 @@ plugins { dependencies { // use basic (all in-mem) control plane - implementation(project(":edc-controlplane:edc-controlplane-base")) { - exclude(module = "data-encryption") - } + implementation(project(":edc-controlplane:edc-controlplane-base")) implementation(project(":core:json-ld-core")) diff --git a/edc-tests/runtime/runtime-postgresql/build.gradle.kts b/edc-tests/runtime/runtime-postgresql/build.gradle.kts index 944ede37c..c50092596 100644 --- a/edc-tests/runtime/runtime-postgresql/build.gradle.kts +++ b/edc-tests/runtime/runtime-postgresql/build.gradle.kts @@ -27,7 +27,6 @@ dependencies { // use basic (all in-mem) control plane implementation(project(":edc-controlplane:edc-controlplane-postgresql-hashicorp-vault")) { - exclude(module = "data-encryption") exclude(module = "json-ld-core") exclude(module = "ssi-identity-core") exclude(module = "ssi-miw-credential-client") diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index aeedaa4df..1d6817d33 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -94,6 +94,9 @@ edc-ext-jersey-providers = { module = "org.eclipse.edc:jersey-providers", versio edc-validator-data-address-http-data = { module = "org.eclipse.edc:validator-data-address-http-data", version.ref = "edc" } edc-lib-boot = { module = "org.eclipse.edc:boot-lib", version.ref = "edc" } edc-lib-http = { module = "org.eclipse.edc:http-lib", version.ref = "edc" } +edc-lib-query = { module = "org.eclipse.edc:query-lib", version.ref = "edc" } +edc-lib-jsonld = { module = "org.eclipse.edc:json-ld-lib", version.ref = "edc" } +edc-lib-store = { module = "org.eclipse.edc:store-lib", version.ref = "edc" } # implementations diff --git a/samples/multi-tenancy/build.gradle.kts b/samples/multi-tenancy/build.gradle.kts index 336bebe19..e7414bbd8 100644 --- a/samples/multi-tenancy/build.gradle.kts +++ b/samples/multi-tenancy/build.gradle.kts @@ -28,7 +28,6 @@ dependencies { implementation(libs.edc.boot) implementation(libs.edc.iam.mock) implementation(project(":edc-controlplane:edc-controlplane-base")) { - exclude("org.eclipse.tractusx.edc", "data-encryption") exclude(module = "ssi-miw-credential-client") exclude(module = "ssi-identity-core") exclude(module = "auth-tokenbased") diff --git a/samples/multi-tenancy/src/main/java/org/eclipse/tractusx/edc/samples/multitenancy/MultiTenantRuntime.java b/samples/multi-tenancy/src/main/java/org/eclipse/tractusx/edc/samples/multitenancy/MultiTenantRuntime.java index d7ac26513..fac9b12cf 100644 --- a/samples/multi-tenancy/src/main/java/org/eclipse/tractusx/edc/samples/multitenancy/MultiTenantRuntime.java +++ b/samples/multi-tenancy/src/main/java/org/eclipse/tractusx/edc/samples/multitenancy/MultiTenantRuntime.java @@ -51,6 +51,11 @@ protected void boot() { loadTenantsConfig().getConfig("edc.tenants").partition().forEach(this::bootTenant); } + @Override + protected void onError(Exception e) { + throw new EdcException(e); + } + private void bootTenant(Config tenantConfig) { var baseProperties = System.getProperties(); tenantConfig.getRelativeEntries().forEach(System::setProperty); diff --git a/spi/ssi-spi/build.gradle.kts b/spi/ssi-spi/build.gradle.kts index 67ffc3c4a..c934a34f0 100644 --- a/spi/ssi-spi/build.gradle.kts +++ b/spi/ssi-spi/build.gradle.kts @@ -25,6 +25,7 @@ plugins { dependencies { implementation(libs.edc.spi.core) implementation(libs.edc.spi.jwt) + implementation(libs.edc.spi.token) implementation(libs.jakartaJson) testFixturesImplementation(libs.jacksonJsonP) From 273c3d54de373f1efbf932fae1ba3cce9663f452 Mon Sep 17 00:00:00 2001 From: Paul Latzelsperger <43503240+paullatzelsperger@users.noreply.github.com> Date: Wed, 27 Mar 2024 13:11:51 +0100 Subject: [PATCH 075/100] feat: add BDRS client w/ expiring cache (#1165) * feat: add BDRS client w/ expiring cache * made class package-private * source doc, cosmetics * DEPENDENCIES * DEPENDENCIES * auto-close GZip Input stream * revert to default cache time * Update BdrsClient.java * DEPENDENCIES --- DEPENDENCIES | 1 + build.gradle.kts | 5 - edc-extensions/bdrs-client/build.gradle.kts | 32 ++++ .../edc/identity/mapper/BdrsClient.java | 120 ++++++++++++ .../identity/mapper/BdrsClientExtension.java | 65 +++++++ ...rg.eclipse.edc.spi.system.ServiceExtension | 20 ++ .../mapper/BdrsClientExtensionTest.java | 57 ++++++ .../edc/identity/mapper/BdrsClientTest.java | 173 ++++++++++++++++++ settings.gradle.kts | 1 + 9 files changed, 469 insertions(+), 5 deletions(-) create mode 100644 edc-extensions/bdrs-client/build.gradle.kts create mode 100644 edc-extensions/bdrs-client/src/main/java/org/eclipse/tractusx/edc/identity/mapper/BdrsClient.java create mode 100644 edc-extensions/bdrs-client/src/main/java/org/eclipse/tractusx/edc/identity/mapper/BdrsClientExtension.java create mode 100644 edc-extensions/bdrs-client/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension create mode 100644 edc-extensions/bdrs-client/src/test/java/org/eclipse/tractusx/edc/identity/mapper/BdrsClientExtensionTest.java create mode 100644 edc-extensions/bdrs-client/src/test/java/org/eclipse/tractusx/edc/identity/mapper/BdrsClientTest.java diff --git a/DEPENDENCIES b/DEPENDENCIES index 00d0595c0..93bff3887 100644 --- a/DEPENDENCIES +++ b/DEPENDENCIES @@ -324,6 +324,7 @@ maven/mavencentral/org.apache.xbean/xbean-reflect/3.7, Apache-2.0, approved, cle maven/mavencentral/org.apiguardian/apiguardian-api/1.1.2, Apache-2.0, approved, clearlydefined maven/mavencentral/org.assertj/assertj-core/3.25.3, Apache-2.0, approved, #12585 maven/mavencentral/org.awaitility/awaitility/4.2.0, Apache-2.0, approved, clearlydefined +maven/mavencentral/org.awaitility/awaitility/4.2.1, , restricted, clearlydefined maven/mavencentral/org.bouncycastle/bcpkix-jdk18on/1.72, MIT, approved, #3789 maven/mavencentral/org.bouncycastle/bcpkix-jdk18on/1.77, MIT, approved, #11593 maven/mavencentral/org.bouncycastle/bcprov-jdk18on/1.72, MIT AND CC0-1.0, approved, #3538 diff --git a/build.gradle.kts b/build.gradle.kts index ba104b846..b7dc88f81 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -53,11 +53,6 @@ project.subprojects.forEach { } -configurations.all { - resolutionStrategy.cacheChangingModulesFor(10, "minutes") - resolutionStrategy.cacheDynamicVersionsFor(10, "minutes") -} - allprojects { apply(plugin = "org.eclipse.edc.edc-build") diff --git a/edc-extensions/bdrs-client/build.gradle.kts b/edc-extensions/bdrs-client/build.gradle.kts new file mode 100644 index 000000000..a7367d260 --- /dev/null +++ b/edc-extensions/bdrs-client/build.gradle.kts @@ -0,0 +1,32 @@ +/******************************************************************************** + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +plugins { + `maven-publish` + `java-library` +} + +dependencies { + implementation(libs.edc.spi.core) + implementation(libs.edc.spi.http) + + testImplementation(libs.netty.mockserver) + testImplementation(libs.edc.junit) + testImplementation(libs.awaitility) +} diff --git a/edc-extensions/bdrs-client/src/main/java/org/eclipse/tractusx/edc/identity/mapper/BdrsClient.java b/edc-extensions/bdrs-client/src/main/java/org/eclipse/tractusx/edc/identity/mapper/BdrsClient.java new file mode 100644 index 000000000..174410d19 --- /dev/null +++ b/edc-extensions/bdrs-client/src/main/java/org/eclipse/tractusx/edc/identity/mapper/BdrsClient.java @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.eclipse.tractusx.edc.identity.mapper; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; +import okhttp3.Request; +import org.eclipse.edc.spi.EdcException; +import org.eclipse.edc.spi.http.EdcHttpClient; +import org.eclipse.edc.spi.iam.AudienceResolver; +import org.eclipse.edc.spi.monitor.Monitor; +import org.eclipse.edc.spi.types.domain.message.RemoteMessage; + +import java.io.IOException; +import java.time.Instant; +import java.time.temporal.ChronoUnit; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.locks.ReentrantReadWriteLock; +import java.util.zip.GZIPInputStream; + +/** + * Holds a local cache of BPN-to-DID mapping entries. An incoming {@link RemoteMessage} is mapped by looking up the {@link RemoteMessage#getCounterPartyId()} + * property in that map. + *

    + * The local cache expires after a configurable time, at which point {@link BdrsClient#resolve(RemoteMessage)} requests will hit the server again. + */ +class BdrsClient implements AudienceResolver { + private static final TypeReference> MAP_REF = new TypeReference<>() { + }; + private final String serverUrl; + private final int cacheValidity; + private final EdcHttpClient httpClient; + private final Monitor monitor; + private final ObjectMapper mapper; + private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); + private Map cache = new HashMap<>(); + private Instant lastCacheUpdate; + + BdrsClient(String baseUrl, int cacheValidity, EdcHttpClient httpClient, Monitor monitor, ObjectMapper mapper) { + this.serverUrl = baseUrl; + this.cacheValidity = cacheValidity; + this.httpClient = httpClient; + this.monitor = monitor; + this.mapper = mapper; + } + + @Override + public String resolve(RemoteMessage remoteMessage) { + var bpn = remoteMessage.getCounterPartyId(); + String value; + lock.readLock().lock(); + try { + if (isCacheExpired()) { + lock.readLock().unlock(); // unlock read, acquire write -> "upgrade" lock + lock.writeLock().lock(); + try { + if (isCacheExpired()) { + updateCache(); + } + } finally { + lock.readLock().lock(); // downgrade lock + lock.writeLock().unlock(); + } + } + + value = cache.get(bpn); + } finally { + lock.readLock().unlock(); + } + return value; + } + + private boolean isCacheExpired() { + return lastCacheUpdate == null || lastCacheUpdate.plus(cacheValidity, ChronoUnit.SECONDS).isBefore(Instant.now()); + } + + private void updateCache() { + var request = new Request.Builder() + //.addHeader("Authorization", createMembershipPresentation()) //todo: add MembershipCredential as JWT-VP to the auth header + .header("Accept-Encoding", "gzip") + .url(serverUrl + "/bpn-directory") + .get() + .build(); + try (var response = httpClient.execute(request)) { + if (response.isSuccessful() && response.body() != null) { + var body = response.body().byteStream(); + try (var gz = new GZIPInputStream(body)) { + var bytes = gz.readAllBytes(); + cache = mapper.readValue(bytes, MAP_REF); + lastCacheUpdate = Instant.now(); + } + } else { + var msg = "Could not obtain data from BDRS server: code: %d, message: %s".formatted(response.code(), response.message()); + throw new EdcException(msg); + } + } catch (IOException e) { + monitor.severe("Error fetching BDRS data", e); + throw new EdcException(e); + } + } + +} diff --git a/edc-extensions/bdrs-client/src/main/java/org/eclipse/tractusx/edc/identity/mapper/BdrsClientExtension.java b/edc-extensions/bdrs-client/src/main/java/org/eclipse/tractusx/edc/identity/mapper/BdrsClientExtension.java new file mode 100644 index 000000000..8232d9887 --- /dev/null +++ b/edc-extensions/bdrs-client/src/main/java/org/eclipse/tractusx/edc/identity/mapper/BdrsClientExtension.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.eclipse.tractusx.edc.identity.mapper; + +import org.eclipse.edc.runtime.metamodel.annotation.Extension; +import org.eclipse.edc.runtime.metamodel.annotation.Inject; +import org.eclipse.edc.runtime.metamodel.annotation.Provider; +import org.eclipse.edc.runtime.metamodel.annotation.Setting; +import org.eclipse.edc.spi.http.EdcHttpClient; +import org.eclipse.edc.spi.iam.AudienceResolver; +import org.eclipse.edc.spi.system.ServiceExtension; +import org.eclipse.edc.spi.system.ServiceExtensionContext; +import org.eclipse.edc.spi.types.TypeManager; + +import static org.eclipse.tractusx.edc.identity.mapper.BdrsClientExtension.NAME; + +@Extension(value = NAME) +public class BdrsClientExtension implements ServiceExtension { + public static final String NAME = "BPN/DID Resolution Service Client Extension"; + + public static final int DEFAULT_BDRS_CACHE_VALIDITY = 15 * 60; // 15 minutes + @Setting(value = "Base URL of the BDRS service", required = true) + public static final String BDRS_SERVER_URL_PROPERTY = "tx.iam.iatp.bdrs.server.url"; + + @Setting(value = "Validity period in seconds for the cached BPN/DID mappings. After this period a new resolution request will hit the server.", defaultValue = DEFAULT_BDRS_CACHE_VALIDITY + "") + public static final String BDRS_SERVER_CACHE_VALIDITY_PERIOD = "tx.iam.iatp.bdrs.cache.validity"; + + @Inject + private EdcHttpClient httpClient; + @Inject + private TypeManager typeManager; + + @Override + public String name() { + return NAME; + } + + @Provider + public AudienceResolver getBdrsAudienceResolver(ServiceExtensionContext context) { + var baseUrl = context.getConfig().getString(BDRS_SERVER_URL_PROPERTY, null); + if (baseUrl == null) { + context.getMonitor().severe("The following property was expected but was not provided: '%s'. This runtime will not work correctly!".formatted(BDRS_SERVER_URL_PROPERTY)); + } + var cacheValidity = context.getConfig().getInteger(BDRS_SERVER_CACHE_VALIDITY_PERIOD, DEFAULT_BDRS_CACHE_VALIDITY); + return new BdrsClient(baseUrl, cacheValidity, httpClient, context.getMonitor(), typeManager.getMapper()); + } + +} diff --git a/edc-extensions/bdrs-client/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension b/edc-extensions/bdrs-client/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension new file mode 100644 index 000000000..8b85b19b1 --- /dev/null +++ b/edc-extensions/bdrs-client/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension @@ -0,0 +1,20 @@ +################################################################################# +# Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License, Version 2.0 which is available at +# https://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. +# +# SPDX-License-Identifier: Apache-2.0 +################################################################################# + +org.eclipse.tractusx.edc.identity.mapper.BdrsClientExtension \ No newline at end of file diff --git a/edc-extensions/bdrs-client/src/test/java/org/eclipse/tractusx/edc/identity/mapper/BdrsClientExtensionTest.java b/edc-extensions/bdrs-client/src/test/java/org/eclipse/tractusx/edc/identity/mapper/BdrsClientExtensionTest.java new file mode 100644 index 000000000..4ca60ab13 --- /dev/null +++ b/edc-extensions/bdrs-client/src/test/java/org/eclipse/tractusx/edc/identity/mapper/BdrsClientExtensionTest.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.eclipse.tractusx.edc.identity.mapper; + +import org.eclipse.edc.junit.extensions.DependencyInjectionExtension; +import org.eclipse.edc.spi.monitor.Monitor; +import org.eclipse.edc.spi.system.ServiceExtensionContext; +import org.eclipse.edc.spi.system.configuration.Config; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; + +import static org.eclipse.tractusx.edc.identity.mapper.BdrsClientExtension.BDRS_SERVER_URL_PROPERTY; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.isNull; +import static org.mockito.ArgumentMatchers.matches; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@ExtendWith(DependencyInjectionExtension.class) +class BdrsClientExtensionTest { + + private final Monitor monitor = mock(); + + @BeforeEach + void setup(ServiceExtensionContext context) { + context.registerService(Monitor.class, monitor); + } + + @Test + void createClient_whenUrlMissing_expectLogError(ServiceExtensionContext context, BdrsClientExtension extension) { + var cfg = mock(Config.class); + when(context.getConfig()).thenReturn(cfg); + when(cfg.getString(eq(BDRS_SERVER_URL_PROPERTY), isNull())).thenReturn(null); + + extension.getBdrsAudienceResolver(context); + verify(monitor).severe(matches("^The following property was expected but was not provided: '.*'. This runtime will not work correctly!$")); + } +} \ No newline at end of file diff --git a/edc-extensions/bdrs-client/src/test/java/org/eclipse/tractusx/edc/identity/mapper/BdrsClientTest.java b/edc-extensions/bdrs-client/src/test/java/org/eclipse/tractusx/edc/identity/mapper/BdrsClientTest.java new file mode 100644 index 000000000..c6a47e838 --- /dev/null +++ b/edc-extensions/bdrs-client/src/test/java/org/eclipse/tractusx/edc/identity/mapper/BdrsClientTest.java @@ -0,0 +1,173 @@ +/* + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.eclipse.tractusx.edc.identity.mapper; + +import com.fasterxml.jackson.databind.ObjectMapper; +import dev.failsafe.RetryPolicy; +import okhttp3.OkHttpClient; +import org.eclipse.edc.spi.EdcException; +import org.eclipse.edc.spi.monitor.Monitor; +import org.eclipse.edc.spi.types.domain.message.RemoteMessage; +import org.eclipse.http.client.EdcHttpClientImpl; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; +import org.mockserver.integration.ClientAndServer; +import org.mockserver.model.HttpResponse; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.Map; +import java.util.zip.GZIPOutputStream; + +import static java.time.Duration.ofSeconds; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.awaitility.Awaitility.await; +import static org.eclipse.edc.util.io.Ports.getFreePort; +import static org.mockito.Mockito.mock; +import static org.mockserver.model.HttpRequest.request; +import static org.mockserver.verify.VerificationTimes.exactly; + +class BdrsClientTest { + + private final Monitor monitor = mock(); + private final ObjectMapper mapper = new ObjectMapper(); + private BdrsClient client; + private ClientAndServer bdrsServer; + + @BeforeEach + void setup() { + bdrsServer = ClientAndServer.startClientAndServer(getFreePort()); + bdrsServer.when(request() + .withMethod("GET") + .withPath("/api/bpn-directory")) + .respond(HttpResponse.response() + .withHeader("Content-Encoding", "gzip") + .withBody(createGzipStream()) + .withStatusCode(200)); + + client = new BdrsClient("http://localhost:%d/api".formatted(bdrsServer.getPort()), 1, new EdcHttpClientImpl(new OkHttpClient(), RetryPolicy.ofDefaults(), monitor), monitor, mapper); + } + + @AfterEach + void teardown() { + bdrsServer.stop(); + } + + @Test + void getData_whenCacheCold_shouldHitServer() { + var did = client.resolve(new TestMessage("bpn1")); + assertThat(did).isEqualTo("did:web:did1"); + + bdrsServer.verify(request() + .withMethod("GET") + .withPath("/api/bpn-directory") + .withHeader("Accept-Encoding", "gzip"), + exactly(1)); + } + + @Test + void getData_whenCacheHot_shouldNotHitServer() { + var did1 = client.resolve(new TestMessage("bpn1")); + var did2 = client.resolve(new TestMessage("bpn2")); + assertThat(did1).isEqualTo("did:web:did1"); + assertThat(did2).isEqualTo("did:web:did2"); + + bdrsServer.verify(request() + .withMethod("GET") + .withPath("/api/bpn-directory") + .withHeader("Accept-Encoding", "gzip"), + exactly(1)); + } + + @Test + void getData_whenCacheExpired_shouldHitServer() { + var did1 = client.resolve(new TestMessage("bpn1")); // hits server + assertThat(did1).isEqualTo("did:web:did1"); + + await().pollDelay(ofSeconds(2)) + .atMost(ofSeconds(3)) //cache expires + .untilAsserted(() -> { + var did2 = client.resolve(new TestMessage("bpn2")); // hits server as well, b/c cache is expired + assertThat(did2).isEqualTo("did:web:did2"); + + bdrsServer.verify(request() + .withHeader("Accept-Encoding", "gzip") + .withMethod("GET") + .withPath("/api/bpn-directory"), + exactly(2)); + }); + + } + + @Test + void getData_whenNotFound() { + var did = client.resolve(new TestMessage("bpn-notexist")); + assertThat(did).isNull(); + bdrsServer.verify(request() + .withMethod("GET") + .withPath("/api/bpn-directory") + .withHeader("Accept-Encoding", "gzip"), + exactly(1)); + } + + @ParameterizedTest(name = "HTTP Status {0}") + @ValueSource(ints = { 400, 401, 403, 404, 405 }) + void getData_bdrsReturnsError(int code) { + bdrsServer.reset(); + bdrsServer.when(request().withPath("/api/bpn-directory").withMethod("GET")) + .respond(HttpResponse.response().withStatusCode(code)); + assertThatThrownBy(() -> client.resolve(new TestMessage("bpn1"))).isInstanceOf(EdcException.class); + } + + private byte[] createGzipStream() { + var data = Map.of("bpn1", "did:web:did1", + "bpn2", "did:web:did2", + "bpn3", "did:web:did3"); + + var bas = new ByteArrayOutputStream(); + try (var gzip = new GZIPOutputStream(bas)) { + gzip.write(mapper.writeValueAsBytes(data)); + } catch (IOException e) { + throw new RuntimeException(e); + } + return bas.toByteArray(); + } + + private record TestMessage(String bpn) implements RemoteMessage { + @Override + public String getProtocol() { + return "test-proto"; + } + + @Override + public String getCounterPartyAddress() { + return "http://bpn1"; + } + + @Override + public String getCounterPartyId() { + return bpn; + } + } +} \ No newline at end of file diff --git a/settings.gradle.kts b/settings.gradle.kts index 8a4d6c9e2..88ad36697 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -41,6 +41,7 @@ include(":edc-extensions:bpn-validation:bpn-validation-core") include(":edc-extensions:bpn-validation:business-partner-store-sql") include(":edc-extensions:postgresql-migration") include(":edc-extensions:tokenrefresh-handler") +include(":edc-extensions:bdrs-client") include(":edc-extensions:provision-additional-headers") include(":edc-extensions:transferprocess-sftp-client") include(":edc-extensions:transferprocess-sftp-common") From cfa891768de50d7ef5d2b5aa45c8e36081ce6573 Mon Sep 17 00:00:00 2001 From: Enrico Risa Date: Wed, 27 Mar 2024 13:21:08 +0100 Subject: [PATCH 076/100] feat: credential based identity extractor (#1164) * feat: moves identity extractor from tests to iatp lib + tests * chore: dependencies file --- core/core-utils/build.gradle.kts | 1 + .../credentials}/CredentialTypePredicate.java | 2 +- edc-extensions/cx-policy/build.gradle.kts | 1 + ...ismantlerCredentialConstraintFunction.java | 2 +- ...AgreementCredentialConstraintFunction.java | 2 +- ...embershipCredentialConstraintFunction.java | 2 +- edc-extensions/iatp/tx-iatp/build.gradle.kts | 1 + .../edc/iam/iatp/IatpIdentityExtension.java | 21 +++- .../iatp/identity/IatpIdentityExtractor.java | 19 +-- ...rg.eclipse.edc.spi.system.ServiceExtension | 1 + .../iam/iatp/IatpIdentityExtensionTest.java | 50 ++++++++ .../identity/IatpIdentityExtractorTest.java | 110 ++++++++++++++++++ ...rg.eclipse.edc.spi.system.ServiceExtension | 1 - 13 files changed, 194 insertions(+), 19 deletions(-) rename {edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/common => core/core-utils/src/main/java/org/eclipse/tractusx/edc/core/utils/credentials}/CredentialTypePredicate.java (96%) rename edc-tests/runtime/iatp/iatp-extensions/src/main/java/org/eclipse/tractusx/edc/iatp/policy/CredentialPolicyEvaluationExtension.java => edc-extensions/iatp/tx-iatp/src/main/java/org/eclipse/tractusx/edc/iam/iatp/IatpIdentityExtension.java (73%) rename edc-tests/runtime/iatp/iatp-extensions/src/main/java/org/eclipse/tractusx/edc/iatp/policy/IdentityExtractor.java => edc-extensions/iatp/tx-iatp/src/main/java/org/eclipse/tractusx/edc/iam/iatp/identity/IatpIdentityExtractor.java (85%) create mode 100644 edc-extensions/iatp/tx-iatp/src/test/java/org/eclipse/tractusx/edc/iam/iatp/IatpIdentityExtensionTest.java create mode 100644 edc-extensions/iatp/tx-iatp/src/test/java/org/eclipse/tractusx/edc/iam/iatp/identity/IatpIdentityExtractorTest.java diff --git a/core/core-utils/build.gradle.kts b/core/core-utils/build.gradle.kts index 5f5745992..9eb6a95d7 100644 --- a/core/core-utils/build.gradle.kts +++ b/core/core-utils/build.gradle.kts @@ -23,4 +23,5 @@ plugins { dependencies { implementation(libs.edc.spi.core) + implementation(libs.edc.spi.identitytrust) } diff --git a/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/common/CredentialTypePredicate.java b/core/core-utils/src/main/java/org/eclipse/tractusx/edc/core/utils/credentials/CredentialTypePredicate.java similarity index 96% rename from edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/common/CredentialTypePredicate.java rename to core/core-utils/src/main/java/org/eclipse/tractusx/edc/core/utils/credentials/CredentialTypePredicate.java index f7a98fb54..0ab867c26 100644 --- a/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/common/CredentialTypePredicate.java +++ b/core/core-utils/src/main/java/org/eclipse/tractusx/edc/core/utils/credentials/CredentialTypePredicate.java @@ -17,7 +17,7 @@ * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ -package org.eclipse.tractusx.edc.policy.cx.common; +package org.eclipse.tractusx.edc.core.utils.credentials; import org.eclipse.edc.identitytrust.model.VerifiableCredential; diff --git a/edc-extensions/cx-policy/build.gradle.kts b/edc-extensions/cx-policy/build.gradle.kts index def8283d6..9f0e6c79c 100644 --- a/edc-extensions/cx-policy/build.gradle.kts +++ b/edc-extensions/cx-policy/build.gradle.kts @@ -24,6 +24,7 @@ plugins { dependencies { implementation(project(":spi:core-spi")) implementation(project(":spi:ssi-spi")) + implementation(project(":core:core-utils")) implementation(libs.edc.spi.policyengine) implementation(libs.jakartaJson) implementation(libs.edc.spi.identitytrust) diff --git a/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/dismantler/DismantlerCredentialConstraintFunction.java b/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/dismantler/DismantlerCredentialConstraintFunction.java index 9d054e974..f9549f2ba 100644 --- a/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/dismantler/DismantlerCredentialConstraintFunction.java +++ b/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/dismantler/DismantlerCredentialConstraintFunction.java @@ -24,8 +24,8 @@ import org.eclipse.edc.policy.engine.spi.PolicyContext; import org.eclipse.edc.policy.model.Operator; import org.eclipse.edc.policy.model.Permission; +import org.eclipse.tractusx.edc.core.utils.credentials.CredentialTypePredicate; import org.eclipse.tractusx.edc.policy.cx.common.AbstractDynamicCredentialConstraintFunction; -import org.eclipse.tractusx.edc.policy.cx.common.CredentialTypePredicate; import org.jetbrains.annotations.NotNull; import java.util.ArrayList; diff --git a/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/framework/FrameworkAgreementCredentialConstraintFunction.java b/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/framework/FrameworkAgreementCredentialConstraintFunction.java index bd1ed844d..6aa34648d 100644 --- a/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/framework/FrameworkAgreementCredentialConstraintFunction.java +++ b/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/framework/FrameworkAgreementCredentialConstraintFunction.java @@ -25,8 +25,8 @@ import org.eclipse.edc.policy.model.Permission; import org.eclipse.edc.spi.agent.ParticipantAgent; import org.eclipse.edc.spi.result.Result; +import org.eclipse.tractusx.edc.core.utils.credentials.CredentialTypePredicate; import org.eclipse.tractusx.edc.policy.cx.common.AbstractDynamicCredentialConstraintFunction; -import org.eclipse.tractusx.edc.policy.cx.common.CredentialTypePredicate; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; diff --git a/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/membership/MembershipCredentialConstraintFunction.java b/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/membership/MembershipCredentialConstraintFunction.java index 4c9d9a234..6c85ce75e 100644 --- a/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/membership/MembershipCredentialConstraintFunction.java +++ b/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/membership/MembershipCredentialConstraintFunction.java @@ -23,8 +23,8 @@ import org.eclipse.edc.policy.model.Operator; import org.eclipse.edc.policy.model.Permission; import org.eclipse.edc.spi.agent.ParticipantAgent; +import org.eclipse.tractusx.edc.core.utils.credentials.CredentialTypePredicate; import org.eclipse.tractusx.edc.policy.cx.common.AbstractDynamicCredentialConstraintFunction; -import org.eclipse.tractusx.edc.policy.cx.common.CredentialTypePredicate; import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.CX_CREDENTIAL_NS; import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.CX_POLICY_NS; diff --git a/edc-extensions/iatp/tx-iatp/build.gradle.kts b/edc-extensions/iatp/tx-iatp/build.gradle.kts index 03633b26c..3205d9b55 100644 --- a/edc-extensions/iatp/tx-iatp/build.gradle.kts +++ b/edc-extensions/iatp/tx-iatp/build.gradle.kts @@ -27,6 +27,7 @@ dependencies { implementation(libs.edc.spi.policyengine) implementation(libs.edc.identity.trust.spi) implementation(project(":spi:core-spi")) + implementation(project(":core:core-utils")) testImplementation(libs.edc.junit) } diff --git a/edc-tests/runtime/iatp/iatp-extensions/src/main/java/org/eclipse/tractusx/edc/iatp/policy/CredentialPolicyEvaluationExtension.java b/edc-extensions/iatp/tx-iatp/src/main/java/org/eclipse/tractusx/edc/iam/iatp/IatpIdentityExtension.java similarity index 73% rename from edc-tests/runtime/iatp/iatp-extensions/src/main/java/org/eclipse/tractusx/edc/iatp/policy/CredentialPolicyEvaluationExtension.java rename to edc-extensions/iatp/tx-iatp/src/main/java/org/eclipse/tractusx/edc/iam/iatp/IatpIdentityExtension.java index 28cf6a19b..7f8213771 100644 --- a/edc-tests/runtime/iatp/iatp-extensions/src/main/java/org/eclipse/tractusx/edc/iatp/policy/CredentialPolicyEvaluationExtension.java +++ b/edc-extensions/iatp/tx-iatp/src/main/java/org/eclipse/tractusx/edc/iam/iatp/IatpIdentityExtension.java @@ -17,24 +17,33 @@ * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ -package org.eclipse.tractusx.edc.iatp.policy; +package org.eclipse.tractusx.edc.iam.iatp; import org.eclipse.edc.runtime.metamodel.annotation.Extension; import org.eclipse.edc.runtime.metamodel.annotation.Inject; import org.eclipse.edc.spi.agent.ParticipantAgentService; import org.eclipse.edc.spi.system.ServiceExtension; import org.eclipse.edc.spi.system.ServiceExtensionContext; +import org.eclipse.tractusx.edc.iam.iatp.identity.IatpIdentityExtractor; -@Extension("TX credential policy evaluation extension") -public class CredentialPolicyEvaluationExtension implements ServiceExtension { - +import static org.eclipse.tractusx.edc.iam.iatp.IatpDefaultScopeExtension.NAME; + +@Extension(NAME) +public class IatpIdentityExtension implements ServiceExtension { + + + static final String NAME = "Tractusx IATP identity extension"; @Inject private ParticipantAgentService participantAgentService; @Override - public void initialize(ServiceExtensionContext context) { + public String name() { + return NAME; + } - participantAgentService.register(new IdentityExtractor()); + @Override + public void initialize(ServiceExtensionContext context) { + participantAgentService.register(new IatpIdentityExtractor()); } } diff --git a/edc-tests/runtime/iatp/iatp-extensions/src/main/java/org/eclipse/tractusx/edc/iatp/policy/IdentityExtractor.java b/edc-extensions/iatp/tx-iatp/src/main/java/org/eclipse/tractusx/edc/iam/iatp/identity/IatpIdentityExtractor.java similarity index 85% rename from edc-tests/runtime/iatp/iatp-extensions/src/main/java/org/eclipse/tractusx/edc/iatp/policy/IdentityExtractor.java rename to edc-extensions/iatp/tx-iatp/src/main/java/org/eclipse/tractusx/edc/iam/iatp/identity/IatpIdentityExtractor.java index 7afddbe82..4899f6af1 100644 --- a/edc-tests/runtime/iatp/iatp-extensions/src/main/java/org/eclipse/tractusx/edc/iatp/policy/IdentityExtractor.java +++ b/edc-extensions/iatp/tx-iatp/src/main/java/org/eclipse/tractusx/edc/iam/iatp/identity/IatpIdentityExtractor.java @@ -17,13 +17,14 @@ * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ -package org.eclipse.tractusx.edc.iatp.policy; +package org.eclipse.tractusx.edc.iam.iatp.identity; import org.eclipse.edc.identitytrust.model.VerifiableCredential; import org.eclipse.edc.spi.EdcException; import org.eclipse.edc.spi.agent.ParticipantAgentServiceExtension; import org.eclipse.edc.spi.iam.ClaimToken; import org.eclipse.edc.spi.result.Result; +import org.eclipse.tractusx.edc.core.utils.credentials.CredentialTypePredicate; import org.jetbrains.annotations.NotNull; import java.util.List; @@ -31,21 +32,27 @@ import java.util.Optional; import static org.eclipse.edc.spi.agent.ParticipantAgent.PARTICIPANT_IDENTITY; +import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.CX_CREDENTIAL_NS; -// TODO this is just a test identity extractor, the real one can be inspired by this but with final Identity credential -public class IdentityExtractor implements ParticipantAgentServiceExtension { +/** + * Implementation of {@link ParticipantAgentServiceExtension} which extracts the identity of a participant + * from the MembershipCredential + */ +public class IatpIdentityExtractor implements ParticipantAgentServiceExtension { private static final String VC_CLAIM = "vc"; private static final String IDENTITY_CREDENTIAL = "MembershipCredential"; private static final String IDENTITY_PROPERTY = "holderIdentifier"; + private final CredentialTypePredicate typePredicate = new CredentialTypePredicate(CX_CREDENTIAL_NS, IDENTITY_CREDENTIAL); + @Override public @NotNull Map attributesFor(ClaimToken claimToken) { var credentials = getCredentialList(claimToken) .orElseThrow(failure -> new EdcException("Failed to fetch credentials from the claim token: %s".formatted(failure.getFailureDetail()))); return credentials.stream() - .filter(this::isIdentityCredential) + .filter(typePredicate) .findFirst() .flatMap(this::getIdentifier) .map(identity -> Map.of(PARTICIPANT_IDENTITY, identity)) @@ -54,10 +61,6 @@ public class IdentityExtractor implements ParticipantAgentServiceExtension { } - private boolean isIdentityCredential(VerifiableCredential verifiableCredential) { - return verifiableCredential.getType().stream().anyMatch(t -> t.endsWith(IDENTITY_CREDENTIAL)); - } - private Optional getIdentifier(VerifiableCredential verifiableCredential) { return verifiableCredential.getCredentialSubject().stream() .flatMap(credentialSubject -> credentialSubject.getClaims().entrySet().stream()) diff --git a/edc-extensions/iatp/tx-iatp/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension b/edc-extensions/iatp/tx-iatp/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension index 8441c54b3..0d9cdbce5 100644 --- a/edc-extensions/iatp/tx-iatp/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension +++ b/edc-extensions/iatp/tx-iatp/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension @@ -18,5 +18,6 @@ ################################################################################# org.eclipse.tractusx.edc.iam.iatp.IatpDefaultScopeExtension +org.eclipse.tractusx.edc.iam.iatp.IatpIdentityExtension org.eclipse.tractusx.edc.iam.iatp.IatpScopeExtractorExtension diff --git a/edc-extensions/iatp/tx-iatp/src/test/java/org/eclipse/tractusx/edc/iam/iatp/IatpIdentityExtensionTest.java b/edc-extensions/iatp/tx-iatp/src/test/java/org/eclipse/tractusx/edc/iam/iatp/IatpIdentityExtensionTest.java new file mode 100644 index 000000000..71e45ab12 --- /dev/null +++ b/edc-extensions/iatp/tx-iatp/src/test/java/org/eclipse/tractusx/edc/iam/iatp/IatpIdentityExtensionTest.java @@ -0,0 +1,50 @@ +/******************************************************************************** + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +package org.eclipse.tractusx.edc.iam.iatp; + +import org.eclipse.edc.junit.extensions.DependencyInjectionExtension; +import org.eclipse.edc.spi.agent.ParticipantAgentService; +import org.eclipse.edc.spi.system.ServiceExtensionContext; +import org.eclipse.tractusx.edc.iam.iatp.identity.IatpIdentityExtractor; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; + +import static org.mockito.ArgumentMatchers.isA; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; + +@ExtendWith(DependencyInjectionExtension.class) +public class IatpIdentityExtensionTest { + + private final ParticipantAgentService participantAgentService = mock(); + + @BeforeEach + void setup(ServiceExtensionContext context) { + context.registerService(ParticipantAgentService.class, participantAgentService); + } + + @Test + void initialize(ServiceExtensionContext context, IatpIdentityExtension extension) { + extension.initialize(context); + verify(participantAgentService).register(isA(IatpIdentityExtractor.class)); + } + +} diff --git a/edc-extensions/iatp/tx-iatp/src/test/java/org/eclipse/tractusx/edc/iam/iatp/identity/IatpIdentityExtractorTest.java b/edc-extensions/iatp/tx-iatp/src/test/java/org/eclipse/tractusx/edc/iam/iatp/identity/IatpIdentityExtractorTest.java new file mode 100644 index 000000000..82062d705 --- /dev/null +++ b/edc-extensions/iatp/tx-iatp/src/test/java/org/eclipse/tractusx/edc/iam/iatp/identity/IatpIdentityExtractorTest.java @@ -0,0 +1,110 @@ +/******************************************************************************** + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +package org.eclipse.tractusx.edc.iam.iatp.identity; + +import org.eclipse.edc.identitytrust.model.CredentialSubject; +import org.eclipse.edc.identitytrust.model.Issuer; +import org.eclipse.edc.identitytrust.model.VerifiableCredential; +import org.eclipse.edc.spi.EdcException; +import org.eclipse.edc.spi.iam.ClaimToken; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtensionContext; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.ArgumentsProvider; +import org.junit.jupiter.params.provider.ArgumentsSource; + +import java.time.Instant; +import java.util.List; +import java.util.Map; +import java.util.stream.Stream; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.eclipse.edc.spi.agent.ParticipantAgent.PARTICIPANT_IDENTITY; +import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.CX_CREDENTIAL_NS; + +class IatpIdentityExtractorTest { + + private static final String IDENTITY = "identity"; + private final IatpIdentityExtractor extractor = new IatpIdentityExtractor(); + + private static VerifiableCredential vc(String type, Map claims) { + return VerifiableCredential.Builder.newInstance().type(type) + .issuanceDate(Instant.now()) + .issuer(new Issuer("issuer", Map.of())) + .credentialSubject(CredentialSubject.Builder.newInstance().claims(claims).build()) + .build(); + } + + @ParameterizedTest + @ArgumentsSource(VerifiableCredentialArgumentProvider.class) + void attributesFor(VerifiableCredential credential) { + var attributes = extractor.attributesFor(ClaimToken.Builder.newInstance().claim("vc", List.of(credential)).build()); + assertThat(attributes).containsEntry(PARTICIPANT_IDENTITY, IDENTITY); + } + + @Test + void attributesFor_Fails_WhenCredentialNotFound() { + assertThatThrownBy(() -> extractor.attributesFor(ClaimToken.Builder.newInstance().claim("vc", List.of(vc("FooCredential", Map.of("foo", "bar")))).build())) + .isInstanceOf(EdcException.class) + .hasMessageContaining("Failed to fetch"); + } + + @Test + void attributesFor_Fails_whenNoVcClaims() { + assertThatThrownBy(() -> extractor.attributesFor(ClaimToken.Builder.newInstance().build())) + .isInstanceOf(EdcException.class) + .hasMessageContaining("Failed to fetch credentials from the claim token: ClaimToken did not contain a 'vc' claim"); + } + + @Test + void attributesFor_Fails_whenNullVcClaims() { + + assertThatThrownBy(() -> extractor.attributesFor(ClaimToken.Builder.newInstance().claim("vc", null).build())) + .isInstanceOf(EdcException.class) + .hasMessageContaining("Failed to fetch credentials from the claim token: ClaimToken did not contain a 'vc' claim"); + } + + @Test + void attributesFor_Fails_WhenVcClaimIsNotList() { + assertThatThrownBy(() -> extractor.attributesFor(ClaimToken.Builder.newInstance().claim("vc", "wrong").build())) + .isInstanceOf(EdcException.class) + .hasMessageContaining("Failed to fetch credentials from the claim token: ClaimToken contains a 'vc' claim, but the type is incorrect. Expected java.util.List, got java.lang.String."); + } + + @Test + void attributesFor_Fails_WhenVcClaimsIsEmptyList() { + assertThatThrownBy(() -> extractor.attributesFor(ClaimToken.Builder.newInstance().claim("vc", List.of()).build())) + .isInstanceOf(EdcException.class) + .hasMessageContaining("Failed to fetch credentials from the claim token: ClaimToken contains a 'vc' claim but it did not contain any VerifiableCredentials."); + } + + private static class VerifiableCredentialArgumentProvider implements ArgumentsProvider { + @Override + public Stream provideArguments(ExtensionContext context) { + return Stream.of( + Arguments.of(vc("MembershipCredential", Map.of("holderIdentifier", IDENTITY))), + Arguments.of(vc(CX_CREDENTIAL_NS + "MembershipCredential", Map.of("holderIdentifier", IDENTITY))), + Arguments.of(vc(CX_CREDENTIAL_NS + "MembershipCredential", Map.of(CX_CREDENTIAL_NS + "holderIdentifier", IDENTITY)))); + } + + } +} diff --git a/edc-tests/runtime/iatp/iatp-extensions/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension b/edc-tests/runtime/iatp/iatp-extensions/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension index db5562906..3fd86f849 100644 --- a/edc-tests/runtime/iatp/iatp-extensions/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension +++ b/edc-tests/runtime/iatp/iatp-extensions/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension @@ -19,5 +19,4 @@ org.eclipse.tractusx.edc.iatp.TestAudienceMapperExtension org.eclipse.tractusx.edc.iatp.ih.IdentityHubExtension -org.eclipse.tractusx.edc.iatp.policy.CredentialPolicyEvaluationExtension org.eclipse.tractusx.edc.iatp.CredentialsJsonLdExtension From 5c0f41809dabfecd520f34a707fa9107d06d2a10 Mon Sep 17 00:00:00 2001 From: Paul Latzelsperger <43503240+paullatzelsperger@users.noreply.github.com> Date: Thu, 28 Mar 2024 08:47:38 +0100 Subject: [PATCH 077/100] chore(build): updates to EDC 0.6.0 (#1168) * chore(build): update to EDC 0.6.0 * DEPENDENCIES --- DEPENDENCIES | 347 +++++++++--------- core/edr-core/build.gradle.kts | 2 +- .../token-refresh-core/build.gradle.kts | 2 +- .../edr/edr-api-v2/build.gradle.kts | 2 +- edc-extensions/edr/edr-api/build.gradle.kts | 2 +- .../build.gradle.kts | 2 +- .../build.gradle.kts | 2 +- .../fixtures/build.gradle.kts | 2 +- gradle/libs.versions.toml | 12 +- 9 files changed, 184 insertions(+), 189 deletions(-) diff --git a/DEPENDENCIES b/DEPENDENCIES index 93bff3887..551567877 100644 --- a/DEPENDENCIES +++ b/DEPENDENCIES @@ -323,8 +323,8 @@ maven/mavencentral/org.apache.velocity/velocity-engine-scripting/2.3, Apache-2.0 maven/mavencentral/org.apache.xbean/xbean-reflect/3.7, Apache-2.0, approved, clearlydefined maven/mavencentral/org.apiguardian/apiguardian-api/1.1.2, Apache-2.0, approved, clearlydefined maven/mavencentral/org.assertj/assertj-core/3.25.3, Apache-2.0, approved, #12585 -maven/mavencentral/org.awaitility/awaitility/4.2.0, Apache-2.0, approved, clearlydefined -maven/mavencentral/org.awaitility/awaitility/4.2.1, , restricted, clearlydefined +maven/mavencentral/org.awaitility/awaitility/4.2.0, Apache-2.0, approved, #14178 +maven/mavencentral/org.awaitility/awaitility/4.2.1, Apache-2.0, approved, #14178 maven/mavencentral/org.bouncycastle/bcpkix-jdk18on/1.72, MIT, approved, #3789 maven/mavencentral/org.bouncycastle/bcpkix-jdk18on/1.77, MIT, approved, #11593 maven/mavencentral/org.bouncycastle/bcprov-jdk18on/1.72, MIT AND CC0-1.0, approved, #3538 @@ -341,177 +341,172 @@ maven/mavencentral/org.codehaus.plexus/plexus-utils/3.1.1, , approved, CQ16492 maven/mavencentral/org.codehaus.plexus/plexus-utils/3.3.0, , approved, CQ21066 maven/mavencentral/org.codehaus.woodstox/stax2-api/4.2.1, BSD-2-Clause, approved, #2670 maven/mavencentral/org.eclipse.angus/angus-activation/1.0.0, EPL-2.0 OR GPL-2.0-only with Classpath-exception-2.0, approved, ee4j.angus -maven/mavencentral/org.eclipse.edc/api-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/api-observability/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/asset-api/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/asset-index-sql/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/asset-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/auth-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/auth-tokenbased/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/autodoc-processor/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/aws-s3-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/aws-s3-test/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/azure-blob-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/azure-test/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/boot-lib/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/boot/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/callback-event-dispatcher/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/callback-http-dispatcher/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/catalog-api/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/catalog-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/catalog-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/configuration-filesystem/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/connector-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/contract-agreement-api/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/contract-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/contract-definition-api/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/contract-definition-store-sql/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/contract-negotiation-api/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/contract-negotiation-store-sql/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/contract-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/control-api-configuration/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/control-plane-aggregate-services/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/control-plane-api-client-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/control-plane-api-client/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/control-plane-api/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/control-plane-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/control-plane-policies-lib/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/control-plane-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/core-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/crypto-common-lib/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/crypto-common/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-address-http-data-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-plane-aws-s3/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-plane-azure-storage/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-plane-client-embedded/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-plane-control-api/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-plane-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-plane-http-oauth2-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-plane-http-oauth2/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-plane-http-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-plane-http/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-plane-public-api-v2/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-plane-selector-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-plane-selector-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-plane-signaling-api-configuration/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-plane-signaling-api/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-plane-signaling-client/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-plane-signaling-transform/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-plane-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-plane-util/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-api-configuration/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-catalog-api/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-catalog-http-dispatcher/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-catalog-transform/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-catalog/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-http-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-http-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-negotiation-api/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-negotiation-http-dispatcher/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-negotiation-transform/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-negotiation/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-transfer-process-api/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-transfer-process-http-dispatcher/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-transfer-process-transform/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-transfer-process/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-version-api/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/edr-store-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/edr-store-receiver/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/edr-store-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/http-lib/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/http-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/http/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/iam-mock/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-did-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-did-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-did-web/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-hub-api/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-hub-credentials/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-hub-did-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-hub-did/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-hub-keypairs/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-hub-participants/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-hub-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-hub-store-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-trust-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-trust-issuers-configuration/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-trust-service/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-trust-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-trust-sts-api/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-trust-sts-client-configuration/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-trust-sts-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-trust-sts-embedded/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-trust-sts-remote-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-trust-sts-remote/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-trust-sts-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-trust-transform/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/jersey-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/jersey-micrometer/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/jersey-providers-lib/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/jersey-providers/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/jetty-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/jetty-micrometer/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/json-ld-lib/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/json-ld-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/json-ld/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/junit-base/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/junit/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/jws2020/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/jwt-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/jwt-verifiable-credentials/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/keys-lib/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/keys-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/ldp-verifiable-credentials/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/management-api-configuration/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/management-api-test-fixtures/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/management-api/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/micrometer-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/oauth2-client/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/oauth2-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/policy-definition-api/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/policy-definition-store-sql/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/policy-engine-lib/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/policy-engine-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/policy-engine/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/policy-evaluator-lib/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/policy-evaluator/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/policy-model/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/policy-monitor-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/policy-monitor-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/policy-monitor-store-sql/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/policy-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/query-lib/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/runtime-metamodel/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/security/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/sql-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/sql-lease/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/sql-pool-apache-commons/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/state-machine-lib/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/state-machine/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/store-lib/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/token-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/token-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/transaction-datasource-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/transaction-local/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/transaction-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/transfer-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/transfer-data-plane-signaling/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/transfer-data-plane-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/transfer-process-api/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/transfer-process-store-sql/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/transfer-pull-http-dynamic-receiver/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/transfer-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/transform-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/transform-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/util/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/validator-core/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/validator-data-address-http-data/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/validator-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/vault-azure/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/vault-hashicorp/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/web-spi/0.5.2-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/api-core/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/api-observability/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/asset-api/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/asset-index-sql/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/asset-spi/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/auth-spi/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/auth-tokenbased/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/autodoc-processor/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/aws-s3-core/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/aws-s3-test/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/azure-blob-core/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/azure-test/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/boot-lib/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/boot/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/callback-event-dispatcher/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/callback-http-dispatcher/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/catalog-api/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/catalog-core/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/catalog-spi/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/configuration-filesystem/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/connector-core/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/contract-agreement-api/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/contract-core/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/contract-definition-api/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/contract-definition-store-sql/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/contract-negotiation-api/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/contract-negotiation-store-sql/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/contract-spi/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/control-api-configuration/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/control-plane-aggregate-services/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/control-plane-api-client-spi/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/control-plane-api-client/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/control-plane-api/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/control-plane-core/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/control-plane-policies-lib/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/control-plane-spi/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/core-spi/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/crypto-common-lib/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-address-http-data-spi/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-aws-s3/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-azure-storage/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-client-embedded/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-control-api/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-core/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-http-oauth2-core/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-http-oauth2/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-http-spi/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-http/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-public-api-v2/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-selector-core/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-selector-spi/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-signaling-api-configuration/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-signaling-api/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-signaling-client/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-signaling-transform/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-spi/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-util/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-api-configuration/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-catalog-api/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-catalog-http-dispatcher/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-catalog-transform/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-catalog/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-http-core/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-http-spi/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-negotiation-api/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-negotiation-http-dispatcher/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-negotiation-transform/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-negotiation/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-spi/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-transfer-process-api/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-transfer-process-http-dispatcher/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-transfer-process-transform/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-transfer-process/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-version-api/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/edr-store-core/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/edr-store-receiver/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/edr-store-spi/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/http-lib/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/http-spi/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/http/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/iam-mock/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-did-core/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-did-spi/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-did-web/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-hub-api/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-hub-credentials/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-hub-did-spi/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-hub-did/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-hub-keypairs/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-hub-participants/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-hub-spi/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-hub-store-spi/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-trust-core/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-trust-issuers-configuration/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-trust-service/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-trust-spi/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-trust-sts-api/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-trust-sts-client-configuration/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-trust-sts-core/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-trust-sts-embedded/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-trust-sts-remote-core/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-trust-sts-remote/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-trust-sts-spi/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-trust-transform/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/jersey-core/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/jersey-micrometer/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/jersey-providers-lib/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/jetty-core/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/jetty-micrometer/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/json-ld-lib/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/json-ld-spi/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/json-ld/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/junit-base/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/junit/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/jws2020/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/jwt-spi/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/jwt-verifiable-credentials/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/keys-lib/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/keys-spi/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/ldp-verifiable-credentials/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/management-api-configuration/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/management-api-test-fixtures/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/management-api/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/micrometer-core/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/oauth2-client/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/oauth2-spi/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/policy-definition-api/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/policy-definition-store-sql/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/policy-engine-lib/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/policy-engine-spi/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/policy-evaluator-lib/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/policy-model/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/policy-monitor-core/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/policy-monitor-spi/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/policy-monitor-store-sql/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/policy-spi/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/query-lib/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/runtime-metamodel/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/security/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/sql-core/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/sql-lease/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/sql-pool-apache-commons/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/state-machine-lib/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/store-lib/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/token-core/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/token-spi/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/transaction-datasource-spi/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/transaction-local/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/transaction-spi/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/transfer-core/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/transfer-data-plane-signaling/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/transfer-data-plane-spi/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/transfer-process-api/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/transfer-process-store-sql/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/transfer-pull-http-dynamic-receiver/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/transfer-spi/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/transform-core/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/transform-spi/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/util/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/validator-core/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/validator-data-address-http-data/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/validator-spi/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/vault-azure/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/vault-hashicorp/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/web-spi/0.6.0, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.jetty.toolchain/jetty-jakarta-servlet-api/5.0.2, EPL-2.0 OR Apache-2.0, approved, rt.jetty maven/mavencentral/org.eclipse.jetty.toolchain/jetty-jakarta-websocket-api/2.0.0, EPL-2.0 OR Apache-2.0, approved, rt.jetty maven/mavencentral/org.eclipse.jetty.websocket/websocket-core-client/11.0.20, EPL-2.0 OR Apache-2.0, approved, rt.jetty @@ -562,13 +557,13 @@ maven/mavencentral/org.jacoco/org.jacoco.core/0.8.9, EPL-2.0, approved, CQ23283 maven/mavencentral/org.jacoco/org.jacoco.report/0.8.9, EPL-2.0 AND Apache-2.0, approved, CQ23284 maven/mavencentral/org.javassist/javassist/3.28.0-GA, Apache-2.0 OR LGPL-2.1-or-later OR MPL-1.1, approved, #327 maven/mavencentral/org.javassist/javassist/3.29.2-GA, Apache-2.0 AND LGPL-2.1-or-later AND MPL-1.1, approved, #6023 -maven/mavencentral/org.jetbrains.kotlin/kotlin-stdlib-common/1.9.10, Apache-2.0, approved, clearlydefined +maven/mavencentral/org.jetbrains.kotlin/kotlin-stdlib-common/1.9.10, Apache-2.0, approved, #14186 maven/mavencentral/org.jetbrains.kotlin/kotlin-stdlib-jdk7/1.8.0, Apache-2.0, approved, #8807 maven/mavencentral/org.jetbrains.kotlin/kotlin-stdlib-jdk7/1.8.21, Apache-2.0, approved, #8807 -maven/mavencentral/org.jetbrains.kotlin/kotlin-stdlib-jdk7/1.9.10, Apache-2.0, approved, clearlydefined +maven/mavencentral/org.jetbrains.kotlin/kotlin-stdlib-jdk7/1.9.10, None, restricted, #14188 maven/mavencentral/org.jetbrains.kotlin/kotlin-stdlib-jdk8/1.8.0, Apache-2.0, approved, #8919 maven/mavencentral/org.jetbrains.kotlin/kotlin-stdlib-jdk8/1.8.21, Apache-2.0, approved, #8919 -maven/mavencentral/org.jetbrains.kotlin/kotlin-stdlib-jdk8/1.9.10, Apache-2.0, approved, clearlydefined +maven/mavencentral/org.jetbrains.kotlin/kotlin-stdlib-jdk8/1.9.10, None, restricted, #14185 maven/mavencentral/org.jetbrains.kotlin/kotlin-stdlib/1.8.21, Apache-2.0, approved, #8865 maven/mavencentral/org.jetbrains.kotlin/kotlin-stdlib/1.9.10, Apache-2.0, approved, #11827 maven/mavencentral/org.jetbrains.kotlin/kotlin-stdlib/1.9.21, Apache-2.0, approved, #11827 diff --git a/core/edr-core/build.gradle.kts b/core/edr-core/build.gradle.kts index e575979c6..96604fd45 100644 --- a/core/edr-core/build.gradle.kts +++ b/core/edr-core/build.gradle.kts @@ -27,7 +27,7 @@ dependencies { implementation(libs.edc.util) implementation(libs.edc.spi.contract) implementation(libs.edc.spi.controlplane) - implementation(libs.edc.statemachine) + implementation(libs.edc.lib.statemachine) implementation(project(":spi:edr-spi")) implementation(project(":spi:core-spi")) diff --git a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/build.gradle.kts b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/build.gradle.kts index fc727dbbb..71d956150 100644 --- a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/build.gradle.kts +++ b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/build.gradle.kts @@ -31,11 +31,11 @@ dependencies { implementation(libs.edc.spi.dataplane.dataplane) implementation(libs.edc.core.token) implementation(libs.edc.lib.query) + implementation(libs.edc.lib.cryptocommon) testImplementation(libs.edc.junit) testImplementation(libs.edc.dpf.core) testImplementation(libs.edc.core.connector) - testImplementation(libs.edc.common.crypto) testImplementation(libs.edc.lib.boot) } diff --git a/edc-extensions/edr/edr-api-v2/build.gradle.kts b/edc-extensions/edr/edr-api-v2/build.gradle.kts index 1e9cf0074..71dc0ca7e 100644 --- a/edc-extensions/edr/edr-api-v2/build.gradle.kts +++ b/edc-extensions/edr/edr-api-v2/build.gradle.kts @@ -37,6 +37,6 @@ dependencies { testImplementation(testFixtures(libs.edc.core.jersey)) testImplementation(libs.restAssured) testImplementation(libs.edc.junit) - testImplementation(libs.edc.ext.jersey.providers) + testImplementation(libs.edc.lib.jersey.providers) testImplementation(libs.edc.core.transform) } diff --git a/edc-extensions/edr/edr-api/build.gradle.kts b/edc-extensions/edr/edr-api/build.gradle.kts index bd0841441..3ed761fa7 100644 --- a/edc-extensions/edr/edr-api/build.gradle.kts +++ b/edc-extensions/edr/edr-api/build.gradle.kts @@ -35,6 +35,6 @@ dependencies { testImplementation(testFixtures(libs.edc.core.jersey)) testImplementation(libs.restAssured) testImplementation(libs.edc.junit) - testImplementation(libs.edc.ext.jersey.providers) + testImplementation(libs.edc.lib.jersey.providers) testImplementation(libs.edc.core.transform) } diff --git a/edc-extensions/transferprocess-sftp-client/build.gradle.kts b/edc-extensions/transferprocess-sftp-client/build.gradle.kts index 67501fb0d..5ca1d98e2 100644 --- a/edc-extensions/transferprocess-sftp-client/build.gradle.kts +++ b/edc-extensions/transferprocess-sftp-client/build.gradle.kts @@ -30,7 +30,7 @@ dependencies { implementation(libs.edc.spi.dataplane.dataplane) implementation(libs.edc.dpf.util) implementation(libs.edc.dpf.core) - implementation(libs.edc.policy.engine) + implementation(libs.edc.lib.policyengine) implementation(libs.bouncyCastle.bcpkixJdk18on) implementation(libs.apache.sshd.core) diff --git a/edc-extensions/transferprocess-sftp-provisioner/build.gradle.kts b/edc-extensions/transferprocess-sftp-provisioner/build.gradle.kts index 67b6aee63..07f96e598 100644 --- a/edc-extensions/transferprocess-sftp-provisioner/build.gradle.kts +++ b/edc-extensions/transferprocess-sftp-provisioner/build.gradle.kts @@ -26,7 +26,7 @@ dependencies { implementation(project(":edc-extensions:transferprocess-sftp-common")) implementation(libs.edc.spi.core) - implementation(libs.edc.policy.engine) + implementation(libs.edc.lib.policyengine) implementation(libs.edc.spi.transfer) testImplementation(libs.edc.junit) diff --git a/edc-tests/edc-controlplane/fixtures/build.gradle.kts b/edc-tests/edc-controlplane/fixtures/build.gradle.kts index 79fa980f2..dc93f0e33 100644 --- a/edc-tests/edc-controlplane/fixtures/build.gradle.kts +++ b/edc-tests/edc-controlplane/fixtures/build.gradle.kts @@ -34,7 +34,7 @@ dependencies { testFixturesApi(libs.edc.spi.contract) testFixturesApi(testFixtures(libs.edc.api.management.test.fixtures)) testFixturesApi(libs.edc.spi.edrstore) - testFixturesApi(libs.edc.common.crypto) + testFixturesApi(libs.edc.lib.cryptocommon) testFixturesApi(libs.edc.lib.boot) // api modules for some test utils diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 1d6817d33..2e6ab4618 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -2,7 +2,7 @@ format.version = "1.1" [versions] -edc = "0.5.2-SNAPSHOT" +edc = "0.6.0" apache-sshd = "2.12.1" assertj = "3.25.3" awaitility = "4.2.0" @@ -57,7 +57,6 @@ edc-config-filesystem = { module = "org.eclipse.edc:configuration-filesystem", v edc-jsonld = { module = "org.eclipse.edc:json-ld", version.ref = "edc" } edc-vault-filesystem = { module = "org.eclipse.edc:vault-filesystem", version.ref = "edc" } edc-vault-hashicorp = { module = "org.eclipse.edc:vault-hashicorp", version.ref = "edc" } -edc-common-crypto = { module = "org.eclipse.edc:crypto-common", version.ref = "edc" } edc-core-controlplane = { module = "org.eclipse.edc:control-plane-core", version.ref = "edc" } edc-core-connector = { module = "org.eclipse.edc:connector-core", version.ref = "edc" } edc-core-jetty = { module = "org.eclipse.edc:jetty-core", version.ref = "edc" } @@ -69,7 +68,6 @@ edc-core-validator = { module = "org.eclipse.edc:validator-core", version.ref = edc-core-transform = { module = "org.eclipse.edc:transform-core", version.ref = "edc" } edc-core-token = { module = "org.eclipse.edc:token-core", version.ref = "edc" } edc-core-edrstore = { module = "org.eclipse.edc:edr-store-core", version.ref = "edc" } -edc-statemachine = { module = "org.eclipse.edc:state-machine", version.ref = "edc" } edc-junit = { module = "org.eclipse.edc:junit", version.ref = "edc" } edc-api-management-config = { module = "org.eclipse.edc:management-api-configuration", version.ref = "edc" } edc-api-management = { module = "org.eclipse.edc:management-api", version.ref = "edc" } @@ -82,7 +80,6 @@ edc-api-transferprocess = { module = "org.eclipse.edc:transfer-process-api", ver edc-api-controlplane = { module = "org.eclipse.edc:control-plane-api", version.ref = "edc" } edc-dsp = { module = "org.eclipse.edc:dsp", version.ref = "edc" } edc-iam-mock = { module = "org.eclipse.edc:iam-mock", version.ref = "edc" } -edc-policy-engine = { module = "org.eclipse.edc:policy-engine", version.ref = "edc" } edc-auth-tokenbased = { module = "org.eclipse.edc:auth-tokenbased", version.ref = "edc" } edc-auth-oauth2-client = { module = "org.eclipse.edc:oauth2-client", version.ref = "edc" } edc-transaction-local = { module = "org.eclipse.edc:transaction-local", version.ref = "edc" } @@ -90,13 +87,16 @@ edc-ext-http = { module = "org.eclipse.edc:http", version.ref = "edc" } edc-ext-azure-cosmos-core = { module = "org.eclipse.edc:azure-cosmos-core", version.ref = "edc" } edc-ext-azure-test = { module = "org.eclipse.edc:azure-test", version.ref = "edc" } edc-ext-jsonld = { module = "org.eclipse.edc:json-ld", version.ref = "edc" } -edc-ext-jersey-providers = { module = "org.eclipse.edc:jersey-providers", version.ref = "edc" } edc-validator-data-address-http-data = { module = "org.eclipse.edc:validator-data-address-http-data", version.ref = "edc" } edc-lib-boot = { module = "org.eclipse.edc:boot-lib", version.ref = "edc" } +edc-lib-cryptocommon = { module = "org.eclipse.edc:crypto-common-lib", version.ref = "edc" } edc-lib-http = { module = "org.eclipse.edc:http-lib", version.ref = "edc" } -edc-lib-query = { module = "org.eclipse.edc:query-lib", version.ref = "edc" } +edc-lib-jersey-providers = { module = "org.eclipse.edc:jersey-providers-lib", version.ref = "edc" } edc-lib-jsonld = { module = "org.eclipse.edc:json-ld-lib", version.ref = "edc" } +edc-lib-policyengine = { module = "org.eclipse.edc:policy-engine-lib", version.ref = "edc" } +edc-lib-query = { module = "org.eclipse.edc:query-lib", version.ref = "edc" } edc-lib-store = { module = "org.eclipse.edc:store-lib", version.ref = "edc" } +edc-lib-statemachine = { module = "org.eclipse.edc:state-machine-lib", version.ref = "edc" } # implementations From b83338b99d786151e5d2182acad35f37f798a456 Mon Sep 17 00:00:00 2001 From: Enrico Risa Date: Thu, 28 Mar 2024 09:50:09 +0100 Subject: [PATCH 078/100] fix: use local key resolver for data plane token verification (#1167) --- .../core/DataPlaneTokenRefreshServiceExtension.java | 5 ++++- .../tokenrefresh/core/DataPlaneTokenRefreshServiceImpl.java | 6 +++++- .../core/DataPlaneTokenRefreshServiceImplComponentTest.java | 6 ++++++ .../core/DataPlaneTokenRefreshServiceImplTest.java | 6 +++++- 4 files changed, 20 insertions(+), 3 deletions(-) diff --git a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceExtension.java b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceExtension.java index ab4de2587..3dd2b5421 100644 --- a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceExtension.java +++ b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceExtension.java @@ -22,6 +22,7 @@ import org.eclipse.edc.connector.dataplane.spi.iam.DataPlaneAccessTokenService; import org.eclipse.edc.connector.dataplane.spi.store.AccessTokenDataStore; import org.eclipse.edc.iam.did.spi.resolution.DidPublicKeyResolver; +import org.eclipse.edc.keys.spi.LocalPublicKeyService; import org.eclipse.edc.keys.spi.PrivateKeyResolver; import org.eclipse.edc.runtime.metamodel.annotation.Extension; import org.eclipse.edc.runtime.metamodel.annotation.Inject; @@ -64,6 +65,8 @@ public class DataPlaneTokenRefreshServiceExtension implements ServiceExtension { @Inject private DidPublicKeyResolver didPkResolver; @Inject + private LocalPublicKeyService localPublicKeyService; + @Inject private AccessTokenDataStore accessTokenDataStore; @Inject private PrivateKeyResolver privateKeyResolver; @@ -108,7 +111,7 @@ private DataPlaneTokenRefreshServiceImpl getTokenRefreshService(ServiceExtension var tokenExpiry = getExpiryConfig(context); monitor.debug("Token refresh endpoint: %s".formatted(refreshEndpoint)); monitor.debug("Token refresh time tolerance: %d s".formatted(expiryTolerance)); - tokenRefreshService = new DataPlaneTokenRefreshServiceImpl(clock, tokenValidationService, didPkResolver, accessTokenDataStore, new JwtGenerationService(), + tokenRefreshService = new DataPlaneTokenRefreshServiceImpl(clock, tokenValidationService, didPkResolver, localPublicKeyService, accessTokenDataStore, new JwtGenerationService(), getPrivateKeySupplier(context), context.getMonitor(), refreshEndpoint, expiryTolerance, tokenExpiry, () -> context.getConfig().getString(TOKEN_VERIFIER_PUBLIC_KEY_ALIAS), vault, typeManager.getMapper()); } diff --git a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImpl.java b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImpl.java index 44f851cd6..9a179e945 100644 --- a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImpl.java +++ b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImpl.java @@ -27,6 +27,7 @@ import org.eclipse.edc.connector.dataplane.spi.store.AccessTokenDataStore; import org.eclipse.edc.iam.did.spi.resolution.DidPublicKeyResolver; import org.eclipse.edc.jwt.spi.JwtRegisteredClaimNames; +import org.eclipse.edc.keys.spi.LocalPublicKeyService; import org.eclipse.edc.spi.iam.ClaimToken; import org.eclipse.edc.spi.iam.TokenParameters; import org.eclipse.edc.spi.iam.TokenRepresentation; @@ -77,6 +78,7 @@ public class DataPlaneTokenRefreshServiceImpl implements DataPlaneTokenRefreshSe private final List accessTokenAuthorizationRules; private final TokenValidationService tokenValidationService; private final DidPublicKeyResolver publicKeyResolver; + private final LocalPublicKeyService localPublicKeyService; private final AccessTokenDataStore accessTokenDataStore; private final TokenGenerationService tokenGenerationService; private final Supplier privateKeySupplier; @@ -90,6 +92,7 @@ public class DataPlaneTokenRefreshServiceImpl implements DataPlaneTokenRefreshSe public DataPlaneTokenRefreshServiceImpl(Clock clock, TokenValidationService tokenValidationService, DidPublicKeyResolver publicKeyResolver, + LocalPublicKeyService localPublicKeyService, AccessTokenDataStore accessTokenDataStore, TokenGenerationService tokenGenerationService, Supplier privateKeySupplier, @@ -102,6 +105,7 @@ public DataPlaneTokenRefreshServiceImpl(Clock clock, ObjectMapper objectMapper) { this.tokenValidationService = tokenValidationService; this.publicKeyResolver = publicKeyResolver; + this.localPublicKeyService = localPublicKeyService; this.accessTokenDataStore = accessTokenDataStore; this.tokenGenerationService = tokenGenerationService; this.privateKeySupplier = privateKeySupplier; @@ -235,7 +239,7 @@ public Result obtainToken(TokenParameters tokenParameters, @Override public Result resolve(String token) { - return tokenValidationService.validate(token, publicKeyResolver, accessTokenAuthorizationRules) + return tokenValidationService.validate(token, localPublicKeyService, accessTokenAuthorizationRules) .compose(claimToken -> { var id = claimToken.getStringClaim(JWTClaimNames.JWT_ID); var tokenData = accessTokenDataStore.getById(id); diff --git a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImplComponentTest.java b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImplComponentTest.java index 6d511b525..1fff7c112 100644 --- a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImplComponentTest.java +++ b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImplComponentTest.java @@ -34,6 +34,7 @@ import org.eclipse.edc.iam.did.spi.resolution.DidPublicKeyResolver; import org.eclipse.edc.junit.annotations.ComponentTest; import org.eclipse.edc.jwt.spi.JwtRegisteredClaimNames; +import org.eclipse.edc.keys.spi.LocalPublicKeyService; import org.eclipse.edc.query.CriterionOperatorRegistryImpl; import org.eclipse.edc.security.token.jwt.CryptoConverter; import org.eclipse.edc.spi.iam.TokenParameters; @@ -69,6 +70,7 @@ class DataPlaneTokenRefreshServiceImplComponentTest { public static final String CONSUMER_DID = "did:web:bob"; public static final String PROVIDER_DID = "did:web:alice"; private final DidPublicKeyResolver didPkResolverMock = mock(); + private final LocalPublicKeyService localPublicKeyService = mock(); private DataPlaneTokenRefreshServiceImpl tokenRefreshService; private InMemoryAccessTokenDataStore tokenDataStore; private ECKey consumerKey; @@ -86,6 +88,7 @@ void setup() throws JOSEException { tokenRefreshService = new DataPlaneTokenRefreshServiceImpl(Clock.systemUTC(), new TokenValidationServiceImpl(), didPkResolverMock, + localPublicKeyService, tokenDataStore, new JwtGenerationService(), () -> privateKey, @@ -97,6 +100,9 @@ void setup() throws JOSEException { new InMemoryVault(mock()), new ObjectMapper()); + when(localPublicKeyService.resolveKey(eq(consumerKey.getKeyID()))).thenReturn(Result.success(consumerKey.toPublicKey())); + when(localPublicKeyService.resolveKey(eq(providerKey.getKeyID()))).thenReturn(Result.success(providerKey.toPublicKey())); + when(didPkResolverMock.resolveKey(eq(consumerKey.getKeyID()))).thenReturn(Result.success(consumerKey.toPublicKey())); when(didPkResolverMock.resolveKey(eq(providerKey.getKeyID()))).thenReturn(Result.success(providerKey.toPublicKey())); } diff --git a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImplTest.java b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImplTest.java index 64c92f65b..173b981ef 100644 --- a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImplTest.java +++ b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImplTest.java @@ -23,6 +23,7 @@ import org.eclipse.edc.connector.dataplane.spi.AccessTokenData; import org.eclipse.edc.connector.dataplane.spi.store.AccessTokenDataStore; import org.eclipse.edc.iam.did.spi.resolution.DidPublicKeyResolver; +import org.eclipse.edc.keys.spi.LocalPublicKeyService; import org.eclipse.edc.spi.iam.ClaimToken; import org.eclipse.edc.spi.iam.TokenParameters; import org.eclipse.edc.spi.iam.TokenRepresentation; @@ -65,7 +66,10 @@ class DataPlaneTokenRefreshServiceImplTest { private final TokenValidationService tokenValidationService = mock(); private final DidPublicKeyResolver didPublicKeyResolver = mock(); - private final DataPlaneTokenRefreshServiceImpl accessTokenService = new DataPlaneTokenRefreshServiceImpl(Clock.systemUTC(), tokenValidationService, didPublicKeyResolver, accessTokenDataStore, tokenGenService, mock(), mock(), + private final LocalPublicKeyService localPublicKeyService = mock(); + + private final DataPlaneTokenRefreshServiceImpl accessTokenService = new DataPlaneTokenRefreshServiceImpl(Clock.systemUTC(), + tokenValidationService, didPublicKeyResolver, localPublicKeyService, accessTokenDataStore, tokenGenService, mock(), mock(), "https://example.com", 1, 300L, () -> "keyid", mock(), new ObjectMapper()); From b2ab647075d7fb4d6380f498ec9e4ba7dbb5c8e3 Mon Sep 17 00:00:00 2001 From: Enrico Risa Date: Thu, 28 Mar 2024 17:30:30 +0100 Subject: [PATCH 079/100] chore: E2E tests refactor (#1169) --- .../edc/lifecycle/DimParticipant.java | 4 +- .../edc/lifecycle/MiwParticipant.java | 4 +- ...st.java => DimCatalogIntegrationTest.java} | 2 +- ...> DimHttpPullTransferIntegrationTest.java} | 8 +- .../tests/catalog/AbstractCatalogTest.java | 205 --------------- .../tests/catalog/CatalogInMemoryTest.java | 44 ---- .../tests/catalog/CatalogPostgresqlTest.java | 43 ---- .../edc/tests/catalog/CatalogTest.java | 235 ++++++++++++++++++ .../tests/edrv2/AbstractNegotiateEdrTest.java | 10 +- .../tests/edrv2/EdrCacheApiEndToEndTest.java | 4 +- .../tests/edrv2/NegotiateEdrInMemoryTest.java | 17 -- .../edc/tests/ParticipantAwareTest.java | 29 +++ .../tractusx/edc/tests/ParticipantEdrApi.java | 3 +- .../tractusx/edc/tests/TxParticipant.java | 166 ------------- .../TransferProcessHelperFunctions.java | 18 +- .../TractusxIatpParticipantBase.java | 6 +- .../TractusxParticipantBase.java | 17 +- .../participant/TransferParticipant.java | 43 ++++ .../edc/tests/runtimes/Runtimes.java} | 25 +- .../transfer/HttpConsumerPullBaseTest.java | 61 +++-- .../tests/transfer/ProviderPushBaseTest.java} | 41 ++- ...AbstractHttpConsumerPullWithProxyTest.java | 136 ---------- .../AbstractIatpConsumerPullTest.java | 88 +++++++ ...Test.java => DimHttpConsumerPullTest.java} | 58 ++--- ...HttpConsumerPullWithProxyInMemoryTest.java | 223 ----------------- .../transfer/StsHttpConsumerPullTest.java | 61 +++++ .../tests/transfer/iatp/IatpParticipant.java | 141 ----------- .../iatp/harness/DataspaceIssuer.java | 41 ++- .../iatp/harness/DidExampleResolver.java | 6 +- .../iatp/harness/IatpHelperFunctions.java | 17 +- .../iatp/harness/IatpParticipant.java | 112 +++++++++ ...eTokenService.java => StsParticipant.java} | 64 ++--- .../tests/transfer/iatp/runtime/Runtimes.java | 49 ++++ .../policy/AbstractPolicyMonitorTest.java | 120 --------- .../policy/PolicyMonitorEndToEndTest.java | 119 +++++++++ .../policy/PolicyMonitorInMemoryTest.java | 59 ----- .../policy/PolicyMonitorPostgresqlTest.java | 43 ---- ...siParticipant.java => MiwParticipant.java} | 30 ++- .../AbstractContractNegotiateTest.java | 13 +- .../SsiContractNegotiationInMemoryTest.java | 12 +- ...AbstractHttpConsumerPullWithProxyTest.java | 145 ----------- ...HttpConsumerPullWithProxyInMemoryTest.java | 36 ++- ...AbstractHttpConsumerPullWithProxyTest.java | 131 ---------- ...HttpConsumerPullWithProxyInMemoryTest.java | 62 ----- ...tpConsumerPullWithProxyPostgresqlTest.java | 45 ---- .../HttpProviderPushInMemoryTest.java | 44 ---- .../HttpProviderPushInPostgresqlTest.java | 43 ---- .../transfer/TransferPullEndToEndTest.java | 86 +++++++ .../transfer/TransferPushEndToEndTest.java | 86 +++++++ .../TransferWithTokenRefreshTest.java | 53 ++-- 50 files changed, 1162 insertions(+), 1946 deletions(-) rename edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/catalog/{DimCatalogTest.java => DimCatalogIntegrationTest.java} (98%) rename edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/{DimHttpPullTransferTest.java => DimHttpPullTransferIntegrationTest.java} (89%) delete mode 100644 edc-tests/edc-controlplane/catalog-tests/src/test/java/org/eclipse/tractusx/edc/tests/catalog/AbstractCatalogTest.java delete mode 100644 edc-tests/edc-controlplane/catalog-tests/src/test/java/org/eclipse/tractusx/edc/tests/catalog/CatalogInMemoryTest.java delete mode 100644 edc-tests/edc-controlplane/catalog-tests/src/test/java/org/eclipse/tractusx/edc/tests/catalog/CatalogPostgresqlTest.java create mode 100644 edc-tests/edc-controlplane/catalog-tests/src/test/java/org/eclipse/tractusx/edc/tests/catalog/CatalogTest.java create mode 100644 edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/ParticipantAwareTest.java delete mode 100644 edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/TxParticipant.java rename edc-tests/edc-controlplane/{transfer-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer => fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/helpers}/TransferProcessHelperFunctions.java (77%) rename edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/{ => participant}/TractusxIatpParticipantBase.java (97%) rename edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/{ => participant}/TractusxParticipantBase.java (93%) create mode 100644 edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/participant/TransferParticipant.java rename edc-tests/edc-controlplane/{iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/iatp/IatpDimParticipant.java => fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/runtimes/Runtimes.java} (57%) rename edc-tests/edc-controlplane/{transfer-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/AbstractHttpProviderPushTest.java => fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/transfer/ProviderPushBaseTest.java} (68%) delete mode 100644 edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/AbstractHttpConsumerPullWithProxyTest.java create mode 100644 edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/AbstractIatpConsumerPullTest.java rename edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/{DimHttpConsumerPullWithProxyInMemoryTest.java => DimHttpConsumerPullTest.java} (57%) delete mode 100644 edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/IatpHttpConsumerPullWithProxyInMemoryTest.java create mode 100644 edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/StsHttpConsumerPullTest.java delete mode 100644 edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/iatp/IatpParticipant.java create mode 100644 edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/iatp/harness/IatpParticipant.java rename edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/iatp/harness/{SecureTokenService.java => StsParticipant.java} (63%) create mode 100644 edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/iatp/runtime/Runtimes.java delete mode 100644 edc-tests/edc-controlplane/policy-tests/src/test/java/org/eclipse/tractusx/edc/tests/policy/AbstractPolicyMonitorTest.java create mode 100644 edc-tests/edc-controlplane/policy-tests/src/test/java/org/eclipse/tractusx/edc/tests/policy/PolicyMonitorEndToEndTest.java delete mode 100644 edc-tests/edc-controlplane/policy-tests/src/test/java/org/eclipse/tractusx/edc/tests/policy/PolicyMonitorInMemoryTest.java delete mode 100644 edc-tests/edc-controlplane/policy-tests/src/test/java/org/eclipse/tractusx/edc/tests/policy/PolicyMonitorPostgresqlTest.java rename edc-tests/edc-controlplane/ssi-summarycred-tests/src/test/java/org/eclipse/tractusx/edc/tests/{SsiParticipant.java => MiwParticipant.java} (72%) delete mode 100644 edc-tests/edc-controlplane/ssi-summarycred-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/AbstractHttpConsumerPullWithProxyTest.java delete mode 100644 edc-tests/edc-controlplane/transfer-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/AbstractHttpConsumerPullWithProxyTest.java delete mode 100644 edc-tests/edc-controlplane/transfer-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/HttpConsumerPullWithProxyInMemoryTest.java delete mode 100644 edc-tests/edc-controlplane/transfer-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/HttpConsumerPullWithProxyPostgresqlTest.java delete mode 100644 edc-tests/edc-controlplane/transfer-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/HttpProviderPushInMemoryTest.java delete mode 100644 edc-tests/edc-controlplane/transfer-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/HttpProviderPushInPostgresqlTest.java create mode 100644 edc-tests/edc-controlplane/transfer-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/TransferPullEndToEndTest.java create mode 100644 edc-tests/edc-controlplane/transfer-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/TransferPushEndToEndTest.java diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/DimParticipant.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/DimParticipant.java index 29ff7540c..348398439 100644 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/DimParticipant.java +++ b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/DimParticipant.java @@ -19,7 +19,7 @@ package org.eclipse.tractusx.edc.lifecycle; -import org.eclipse.tractusx.edc.tests.TractusxIatpParticipantBase; +import org.eclipse.tractusx.edc.tests.participant.TractusxIatpParticipantBase; import java.net.URI; import java.util.HashMap; @@ -42,7 +42,7 @@ public Map iatpConfiguration(TractusxIatpParticipantBase... othe } public static class Builder extends TractusxIatpParticipantBase.Builder { - + protected Builder() { super(new DimParticipant()); } diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/MiwParticipant.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/MiwParticipant.java index 1db4c37a5..b20aa6e08 100644 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/MiwParticipant.java +++ b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/MiwParticipant.java @@ -19,7 +19,7 @@ package org.eclipse.tractusx.edc.lifecycle; -import org.eclipse.tractusx.edc.tests.TractusxParticipantBase; +import org.eclipse.tractusx.edc.tests.participant.TractusxParticipantBase; import java.util.HashMap; import java.util.Map; @@ -29,7 +29,7 @@ * Extension of {@link TractusxParticipantBase} with MIW specific configuration */ public class MiwParticipant extends TractusxParticipantBase { - + protected String miwUri; protected String oauth2Uri; diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/catalog/DimCatalogTest.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/catalog/DimCatalogIntegrationTest.java similarity index 98% rename from edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/catalog/DimCatalogTest.java rename to edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/catalog/DimCatalogIntegrationTest.java index 1d0cb3edd..4e59c58cc 100644 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/catalog/DimCatalogTest.java +++ b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/catalog/DimCatalogIntegrationTest.java @@ -41,7 +41,7 @@ @DimIntegrationTest @Disabled -public class DimCatalogTest { +public class DimCatalogIntegrationTest { protected static final DimParticipant SOKRATES = configureParticipant(SOKRATES_NAME); protected static final DimParticipant PLATO = configureParticipant(PLATO_NAME); diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/DimHttpPullTransferTest.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/DimHttpPullTransferIntegrationTest.java similarity index 89% rename from edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/DimHttpPullTransferTest.java rename to edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/DimHttpPullTransferIntegrationTest.java index e70bc2697..2c9c80ef8 100644 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/DimHttpPullTransferTest.java +++ b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/DimHttpPullTransferIntegrationTest.java @@ -22,7 +22,7 @@ import org.eclipse.tractusx.edc.lifecycle.DimParticipant; import org.eclipse.tractusx.edc.lifecycle.ParticipantRuntime; import org.eclipse.tractusx.edc.tag.DimIntegrationTest; -import org.eclipse.tractusx.edc.tests.TractusxParticipantBase; +import org.eclipse.tractusx.edc.tests.participant.TractusxParticipantBase; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.extension.RegisterExtension; @@ -33,7 +33,7 @@ @DimIntegrationTest @Disabled -public class DimHttpPullTransferTest extends HttpConsumerPullBaseTest { +public class DimHttpPullTransferIntegrationTest extends HttpConsumerPullBaseTest { protected static final DimParticipant SOKRATES = configureParticipant(SOKRATES_NAME); protected static final DimParticipant PLATO = configureParticipant(PLATO_NAME); @@ -45,12 +45,12 @@ public class DimHttpPullTransferTest extends HttpConsumerPullBaseTest { protected static final ParticipantRuntime SOKRATES_RUNTIME = dimRuntime(SOKRATES.getName(), SOKRATES.iatpConfiguration(PLATO)); @Override - protected TractusxParticipantBase plato() { + public TractusxParticipantBase plato() { return PLATO; } @Override - protected TractusxParticipantBase sokrates() { + public TractusxParticipantBase sokrates() { return SOKRATES; } } diff --git a/edc-tests/edc-controlplane/catalog-tests/src/test/java/org/eclipse/tractusx/edc/tests/catalog/AbstractCatalogTest.java b/edc-tests/edc-controlplane/catalog-tests/src/test/java/org/eclipse/tractusx/edc/tests/catalog/AbstractCatalogTest.java deleted file mode 100644 index 063c16439..000000000 --- a/edc-tests/edc-controlplane/catalog-tests/src/test/java/org/eclipse/tractusx/edc/tests/catalog/AbstractCatalogTest.java +++ /dev/null @@ -1,205 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.tests.catalog; - - -import org.eclipse.edc.policy.model.Operator; -import org.eclipse.tractusx.edc.tests.TxParticipant; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; - -import java.util.Map; - -import static java.util.stream.IntStream.range; -import static org.assertj.core.api.Assertions.assertThat; -import static org.eclipse.edc.test.system.utils.PolicyFixtures.noConstraintPolicy; -import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.PLATO_BPN; -import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.PLATO_NAME; -import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.SOKRATES_BPN; -import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.SOKRATES_NAME; -import static org.eclipse.tractusx.edc.tests.helpers.CatalogHelperFunctions.getDatasetAssetId; -import static org.eclipse.tractusx.edc.tests.helpers.CatalogHelperFunctions.getDatasetPolicies; -import static org.eclipse.tractusx.edc.tests.helpers.PolicyHelperFunctions.BUSINESS_PARTNER_LEGACY_EVALUATION_KEY; -import static org.eclipse.tractusx.edc.tests.helpers.PolicyHelperFunctions.bnpPolicy; -import static org.eclipse.tractusx.edc.tests.helpers.PolicyHelperFunctions.bpnGroupPolicy; -import static org.eclipse.tractusx.edc.tests.helpers.PolicyHelperFunctions.frameworkPolicy; -import static org.eclipse.tractusx.edc.tests.helpers.QueryHelperFunctions.createQuery; - -public abstract class AbstractCatalogTest { - - - protected static final TxParticipant SOKRATES = TxParticipant.Builder.newInstance() - .name(SOKRATES_NAME) - .id(SOKRATES_BPN) - .build(); - - - protected static final TxParticipant PLATO = TxParticipant.Builder.newInstance() - .name(PLATO_NAME) - .id(PLATO_BPN) - .build(); - - - @Test - @DisplayName("Plato gets catalog from Sokrates. No constraints.") - void requestCatalog_fulfillsPolicy_shouldReturnOffer() { - // arrange - SOKRATES.createAsset("test-asset"); - var ap = SOKRATES.createPolicyDefinition(noConstraintPolicy()); - var cp = SOKRATES.createPolicyDefinition(noConstraintPolicy()); - SOKRATES.createContractDefinition("test-asset", "test-def", ap, cp); - - // act - var catalog = PLATO.getCatalogDatasets(SOKRATES); - - // assert - assertThat(catalog).isNotEmpty() - .hasSize(1) - .allSatisfy(co -> { - assertThat(getDatasetAssetId(co)).isEqualTo("test-asset"); - }); - - } - - @Test - @DisplayName("Verify that Plato receives only the offers he is permitted to (using the legacy BPN validation)") - void requestCatalog_filteredByBpnLegacy_shouldReject() { - var onlyPlatoPolicy = bnpPolicy("BPN1", "BPN2", PLATO.getBpn()); - var onlyDiogenesPolicy = bnpPolicy("ARISTOTELES-BPN"); - - var onlyPlatoId = SOKRATES.createPolicyDefinition(onlyPlatoPolicy); - var onlyDiogenesId = SOKRATES.createPolicyDefinition(onlyDiogenesPolicy); - var noConstraintPolicyId = SOKRATES.createPolicyDefinition(noConstraintPolicy()); - - SOKRATES.createAsset("test-asset1"); - SOKRATES.createAsset("test-asset2"); - SOKRATES.createAsset("test-asset3"); - - SOKRATES.createContractDefinition("test-asset1", "def1", noConstraintPolicyId, noConstraintPolicyId); - SOKRATES.createContractDefinition("test-asset2", "def2", onlyPlatoId, noConstraintPolicyId); - SOKRATES.createContractDefinition("test-asset3", "def3", onlyDiogenesId, noConstraintPolicyId); - - - // act - var catalog = PLATO.getCatalogDatasets(SOKRATES); - assertThat(catalog).hasSize(2); - } - - - @Test - @DisplayName("Verify that Plato receives only the offers he is permitted to (using the legacy BPN validation)") - void requestCatalog_filteredByBpnLegacy_WithNamespace_shouldReject() { - - var onlyPlatoPolicy = bnpPolicy("BPN1", "BPN2", PLATO.getBpn()); - var onlyDiogenesPolicy = frameworkPolicy(Map.of(BUSINESS_PARTNER_LEGACY_EVALUATION_KEY, "ARISTOTELES-BPN")); - - var onlyPlatoId = SOKRATES.createPolicyDefinition(onlyPlatoPolicy); - var onlyDiogenesId = SOKRATES.createPolicyDefinition(onlyDiogenesPolicy); - var noConstraintPolicyId = SOKRATES.createPolicyDefinition(noConstraintPolicy()); - - SOKRATES.createAsset("test-asset1"); - SOKRATES.createAsset("test-asset2"); - SOKRATES.createAsset("test-asset3"); - - SOKRATES.createContractDefinition("test-asset1", "def1", noConstraintPolicyId, noConstraintPolicyId); - SOKRATES.createContractDefinition("test-asset2", "def2", onlyPlatoId, noConstraintPolicyId); - SOKRATES.createContractDefinition("test-asset3", "def3", onlyDiogenesId, noConstraintPolicyId); - - - // act - var catalog = PLATO.getCatalogDatasets(SOKRATES); - assertThat(catalog).hasSize(2); - } - - @Test - @DisplayName("Verify that Plato receives only the offers he is permitted to (using the new BPN validation)") - void requestCatalog_filteredByBpn_shouldReject() { - - var mustBeGreekPhilosopher = bpnGroupPolicy(Operator.IS_ANY_OF, "greek_customer", "philosopher"); - var mustBeGreekMathematician = bpnGroupPolicy(Operator.IS_ALL_OF, "greek_customer", "mathematician"); - - - SOKRATES.storeBusinessPartner(PLATO.getBpn(), "greek_customer", "philosopher"); - var philosopherId = SOKRATES.createPolicyDefinition(mustBeGreekPhilosopher); - var mathId = SOKRATES.createPolicyDefinition(mustBeGreekMathematician); - var noConstraintPolicyId = SOKRATES.createPolicyDefinition(noConstraintPolicy()); - - SOKRATES.createAsset("test-asset1"); - SOKRATES.createAsset("test-asset2"); - SOKRATES.createAsset("test-asset3"); - - SOKRATES.createContractDefinition("test-asset1", "def1", noConstraintPolicyId, noConstraintPolicyId); - SOKRATES.createContractDefinition("test-asset2", "def2", philosopherId, noConstraintPolicyId); - SOKRATES.createContractDefinition("test-asset3", "def3", mathId, noConstraintPolicyId); - - - // act - var catalog = PLATO.getCatalogDatasets(SOKRATES); - assertThat(catalog).hasSize(2); - } - - @Test - @DisplayName("Multiple ContractDefinitions exist for one Asset") - void requestCatalog_multipleOffersForAsset() { - SOKRATES.storeBusinessPartner(PLATO.getBpn(), "test-group"); - SOKRATES.createAsset("asset-1"); - var noConstraintId = SOKRATES.createPolicyDefinition(noConstraintPolicy()); - var groupConstraintId = SOKRATES.createPolicyDefinition(bpnGroupPolicy(Operator.IS_ANY_OF, "test-group")); - - SOKRATES.createContractDefinition("asset-1", "def1", noConstraintId, noConstraintId); - SOKRATES.createContractDefinition("asset-1", "def2", groupConstraintId, noConstraintId); - - var catalog = PLATO.getCatalogDatasets(SOKRATES); - assertThat(catalog).hasSize(1) - .allSatisfy(cd -> { - assertThat(getDatasetAssetId(cd)).isEqualTo("asset-1"); - assertThat(getDatasetPolicies(cd)).hasSize(2); - }); - } - - @Test - @DisplayName("Catalog with 1000 offers") - void requestCatalog_of1000Assets_shouldContainAll() { - var policy = bpnGroupPolicy(Operator.IS_NONE_OF, "test-group1", "test-group2"); - var policyId = SOKRATES.createPolicyDefinition(policy); - var noConstraintId = SOKRATES.createPolicyDefinition(noConstraintPolicy()); - SOKRATES.storeBusinessPartner(PLATO.getBpn(), "test-group-3"); - - range(0, 1000) - .forEach(i -> { - var assetId = "asset-" + i; - SOKRATES.createAsset(assetId); - SOKRATES.createContractDefinition(assetId, "def-" + i, policyId, noConstraintId); - }); - - // request all at once - var dataset = PLATO.getCatalogDatasets(SOKRATES, createQuery(1000, 0)); - assertThat(dataset).hasSize(1000); - - // request in chunks - var o2 = PLATO.getCatalogDatasets(SOKRATES, createQuery(500, 0)); - var o3 = PLATO.getCatalogDatasets(SOKRATES, createQuery(500, 500)); - assertThat(o2).doesNotContainAnyElementsOf(o3); - - } - - -} - diff --git a/edc-tests/edc-controlplane/catalog-tests/src/test/java/org/eclipse/tractusx/edc/tests/catalog/CatalogInMemoryTest.java b/edc-tests/edc-controlplane/catalog-tests/src/test/java/org/eclipse/tractusx/edc/tests/catalog/CatalogInMemoryTest.java deleted file mode 100644 index 17e3496cd..000000000 --- a/edc-tests/edc-controlplane/catalog-tests/src/test/java/org/eclipse/tractusx/edc/tests/catalog/CatalogInMemoryTest.java +++ /dev/null @@ -1,44 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.tests.catalog; - -import org.eclipse.edc.junit.annotations.EndToEndTest; -import org.eclipse.tractusx.edc.tests.runtimes.ParticipantRuntime; -import org.junit.jupiter.api.extension.RegisterExtension; - -@EndToEndTest -public class CatalogInMemoryTest extends AbstractCatalogTest { - - @RegisterExtension - protected static final ParticipantRuntime SOKRATES_RUNTIME = new ParticipantRuntime( - ":edc-tests:runtime:runtime-memory", - SOKRATES.getName(), - SOKRATES.getBpn(), - SOKRATES.getConfiguration() - ); - - @RegisterExtension - protected static final ParticipantRuntime PLATO_RUNTIME = new ParticipantRuntime( - ":edc-tests:runtime:runtime-memory", - PLATO.getName(), - PLATO.getBpn(), - PLATO.getConfiguration() - ); -} diff --git a/edc-tests/edc-controlplane/catalog-tests/src/test/java/org/eclipse/tractusx/edc/tests/catalog/CatalogPostgresqlTest.java b/edc-tests/edc-controlplane/catalog-tests/src/test/java/org/eclipse/tractusx/edc/tests/catalog/CatalogPostgresqlTest.java deleted file mode 100644 index a7a8cb0bf..000000000 --- a/edc-tests/edc-controlplane/catalog-tests/src/test/java/org/eclipse/tractusx/edc/tests/catalog/CatalogPostgresqlTest.java +++ /dev/null @@ -1,43 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.tests.catalog; - -import org.eclipse.edc.junit.annotations.PostgresqlIntegrationTest; -import org.eclipse.tractusx.edc.tests.runtimes.PgParticipantRuntime; -import org.junit.jupiter.api.extension.RegisterExtension; - -@PostgresqlIntegrationTest -public class CatalogPostgresqlTest extends AbstractCatalogTest { - - @RegisterExtension - protected static final PgParticipantRuntime SOKRATES_RUNTIME = new PgParticipantRuntime( - ":edc-tests:runtime:runtime-postgresql", - SOKRATES.getName(), - SOKRATES.getBpn(), - SOKRATES.getConfiguration() - ); - @RegisterExtension - protected static final PgParticipantRuntime PLATO_RUNTIME = new PgParticipantRuntime( - ":edc-tests:runtime:runtime-postgresql", - PLATO.getName(), - PLATO.getBpn(), - PLATO.getConfiguration() - ); -} diff --git a/edc-tests/edc-controlplane/catalog-tests/src/test/java/org/eclipse/tractusx/edc/tests/catalog/CatalogTest.java b/edc-tests/edc-controlplane/catalog-tests/src/test/java/org/eclipse/tractusx/edc/tests/catalog/CatalogTest.java new file mode 100644 index 000000000..f2a835960 --- /dev/null +++ b/edc-tests/edc-controlplane/catalog-tests/src/test/java/org/eclipse/tractusx/edc/tests/catalog/CatalogTest.java @@ -0,0 +1,235 @@ +/******************************************************************************** + * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +package org.eclipse.tractusx.edc.tests.catalog; + +import org.eclipse.edc.junit.annotations.EndToEndTest; +import org.eclipse.edc.junit.annotations.PostgresqlIntegrationTest; +import org.eclipse.edc.policy.model.Operator; +import org.eclipse.tractusx.edc.tests.participant.TransferParticipant; +import org.eclipse.tractusx.edc.tests.runtimes.ParticipantRuntime; +import org.eclipse.tractusx.edc.tests.runtimes.PgParticipantRuntime; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import java.util.Map; + +import static java.util.stream.IntStream.range; +import static org.assertj.core.api.Assertions.assertThat; +import static org.eclipse.edc.test.system.utils.PolicyFixtures.noConstraintPolicy; +import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.PLATO_BPN; +import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.PLATO_NAME; +import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.SOKRATES_BPN; +import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.SOKRATES_NAME; +import static org.eclipse.tractusx.edc.tests.helpers.CatalogHelperFunctions.getDatasetAssetId; +import static org.eclipse.tractusx.edc.tests.helpers.CatalogHelperFunctions.getDatasetPolicies; +import static org.eclipse.tractusx.edc.tests.helpers.PolicyHelperFunctions.BUSINESS_PARTNER_LEGACY_EVALUATION_KEY; +import static org.eclipse.tractusx.edc.tests.helpers.PolicyHelperFunctions.bnpPolicy; +import static org.eclipse.tractusx.edc.tests.helpers.PolicyHelperFunctions.bpnGroupPolicy; +import static org.eclipse.tractusx.edc.tests.helpers.PolicyHelperFunctions.frameworkPolicy; +import static org.eclipse.tractusx.edc.tests.helpers.QueryHelperFunctions.createQuery; +import static org.eclipse.tractusx.edc.tests.runtimes.Runtimes.memoryRuntime; +import static org.eclipse.tractusx.edc.tests.runtimes.Runtimes.pgRuntime; + +public class CatalogTest { + + protected static final TransferParticipant SOKRATES = TransferParticipant.Builder.newInstance() + .name(SOKRATES_NAME) + .id(SOKRATES_BPN) + .build(); + + + protected static final TransferParticipant PLATO = TransferParticipant.Builder.newInstance() + .name(PLATO_NAME) + .id(PLATO_BPN) + .build(); + + + abstract static class Tests { + @Test + @DisplayName("Plato gets catalog from Sokrates. No constraints.") + void requestCatalog_fulfillsPolicy_shouldReturnOffer() { + // arrange + SOKRATES.createAsset("test-asset"); + var ap = SOKRATES.createPolicyDefinition(noConstraintPolicy()); + var cp = SOKRATES.createPolicyDefinition(noConstraintPolicy()); + SOKRATES.createContractDefinition("test-asset", "test-def", ap, cp); + + // act + var catalog = PLATO.getCatalogDatasets(SOKRATES); + + // assert + assertThat(catalog).isNotEmpty() + .hasSize(1) + .allSatisfy(co -> { + assertThat(getDatasetAssetId(co)).isEqualTo("test-asset"); + }); + + } + + @Test + @DisplayName("Verify that Plato receives only the offers he is permitted to (using the legacy BPN validation)") + void requestCatalog_filteredByBpnLegacy_shouldReject() { + var onlyPlatoPolicy = bnpPolicy("BPN1", "BPN2", PLATO.getBpn()); + var onlyDiogenesPolicy = bnpPolicy("ARISTOTELES-BPN"); + + var onlyPlatoId = SOKRATES.createPolicyDefinition(onlyPlatoPolicy); + var onlyDiogenesId = SOKRATES.createPolicyDefinition(onlyDiogenesPolicy); + var noConstraintPolicyId = SOKRATES.createPolicyDefinition(noConstraintPolicy()); + + SOKRATES.createAsset("test-asset1"); + SOKRATES.createAsset("test-asset2"); + SOKRATES.createAsset("test-asset3"); + + SOKRATES.createContractDefinition("test-asset1", "def1", noConstraintPolicyId, noConstraintPolicyId); + SOKRATES.createContractDefinition("test-asset2", "def2", onlyPlatoId, noConstraintPolicyId); + SOKRATES.createContractDefinition("test-asset3", "def3", onlyDiogenesId, noConstraintPolicyId); + + + // act + var catalog = PLATO.getCatalogDatasets(SOKRATES); + assertThat(catalog).hasSize(2); + } + + + @Test + @DisplayName("Verify that Plato receives only the offers he is permitted to (using the legacy BPN validation)") + void requestCatalog_filteredByBpnLegacy_WithNamespace_shouldReject() { + + var onlyPlatoPolicy = bnpPolicy("BPN1", "BPN2", PLATO.getBpn()); + var onlyDiogenesPolicy = frameworkPolicy(Map.of(BUSINESS_PARTNER_LEGACY_EVALUATION_KEY, "ARISTOTELES-BPN")); + + var onlyPlatoId = SOKRATES.createPolicyDefinition(onlyPlatoPolicy); + var onlyDiogenesId = SOKRATES.createPolicyDefinition(onlyDiogenesPolicy); + var noConstraintPolicyId = SOKRATES.createPolicyDefinition(noConstraintPolicy()); + + SOKRATES.createAsset("test-asset1"); + SOKRATES.createAsset("test-asset2"); + SOKRATES.createAsset("test-asset3"); + + SOKRATES.createContractDefinition("test-asset1", "def1", noConstraintPolicyId, noConstraintPolicyId); + SOKRATES.createContractDefinition("test-asset2", "def2", onlyPlatoId, noConstraintPolicyId); + SOKRATES.createContractDefinition("test-asset3", "def3", onlyDiogenesId, noConstraintPolicyId); + + + // act + var catalog = PLATO.getCatalogDatasets(SOKRATES); + assertThat(catalog).hasSize(2); + } + + @Test + @DisplayName("Verify that Plato receives only the offers he is permitted to (using the new BPN validation)") + void requestCatalog_filteredByBpn_shouldReject() { + + var mustBeGreekPhilosopher = bpnGroupPolicy(Operator.IS_ANY_OF, "greek_customer", "philosopher"); + var mustBeGreekMathematician = bpnGroupPolicy(Operator.IS_ALL_OF, "greek_customer", "mathematician"); + + + SOKRATES.storeBusinessPartner(PLATO.getBpn(), "greek_customer", "philosopher"); + var philosopherId = SOKRATES.createPolicyDefinition(mustBeGreekPhilosopher); + var mathId = SOKRATES.createPolicyDefinition(mustBeGreekMathematician); + var noConstraintPolicyId = SOKRATES.createPolicyDefinition(noConstraintPolicy()); + + SOKRATES.createAsset("test-asset1"); + SOKRATES.createAsset("test-asset2"); + SOKRATES.createAsset("test-asset3"); + + SOKRATES.createContractDefinition("test-asset1", "def1", noConstraintPolicyId, noConstraintPolicyId); + SOKRATES.createContractDefinition("test-asset2", "def2", philosopherId, noConstraintPolicyId); + SOKRATES.createContractDefinition("test-asset3", "def3", mathId, noConstraintPolicyId); + + + // act + var catalog = PLATO.getCatalogDatasets(SOKRATES); + assertThat(catalog).hasSize(2); + } + + @Test + @DisplayName("Multiple ContractDefinitions exist for one Asset") + void requestCatalog_multipleOffersForAsset() { + SOKRATES.storeBusinessPartner(PLATO.getBpn(), "test-group"); + SOKRATES.createAsset("asset-1"); + var noConstraintId = SOKRATES.createPolicyDefinition(noConstraintPolicy()); + var groupConstraintId = SOKRATES.createPolicyDefinition(bpnGroupPolicy(Operator.IS_ANY_OF, "test-group")); + + SOKRATES.createContractDefinition("asset-1", "def1", noConstraintId, noConstraintId); + SOKRATES.createContractDefinition("asset-1", "def2", groupConstraintId, noConstraintId); + + var catalog = PLATO.getCatalogDatasets(SOKRATES); + assertThat(catalog).hasSize(1) + .allSatisfy(cd -> { + assertThat(getDatasetAssetId(cd)).isEqualTo("asset-1"); + assertThat(getDatasetPolicies(cd)).hasSize(2); + }); + } + + @Test + @DisplayName("Catalog with 1000 offers") + void requestCatalog_of1000Assets_shouldContainAll() { + var policy = bpnGroupPolicy(Operator.IS_NONE_OF, "test-group1", "test-group2"); + var policyId = SOKRATES.createPolicyDefinition(policy); + var noConstraintId = SOKRATES.createPolicyDefinition(noConstraintPolicy()); + SOKRATES.storeBusinessPartner(PLATO.getBpn(), "test-group-3"); + + range(0, 1000) + .forEach(i -> { + var assetId = "asset-" + i; + SOKRATES.createAsset(assetId); + SOKRATES.createContractDefinition(assetId, "def-" + i, policyId, noConstraintId); + }); + + // request all at once + var dataset = PLATO.getCatalogDatasets(SOKRATES, createQuery(1000, 0)); + assertThat(dataset).hasSize(1000); + + // request in chunks + var o2 = PLATO.getCatalogDatasets(SOKRATES, createQuery(500, 0)); + var o3 = PLATO.getCatalogDatasets(SOKRATES, createQuery(500, 500)); + assertThat(o2).doesNotContainAnyElementsOf(o3); + + } + } + + @Nested + @EndToEndTest + class InMemory extends Tests { + + @RegisterExtension + protected static final ParticipantRuntime SOKRATES_RUNTIME = memoryRuntime(SOKRATES.getName(), SOKRATES.getBpn(), SOKRATES.getConfiguration()); + + @RegisterExtension + protected static final ParticipantRuntime PLATO_RUNTIME = memoryRuntime(PLATO.getName(), PLATO.getBpn(), PLATO.getConfiguration()); + + } + + @Nested + @PostgresqlIntegrationTest + class Postgres extends Tests { + + @RegisterExtension + protected static final PgParticipantRuntime SOKRATES_RUNTIME = pgRuntime(SOKRATES.getName(), SOKRATES.getBpn(), SOKRATES.getConfiguration()); + + @RegisterExtension + protected static final PgParticipantRuntime PLATO_RUNTIME = pgRuntime(PLATO.getName(), PLATO.getBpn(), PLATO.getConfiguration()); + + } + +} diff --git a/edc-tests/edc-controlplane/edr-api-tests/src/test/java/org/eclipse/tractusx/edc/tests/edrv2/AbstractNegotiateEdrTest.java b/edc-tests/edc-controlplane/edr-api-tests/src/test/java/org/eclipse/tractusx/edc/tests/edrv2/AbstractNegotiateEdrTest.java index 824c2f891..6e355b2ba 100644 --- a/edc-tests/edc-controlplane/edr-api-tests/src/test/java/org/eclipse/tractusx/edc/tests/edrv2/AbstractNegotiateEdrTest.java +++ b/edc-tests/edc-controlplane/edr-api-tests/src/test/java/org/eclipse/tractusx/edc/tests/edrv2/AbstractNegotiateEdrTest.java @@ -33,9 +33,9 @@ import org.eclipse.edc.connector.transfer.spi.event.TransferProcessStarted; import org.eclipse.edc.policy.model.Operator; import org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration; -import org.eclipse.tractusx.edc.tests.TxParticipant; import org.eclipse.tractusx.edc.tests.helpers.EdrNegotiationHelperFunctions; import org.eclipse.tractusx.edc.tests.helpers.PolicyHelperFunctions; +import org.eclipse.tractusx.edc.tests.participant.TransferParticipant; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; @@ -49,19 +49,19 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.awaitility.Awaitility.await; -import static org.eclipse.tractusx.edc.tests.TxParticipant.ASYNC_POLL_INTERVAL; -import static org.eclipse.tractusx.edc.tests.TxParticipant.ASYNC_TIMEOUT; import static org.eclipse.tractusx.edc.tests.helpers.EdrNegotiationHelperFunctions.createEvent; import static org.eclipse.tractusx.edc.tests.helpers.Functions.waitForEvent; +import static org.eclipse.tractusx.edc.tests.participant.TractusxParticipantBase.ASYNC_POLL_INTERVAL; +import static org.eclipse.tractusx.edc.tests.participant.TractusxParticipantBase.ASYNC_TIMEOUT; public abstract class AbstractNegotiateEdrTest { - protected static final TxParticipant SOKRATES = TxParticipant.Builder.newInstance() + protected static final TransferParticipant SOKRATES = TransferParticipant.Builder.newInstance() .name(TestRuntimeConfiguration.SOKRATES_NAME) .id(TestRuntimeConfiguration.SOKRATES_BPN) .build(); - protected static final TxParticipant PLATO = TxParticipant.Builder.newInstance() + protected static final TransferParticipant PLATO = TransferParticipant.Builder.newInstance() .name(TestRuntimeConfiguration.PLATO_NAME) .id(TestRuntimeConfiguration.PLATO_BPN) .build(); diff --git a/edc-tests/edc-controlplane/edr-api-tests/src/test/java/org/eclipse/tractusx/edc/tests/edrv2/EdrCacheApiEndToEndTest.java b/edc-tests/edc-controlplane/edr-api-tests/src/test/java/org/eclipse/tractusx/edc/tests/edrv2/EdrCacheApiEndToEndTest.java index 74486302e..b9a760e17 100644 --- a/edc-tests/edc-controlplane/edr-api-tests/src/test/java/org/eclipse/tractusx/edc/tests/edrv2/EdrCacheApiEndToEndTest.java +++ b/edc-tests/edc-controlplane/edr-api-tests/src/test/java/org/eclipse/tractusx/edc/tests/edrv2/EdrCacheApiEndToEndTest.java @@ -37,7 +37,7 @@ import org.eclipse.edc.junit.annotations.EndToEndTest; import org.eclipse.edc.spi.types.domain.DataAddress; import org.eclipse.tractusx.edc.spi.tokenrefresh.dataplane.model.TokenResponse; -import org.eclipse.tractusx.edc.tests.TxParticipant; +import org.eclipse.tractusx.edc.tests.participant.TransferParticipant; import org.eclipse.tractusx.edc.tests.runtimes.ParticipantRuntime; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; @@ -73,7 +73,7 @@ */ @EndToEndTest public class EdrCacheApiEndToEndTest { - protected static final TxParticipant SOKRATES = TxParticipant.Builder.newInstance() + protected static final TransferParticipant SOKRATES = TransferParticipant.Builder.newInstance() .name("sokrates") .id("BPN00001") .build(); diff --git a/edc-tests/edc-controlplane/edr-api-tests/src/test/java/org/eclipse/tractusx/edc/tests/edrv2/NegotiateEdrInMemoryTest.java b/edc-tests/edc-controlplane/edr-api-tests/src/test/java/org/eclipse/tractusx/edc/tests/edrv2/NegotiateEdrInMemoryTest.java index 974969b0f..dd25e45e1 100644 --- a/edc-tests/edc-controlplane/edr-api-tests/src/test/java/org/eclipse/tractusx/edc/tests/edrv2/NegotiateEdrInMemoryTest.java +++ b/edc-tests/edc-controlplane/edr-api-tests/src/test/java/org/eclipse/tractusx/edc/tests/edrv2/NegotiateEdrInMemoryTest.java @@ -20,15 +20,10 @@ package org.eclipse.tractusx.edc.tests.edrv2; -import com.nimbusds.jose.util.Base64; import org.eclipse.edc.junit.annotations.EndToEndTest; -import org.eclipse.edc.spi.security.Vault; import org.eclipse.tractusx.edc.tests.runtimes.ParticipantRuntime; -import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.extension.RegisterExtension; -import java.security.SecureRandom; - @EndToEndTest public class NegotiateEdrInMemoryTest extends AbstractNegotiateEdrTest { @@ -48,16 +43,4 @@ public class NegotiateEdrInMemoryTest extends AbstractNegotiateEdrTest { PLATO.getConfiguration() ); - @BeforeAll - static void prepare() { - var bytes = new byte[32]; - - new SecureRandom().nextBytes(bytes); - var value = Base64.encode(bytes).toString(); - var vault = SOKRATES_RUNTIME.getContext().getService(Vault.class); - vault.storeSecret("test-alias", value); - vault = PLATO_RUNTIME.getContext().getService(Vault.class); - vault.storeSecret("test-alias", value); - - } } diff --git a/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/ParticipantAwareTest.java b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/ParticipantAwareTest.java new file mode 100644 index 000000000..26cddc343 --- /dev/null +++ b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/ParticipantAwareTest.java @@ -0,0 +1,29 @@ +/******************************************************************************** + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +package org.eclipse.tractusx.edc.tests; + +import org.eclipse.tractusx.edc.tests.participant.TractusxParticipantBase; + +public interface ParticipantAwareTest { + + TractusxParticipantBase plato(); + + TractusxParticipantBase sokrates(); +} diff --git a/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/ParticipantEdrApi.java b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/ParticipantEdrApi.java index 443dd8967..fccc1bb0d 100644 --- a/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/ParticipantEdrApi.java +++ b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/ParticipantEdrApi.java @@ -25,6 +25,7 @@ import jakarta.json.JsonArray; import jakarta.json.JsonObject; import org.eclipse.edc.test.system.utils.Participant; +import org.eclipse.tractusx.edc.tests.participant.TransferParticipant; import static io.restassured.http.ContentType.JSON; import static jakarta.json.Json.createObjectBuilder; @@ -109,7 +110,7 @@ public ValidatableResponse refreshEdr(String transferProcessId) { * @param callbacks The callbacks * @return The contract negotiation id */ - public String negotiateEdr(TxParticipant other, String assetId, JsonArray callbacks) { + public String negotiateEdr(TransferParticipant other, String assetId, JsonArray callbacks) { var dataset = participant.getDatasetForAsset(other, assetId); assertThat(dataset).withFailMessage("Catalog received from " + other.getName() + " was empty!").isNotEmpty(); diff --git a/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/TxParticipant.java b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/TxParticipant.java deleted file mode 100644 index b17fb24ac..000000000 --- a/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/TxParticipant.java +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -package org.eclipse.tractusx.edc.tests; - -import com.fasterxml.jackson.annotation.JsonCreator; -import jakarta.json.Json; -import org.eclipse.edc.test.system.utils.Participant; -import org.jetbrains.annotations.NotNull; - -import java.net.URI; -import java.time.Duration; -import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; - -import static io.restassured.http.ContentType.JSON; -import static jakarta.json.Json.createObjectBuilder; -import static java.time.Duration.ofSeconds; -import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.ID; -import static org.eclipse.edc.util.io.Ports.getFreePort; -import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.TX_NAMESPACE; - -public class TxParticipant extends IdentityParticipant { - public static final String API_KEY = "testkey"; - public static final Duration ASYNC_TIMEOUT = ofSeconds(60); - public static final Duration ASYNC_POLL_INTERVAL = ofSeconds(1); - - private final URI controlPlaneDefault = URI.create("http://localhost:" + getFreePort()); - private final URI controlPlaneControl = URI.create("http://localhost:" + getFreePort() + "/control"); - private final URI backendProviderProxy = URI.create("http://localhost:" + getFreePort() + "/events"); - private final URI dataPlaneProxy = URI.create("http://localhost:" + getFreePort()); - private final URI dataPlanePublic = URI.create("http://localhost:" + getFreePort() + "/public"); - - private ParticipantEdrApi edrs; - private ParticipantDataApi data; - - public void createAsset(String id) { - createAsset(id, new HashMap<>(), Map.of("type", "test-type")); - } - - public String getBpn() { - return getId(); - } - - /** - * Returns the base configuration - */ - public Map getConfiguration() { - return new HashMap<>() { - { - put("edc.connector.name", name); - put("edc.participant.id", id); - put("web.http.port", String.valueOf(controlPlaneDefault.getPort())); - put("web.http.path", "/api"); - put("web.http.protocol.port", String.valueOf(protocolEndpoint.getUrl().getPort())); - put("web.http.protocol.path", protocolEndpoint.getUrl().getPath()); - put("web.http.management.port", String.valueOf(managementEndpoint.getUrl().getPort())); - put("web.http.management.path", managementEndpoint.getUrl().getPath()); - put("web.http.control.port", String.valueOf(controlPlaneControl.getPort())); - put("web.http.control.path", controlPlaneControl.getPath()); - put("edc.dsp.callback.address", protocolEndpoint.getUrl().toString()); - put("edc.api.auth.key", "testkey"); - put("web.http.public.path", "/api/public"); - put("web.http.public.port", String.valueOf(dataPlanePublic.getPort())); - put("edc.transfer.proxy.token.signer.privatekey.alias", getPrivateKeyAlias()); - put("edc.transfer.proxy.token.verifier.publickey.alias", getFullKeyId()); - put("edc.transfer.send.retry.limit", "1"); - put("edc.transfer.send.retry.base-delay.ms", "100"); - put("tx.dpf.consumer.proxy.port", String.valueOf(dataPlaneProxy.getPort())); - put("edc.dataplane.token.validation.endpoint", controlPlaneControl + "/token"); - put("edc.dataplane.selector.httpplane.url", controlPlaneControl.toString()); - put("edc.dataplane.selector.httpplane.sourcetypes", "HttpData"); - put("edc.dataplane.selector.httpplane.destinationtypes", "HttpProxy"); - put("edc.dataplane.selector.httpplane.transfertypes", "HttpProxy-PULL"); - put("edc.dataplane.selector.httpplane.properties", "{\"publicApiUrl\":\"http://localhost:" + dataPlanePublic.getPort() + "/api/public/v2\"}"); - put("edc.receiver.http.dynamic.endpoint", "http://localhost:" + controlPlaneDefault.getPort() + "/api/consumer/datareference"); - put("tractusx.businesspartnervalidation.log.agreement.validation", "true"); - put("edc.agent.identity.key", "BusinessPartnerNumber"); - put("edc.data.encryption.keys.alias", "test-alias"); - put("tx.dpf.proxy.gateway.aas.proxied.path", backendProviderProxy.toString()); - put("tx.dpf.proxy.gateway.aas.authorization.type", "none"); - put("edc.iam.issuer.id", getDid()); - put("edc.dataplane.api.public.baseurl", "http://localhost:%d/api/public/v2/data".formatted(dataPlanePublic.getPort())); - } - }; - } - - public ParticipantEdrApi edrs() { - return edrs; - } - - /** - * Returns the client API for fetching data - */ - public ParticipantDataApi data() { - return data; - } - - /** - * Stores BPN groups - */ - public void storeBusinessPartner(String bpn, String... groups) { - var body = createObjectBuilder() - .add(ID, bpn) - .add(TX_NAMESPACE + "groups", Json.createArrayBuilder(Arrays.asList(groups))) - .build(); - managementEndpoint.baseRequest() - .contentType(JSON) - .body(body) - .when() - .post("/business-partner-groups") - .then() - .statusCode(204); - } - - @Override - public String getFullKeyId() { - return getDid() + "#" + getKeyId(); - } - - @NotNull - private String getDid() { - return "did:web:" + name.toLowerCase(); - } - - public static final class Builder extends Participant.Builder { - - private Builder() { - super(new TxParticipant()); - } - - @JsonCreator - public static Builder newInstance() { - return new Builder(); - } - - @Override - public TxParticipant build() { - super.managementEndpoint(new Endpoint(URI.create("http://localhost:" + getFreePort() + "/api/management"), Map.of("x-api-key", API_KEY))); - super.protocolEndpoint(new Endpoint(URI.create("http://localhost:" + getFreePort() + "/protocol"))); - super.timeout(ASYNC_TIMEOUT); - super.build(); - - this.participant.edrs = new ParticipantEdrApi(participant); - this.participant.data = new ParticipantDataApi(); - return participant; - } - } -} diff --git a/edc-tests/edc-controlplane/transfer-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/TransferProcessHelperFunctions.java b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/helpers/TransferProcessHelperFunctions.java similarity index 77% rename from edc-tests/edc-controlplane/transfer-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/TransferProcessHelperFunctions.java rename to edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/helpers/TransferProcessHelperFunctions.java index da83d3143..73d1a44c7 100644 --- a/edc-tests/edc-controlplane/transfer-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/TransferProcessHelperFunctions.java +++ b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/helpers/TransferProcessHelperFunctions.java @@ -1,5 +1,5 @@ /******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) * * See the NOTICE file(s) distributed with this work for additional * information regarding copyright ownership. @@ -17,11 +17,12 @@ * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ -package org.eclipse.tractusx.edc.tests.transfer; +package org.eclipse.tractusx.edc.tests.helpers; import jakarta.json.Json; import jakarta.json.JsonObject; +import static jakarta.json.Json.createObjectBuilder; import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.ID; import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.TYPE; import static org.eclipse.edc.spi.CoreConstants.EDC_NAMESPACE; @@ -43,12 +44,21 @@ public static JsonObject createTransferRequest(String dataRequestId, String coun } - public static JsonObject createProxyRequest() { return Json.createObjectBuilder() .add(TYPE, EDC_NAMESPACE + "DataAddress") - .add(EDC_NAMESPACE + "type", "HttpProxy-PULL") + .add(EDC_NAMESPACE + "type", "HttpProxy") .build(); } + + public static JsonObject httpDataAddress(String baseUrl) { + return createObjectBuilder() + .add(TYPE, EDC_NAMESPACE + "DataAddress") + .add(EDC_NAMESPACE + "type", "HttpData") + .add(EDC_NAMESPACE + "properties", createObjectBuilder() + .add(EDC_NAMESPACE + "baseUrl", baseUrl) + .build()) + .build(); + } } diff --git a/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/TractusxIatpParticipantBase.java b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/participant/TractusxIatpParticipantBase.java similarity index 97% rename from edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/TractusxIatpParticipantBase.java rename to edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/participant/TractusxIatpParticipantBase.java index fada1c3de..175a8fa2a 100644 --- a/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/TractusxIatpParticipantBase.java +++ b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/participant/TractusxIatpParticipantBase.java @@ -1,5 +1,5 @@ /******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) * * See the NOTICE file(s) distributed with this work for additional * information regarding copyright ownership. @@ -17,7 +17,7 @@ * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ -package org.eclipse.tractusx.edc.tests; +package org.eclipse.tractusx.edc.tests.participant; import java.net.URI; import java.util.Arrays; @@ -86,7 +86,7 @@ public B trustedIssuer(String trustedIssuer) { participant.trustedIssuer = trustedIssuer; return self(); } - + @Override public TractusxIatpParticipantBase build() { super.build(); diff --git a/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/TractusxParticipantBase.java b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/participant/TractusxParticipantBase.java similarity index 93% rename from edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/TractusxParticipantBase.java rename to edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/participant/TractusxParticipantBase.java index cd8d8fe78..c8e3baae9 100644 --- a/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/TractusxParticipantBase.java +++ b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/participant/TractusxParticipantBase.java @@ -1,5 +1,5 @@ -/* - * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft +/******************************************************************************** + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) * * See the NOTICE file(s) distributed with this work for additional * information regarding copyright ownership. @@ -15,12 +15,15 @@ * under the License. * * SPDX-License-Identifier: Apache-2.0 - */ + ********************************************************************************/ -package org.eclipse.tractusx.edc.tests; +package org.eclipse.tractusx.edc.tests.participant; import jakarta.json.Json; import org.eclipse.edc.test.system.utils.Participant; +import org.eclipse.tractusx.edc.tests.IdentityParticipant; +import org.eclipse.tractusx.edc.tests.ParticipantDataApi; +import org.eclipse.tractusx.edc.tests.ParticipantEdrApi; import org.jetbrains.annotations.NotNull; import java.net.URI; @@ -37,12 +40,13 @@ import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.TX_NAMESPACE; /** - * Base class for doing E2E tests with participants. It will replace {@link TxParticipant} + * Base class for doing E2E tests with participants. */ public abstract class TractusxParticipantBase extends IdentityParticipant { public static final String API_KEY = "testkey"; public static final Duration ASYNC_TIMEOUT = ofSeconds(60); + public static final Duration ASYNC_POLL_INTERVAL = ofSeconds(1); private final URI controlPlaneDefault = URI.create("http://localhost:" + getFreePort()); private final URI controlPlaneControl = URI.create("http://localhost:" + getFreePort() + "/control"); private final URI backendProviderProxy = URI.create("http://localhost:" + getFreePort() + "/events"); @@ -95,7 +99,6 @@ public Map getConfiguration() { put("edc.receiver.http.dynamic.endpoint", "http://localhost:" + controlPlaneDefault.getPort() + "/api/consumer/datareference"); put("tractusx.businesspartnervalidation.log.agreement.validation", "true"); put("edc.agent.identity.key", "BusinessPartnerNumber"); - put("edc.data.encryption.keys.alias", "test-alias"); put("tx.dpf.proxy.gateway.aas.proxied.path", backendProviderProxy.toString()); put("tx.dpf.proxy.gateway.aas.authorization.type", "none"); put("edc.iam.issuer.id", getDid()); @@ -144,7 +147,7 @@ public String getFullKeyId() { public String getDid() { return did; } - + public static class Builder

    > extends Participant.Builder { protected Builder(P participant) { diff --git a/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/participant/TransferParticipant.java b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/participant/TransferParticipant.java new file mode 100644 index 000000000..725d018f1 --- /dev/null +++ b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/participant/TransferParticipant.java @@ -0,0 +1,43 @@ +/******************************************************************************** + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +package org.eclipse.tractusx.edc.tests.participant; + +/** + * Extension of {@link TractusxParticipantBase} with Transfer specific configuration + */ +public class TransferParticipant extends TractusxParticipantBase { + + public static class Builder extends TractusxParticipantBase.Builder { + + protected Builder() { + super(new TransferParticipant()); + } + + public static Builder newInstance() { + return new Builder(); + } + + @Override + public TransferParticipant build() { + super.build(); + return participant; + } + } +} diff --git a/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/iatp/IatpDimParticipant.java b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/runtimes/Runtimes.java similarity index 57% rename from edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/iatp/IatpDimParticipant.java rename to edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/runtimes/Runtimes.java index 28bebf2ec..79aaf0057 100644 --- a/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/iatp/IatpDimParticipant.java +++ b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/runtimes/Runtimes.java @@ -17,30 +17,17 @@ * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ -package org.eclipse.tractusx.edc.tests.transfer.iatp; +package org.eclipse.tractusx.edc.tests.runtimes; - -import org.eclipse.tractusx.edc.tests.TxParticipant; - -import java.net.URI; -import java.util.HashMap; import java.util.Map; -/** - * Extension of {@link IatpParticipant} with DIM specific configuration - */ -public class IatpDimParticipant extends IatpParticipant { - private final URI dimUri; +public interface Runtimes { - public IatpDimParticipant(TxParticipant participant, URI stsUri, URI dimUri) { - super(participant, stsUri); - this.dimUri = dimUri; + static ParticipantRuntime memoryRuntime(String runtimeName, String bpn, Map properties) { + return new ParticipantRuntime(":edc-tests:runtime:runtime-memory", runtimeName, bpn, properties); } - @Override - public Map iatpConfiguration(TxParticipant... others) { - var config = new HashMap<>(super.iatpConfiguration(others)); - config.put("edc.iam.sts.dim.url", dimUri.toString()); - return config; + static PgParticipantRuntime pgRuntime(String runtimeName, String bpn, Map properties) { + return new PgParticipantRuntime(":edc-tests:runtime:runtime-postgresql", runtimeName, bpn, properties); } } diff --git a/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/transfer/HttpConsumerPullBaseTest.java b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/transfer/HttpConsumerPullBaseTest.java index ea6383b23..c32af6cb9 100644 --- a/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/transfer/HttpConsumerPullBaseTest.java +++ b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/transfer/HttpConsumerPullBaseTest.java @@ -21,55 +21,52 @@ import jakarta.json.Json; import jakarta.json.JsonObject; -import okhttp3.mockwebserver.MockResponse; -import okhttp3.mockwebserver.MockWebServer; import org.eclipse.edc.connector.transfer.spi.types.TransferProcessStates; -import org.eclipse.tractusx.edc.tests.TractusxParticipantBase; +import org.eclipse.tractusx.edc.tests.ParticipantAwareTest; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.mockserver.integration.ClientAndServer; +import org.mockserver.verify.VerificationTimes; -import java.io.IOException; import java.util.Map; import java.util.concurrent.atomic.AtomicReference; import static org.assertj.core.api.Assertions.assertThat; import static org.awaitility.Awaitility.await; import static org.awaitility.pollinterval.FibonacciPollInterval.fibonacci; -import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.TYPE; -import static org.eclipse.edc.spi.CoreConstants.EDC_NAMESPACE; -import static org.eclipse.tractusx.edc.tests.TxParticipant.ASYNC_TIMEOUT; +import static org.eclipse.edc.util.io.Ports.getFreePort; import static org.eclipse.tractusx.edc.tests.helpers.PolicyHelperFunctions.bnpPolicy; +import static org.eclipse.tractusx.edc.tests.helpers.TransferProcessHelperFunctions.createProxyRequest; +import static org.eclipse.tractusx.edc.tests.participant.TractusxParticipantBase.ASYNC_TIMEOUT; +import static org.mockserver.model.HttpRequest.request; +import static org.mockserver.model.HttpResponse.response; /** * Base tests for Http PULL scenario */ -public abstract class HttpConsumerPullBaseTest { +public abstract class HttpConsumerPullBaseTest implements ParticipantAwareTest { - protected MockWebServer server; + public static final String MOCK_BACKEND_REMOTE_HOST = "localhost"; + public static final String MOCK_BACKEND_PATH = "/mock/api"; + protected ClientAndServer server; - public static JsonObject createProxyRequest() { - return Json.createObjectBuilder() - .add(TYPE, EDC_NAMESPACE + "DataAddress") - .add(EDC_NAMESPACE + "type", "HttpProxy-PULL") - .build(); + private String privateBackendUrl; - } @BeforeEach void setup() { - server = new MockWebServer(); + server = ClientAndServer.startClientAndServer(MOCK_BACKEND_REMOTE_HOST, getFreePort()); + privateBackendUrl = "http://%s:%d%s".formatted(MOCK_BACKEND_REMOTE_HOST, server.getPort(), MOCK_BACKEND_PATH); } @Test - void transferData_privateBackend() throws IOException, InterruptedException { + void transferData_privateBackend() { var assetId = "api-asset-1"; - var url = server.url("/mock/api"); - server.start(); Map dataAddress = Map.of( - "baseUrl", url.toString(), + "baseUrl", privateBackendUrl, "type", "HttpData", "contentType", "application/json" ); @@ -79,9 +76,8 @@ void transferData_privateBackend() throws IOException, InterruptedException { var accessPolicyId = plato().createPolicyDefinition(createAccessPolicy(sokrates().getBpn())); var contractPolicyId = plato().createPolicyDefinition(createContractPolicy(sokrates().getBpn())); plato().createContractDefinition(assetId, "def-1", accessPolicyId, contractPolicyId); - var transferProcessId = sokrates().requestAsset(plato(), assetId, Json.createObjectBuilder().build(), createProxyRequest()); + var transferProcessId = sokrates().requestAsset(plato(), assetId, Json.createObjectBuilder().build(), createProxyRequest(), "HttpData-PULL"); - var contractAgreementId = new AtomicReference(); var edr = new AtomicReference(); // wait until transfer process completes @@ -93,7 +89,7 @@ void transferData_privateBackend() throws IOException, InterruptedException { }); // wait until EDC is available on the consumer side - server.enqueue(new MockResponse().setBody("test response").setResponseCode(200)); + server.when(request().withMethod("GET").withPath(MOCK_BACKEND_PATH)).respond(response().withStatusCode(200).withBody("test response")); await().pollInterval(fibonacci()) .atMost(ASYNC_TIMEOUT) .untilAsserted(() -> { @@ -104,21 +100,20 @@ void transferData_privateBackend() throws IOException, InterruptedException { // pull data out of provider's backend service: // Prov-DP -> Prov-backend assertThat(sokrates().data().pullData(edr.get(), Map.of())).isEqualTo("test response"); - var rq = server.takeRequest(); - assertThat(rq.getHeader("Edc-Contract-Agreement-Id")).isNotNull(); - assertThat(rq.getHeader("Edc-Bpn")).isEqualTo(sokrates().getBpn()); - assertThat(rq.getMethod()).isEqualToIgnoringCase("GET"); + + server.verify(request() + .withPath(MOCK_BACKEND_PATH) + .withHeader("Edc-Contract-Agreement-Id") + .withHeader("Edc-Bpn", sokrates().getBpn()) + .withMethod("GET"), VerificationTimes.exactly(1)); + } @AfterEach - void teardown() throws IOException { - server.shutdown(); + void teardown() { + server.stop(); } - protected abstract TractusxParticipantBase plato(); - - protected abstract TractusxParticipantBase sokrates(); - protected JsonObject createAccessPolicy(String bpn) { return bnpPolicy(bpn); } diff --git a/edc-tests/edc-controlplane/transfer-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/AbstractHttpProviderPushTest.java b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/transfer/ProviderPushBaseTest.java similarity index 68% rename from edc-tests/edc-controlplane/transfer-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/AbstractHttpProviderPushTest.java rename to edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/transfer/ProviderPushBaseTest.java index bb6e51c46..90b2b41fc 100644 --- a/edc-tests/edc-controlplane/transfer-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/AbstractHttpProviderPushTest.java +++ b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/transfer/ProviderPushBaseTest.java @@ -1,5 +1,5 @@ /******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) * * See the NOTICE file(s) distributed with this work for additional * information regarding copyright ownership. @@ -20,7 +20,7 @@ package org.eclipse.tractusx.edc.tests.transfer; import jakarta.json.JsonObject; -import org.eclipse.tractusx.edc.tests.TxParticipant; +import org.eclipse.tractusx.edc.tests.ParticipantAwareTest; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -37,39 +37,30 @@ import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.TYPE; import static org.eclipse.edc.spi.CoreConstants.EDC_NAMESPACE; import static org.eclipse.edc.util.io.Ports.getFreePort; -import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.PLATO_BPN; -import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.PLATO_NAME; -import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.SOKRATES_BPN; -import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.SOKRATES_NAME; -import static org.eclipse.tractusx.edc.tests.TxParticipant.ASYNC_TIMEOUT; import static org.eclipse.tractusx.edc.tests.helpers.PolicyHelperFunctions.bnpPolicy; +import static org.eclipse.tractusx.edc.tests.participant.TractusxParticipantBase.ASYNC_TIMEOUT; import static org.mockserver.model.HttpRequest.request; -public abstract class AbstractHttpProviderPushTest { - public static final String MOCK_BACKEND_REMOTEHOST = "localhost"; - protected static final TxParticipant SOKRATES = TxParticipant.Builder.newInstance() - .name(SOKRATES_NAME) - .id(SOKRATES_BPN) - .build(); +/** + * Base tests for Provider PUSH scenario + */ +public abstract class ProviderPushBaseTest implements ParticipantAwareTest { - protected static final TxParticipant PLATO = TxParticipant.Builder.newInstance() - .name(PLATO_NAME) - .id(PLATO_BPN) - .build(); + public static final String MOCK_BACKEND_REMOTE_HOST = "localhost"; private ClientAndServer server; @BeforeEach void setup() { - server = ClientAndServer.startClientAndServer(MOCK_BACKEND_REMOTEHOST, getFreePort()); + server = ClientAndServer.startClientAndServer(MOCK_BACKEND_REMOTE_HOST, getFreePort()); } @Test void httpPushDataTransfer() { var assetId = UUID.randomUUID().toString(); - var providerUrl = "http://%s:%d%s".formatted(MOCK_BACKEND_REMOTEHOST, server.getPort(), "/mock/api/provider"); - var consumerUrl = "http://%s:%d%s".formatted(MOCK_BACKEND_REMOTEHOST, server.getPort(), "/mock/api/consumer"); + var providerUrl = "http://%s:%d%s".formatted(MOCK_BACKEND_REMOTE_HOST, server.getPort(), "/mock/api/provider"); + var consumerUrl = "http://%s:%d%s".formatted(MOCK_BACKEND_REMOTE_HOST, server.getPort(), "/mock/api/consumer"); server.when(request().withPath("/mock/api/provider")) .respond(HttpResponse.response().withStatusCode(200)); @@ -83,15 +74,15 @@ void httpPushDataTransfer() { "contentType", "application/json" ); - PLATO.createAsset(assetId, Map.of(), dataAddress); - var policyId = PLATO.createPolicyDefinition(bnpPolicy(SOKRATES.getBpn())); - PLATO.createContractDefinition(assetId, "def-1", policyId, policyId); + plato().createAsset(assetId, Map.of(), dataAddress); + var policyId = plato().createPolicyDefinition(bnpPolicy(sokrates().getBpn())); + plato().createContractDefinition(assetId, "def-1", policyId, policyId); var destination = httpDataAddress(consumerUrl); - var transferProcessId = SOKRATES.requestAsset(PLATO, assetId, createObjectBuilder().build(), destination, "HttpData-PUSH"); + var transferProcessId = sokrates().requestAsset(plato(), assetId, createObjectBuilder().build(), destination, "HttpData-PUSH"); await().atMost(ASYNC_TIMEOUT).untilAsserted(() -> { - var state = SOKRATES.getTransferProcessState(transferProcessId); + var state = sokrates().getTransferProcessState(transferProcessId); assertThat(state).isEqualTo(COMPLETED.name()); }); } diff --git a/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/AbstractHttpConsumerPullWithProxyTest.java b/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/AbstractHttpConsumerPullWithProxyTest.java deleted file mode 100644 index d6e53441d..000000000 --- a/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/AbstractHttpConsumerPullWithProxyTest.java +++ /dev/null @@ -1,136 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.tests.transfer; - -import jakarta.json.Json; -import jakarta.json.JsonObject; -import okhttp3.mockwebserver.MockResponse; -import okhttp3.mockwebserver.MockWebServer; -import org.eclipse.edc.connector.transfer.spi.types.TransferProcessStates; -import org.eclipse.tractusx.edc.tests.TxParticipant; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import java.io.IOException; -import java.util.Map; -import java.util.concurrent.atomic.AtomicReference; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.awaitility.Awaitility.await; -import static org.awaitility.pollinterval.FibonacciPollInterval.fibonacci; -import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.TYPE; -import static org.eclipse.edc.spi.CoreConstants.EDC_NAMESPACE; -import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.PLATO_BPN; -import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.PLATO_NAME; -import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.SOKRATES_BPN; -import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.SOKRATES_NAME; -import static org.eclipse.tractusx.edc.tests.TxParticipant.ASYNC_TIMEOUT; -import static org.eclipse.tractusx.edc.tests.helpers.PolicyHelperFunctions.bnpPolicy; - -public abstract class AbstractHttpConsumerPullWithProxyTest { - - protected static final TxParticipant SOKRATES = TxParticipant.Builder.newInstance() - .name(SOKRATES_NAME) - .id(SOKRATES_BPN) - .build(); - - protected static final TxParticipant PLATO = TxParticipant.Builder.newInstance() - .name(PLATO_NAME) - .id(PLATO_BPN) - .build(); - - protected MockWebServer server; - - public static JsonObject createProxyRequest() { - return Json.createObjectBuilder() - .add(TYPE, EDC_NAMESPACE + "DataAddress") - .add(EDC_NAMESPACE + "type", "HttpProxy-PULL") - .build(); - - } - - @BeforeEach - void setup() throws IOException { - server = new MockWebServer(); - } - - @Test - void transferData_privateBackend() throws IOException, InterruptedException { - var assetId = "api-asset-1"; - var url = server.url("/mock/api"); - server.start(); - - - Map dataAddress = Map.of( - "baseUrl", url.toString(), - "type", "HttpData", - "contentType", "application/json" - ); - - PLATO.createAsset(assetId, Map.of(), dataAddress); - - var accessPolicyId = PLATO.createPolicyDefinition(createAccessPolicy(SOKRATES.getBpn())); - var contractPolicyId = PLATO.createPolicyDefinition(createContractPolicy(SOKRATES.getBpn())); - PLATO.createContractDefinition(assetId, "def-1", accessPolicyId, contractPolicyId); - var transferProcessId = SOKRATES.requestAsset(PLATO, assetId, Json.createObjectBuilder().build(), createProxyRequest()); - - var contractAgreementId = new AtomicReference(); - var edr = new AtomicReference(); - - // wait until transfer process completes - await().pollInterval(fibonacci()) - .atMost(ASYNC_TIMEOUT) - .untilAsserted(() -> { - var tpState = SOKRATES.getTransferProcessState(transferProcessId); - assertThat(tpState).isNotNull().isEqualTo(TransferProcessStates.STARTED.toString()); - }); - - // wait until EDC is available on the consumer side - server.enqueue(new MockResponse().setBody("test response").setResponseCode(200)); - await().pollInterval(fibonacci()) - .atMost(ASYNC_TIMEOUT) - .untilAsserted(() -> { - edr.set(SOKRATES.edrs().getEdr(transferProcessId)); - assertThat(edr).isNotNull(); - }); - - // pull data out of provider's backend service: - // Prov-DP -> Prov-backend - assertThat(SOKRATES.data().pullData(edr.get(), Map.of())).isEqualTo("test response"); - var rq = server.takeRequest(); - assertThat(rq.getHeader("Edc-Contract-Agreement-Id")).isNotNull(); - assertThat(rq.getHeader("Edc-Bpn")).isEqualTo(SOKRATES.getBpn()); - assertThat(rq.getMethod()).isEqualToIgnoringCase("GET"); - } - - @AfterEach - void teardown() throws IOException { - server.shutdown(); - } - - protected JsonObject createAccessPolicy(String bpn) { - return bnpPolicy(bpn); - } - - protected JsonObject createContractPolicy(String bpn) { - return bnpPolicy(bpn); - } -} diff --git a/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/AbstractIatpConsumerPullTest.java b/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/AbstractIatpConsumerPullTest.java new file mode 100644 index 000000000..df4b53d5a --- /dev/null +++ b/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/AbstractIatpConsumerPullTest.java @@ -0,0 +1,88 @@ +/******************************************************************************** + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +package org.eclipse.tractusx.edc.tests.transfer; + +import jakarta.json.JsonObject; +import org.eclipse.tractusx.edc.tests.participant.TractusxParticipantBase; +import org.eclipse.tractusx.edc.tests.transfer.iatp.harness.DataspaceIssuer; +import org.eclipse.tractusx.edc.tests.transfer.iatp.harness.IatpParticipant; +import org.eclipse.tractusx.edc.tests.transfer.iatp.harness.StsParticipant; + +import java.net.URI; +import java.util.Map; + +import static org.eclipse.edc.util.io.Ports.getFreePort; +import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.CX_POLICY_NS; +import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.PLATO_BPN; +import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.PLATO_NAME; +import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.SOKRATES_BPN; +import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.SOKRATES_NAME; +import static org.eclipse.tractusx.edc.tests.helpers.PolicyHelperFunctions.frameworkPolicy; + +public abstract class AbstractIatpConsumerPullTest extends HttpConsumerPullBaseTest { + + protected static final URI DIM_URI = URI.create("http://localhost:" + getFreePort()); + protected static final DataspaceIssuer DATASPACE_ISSUER_PARTICIPANT = new DataspaceIssuer(); + protected static final StsParticipant STS = StsParticipant.Builder.newInstance() + .id("STS") + .name("STS") + .build(); + protected static final IatpParticipant SOKRATES = IatpParticipant.Builder.newInstance() + .name(SOKRATES_NAME) + .id(SOKRATES_BPN) + .stsUri(STS.stsUri()) + .stsClientId(SOKRATES_BPN) + .stsClientSecret("client_secret") + .trustedIssuer(DATASPACE_ISSUER_PARTICIPANT.didUrl()) + .dimUri(DIM_URI) + .did(did(SOKRATES_NAME)) + .build(); + protected static final IatpParticipant PLATO = IatpParticipant.Builder.newInstance() + .name(PLATO_NAME) + .id(PLATO_BPN) + .stsUri(STS.stsUri()) + .stsClientId(PLATO_BPN) + .stsClientSecret("client_secret") + .trustedIssuer(DATASPACE_ISSUER_PARTICIPANT.didUrl()) + .dimUri(DIM_URI) + .did(did(PLATO_NAME)) + .build(); + + private static String did(String name) { + return "did:example:" + name.toLowerCase(); + } + + + @Override + public TractusxParticipantBase plato() { + return PLATO; + } + + @Override + public TractusxParticipantBase sokrates() { + return SOKRATES; + } + + @Override + protected JsonObject createContractPolicy(String bpn) { + return frameworkPolicy(Map.of(CX_POLICY_NS + "Membership", "active")); + } + +} diff --git a/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/DimHttpConsumerPullWithProxyInMemoryTest.java b/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/DimHttpConsumerPullTest.java similarity index 57% rename from edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/DimHttpConsumerPullWithProxyInMemoryTest.java rename to edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/DimHttpConsumerPullTest.java index 68f20aa3e..90b9c2e4d 100644 --- a/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/DimHttpConsumerPullWithProxyInMemoryTest.java +++ b/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/DimHttpConsumerPullTest.java @@ -19,60 +19,39 @@ package org.eclipse.tractusx.edc.tests.transfer; -import jakarta.json.JsonObject; import okhttp3.mockwebserver.MockWebServer; import org.eclipse.edc.iam.did.spi.document.DidDocument; import org.eclipse.edc.iam.identitytrust.sts.embedded.EmbeddedSecureTokenService; import org.eclipse.edc.junit.annotations.EndToEndTest; import org.eclipse.edc.token.JwtGenerationService; import org.eclipse.edc.token.spi.TokenGenerationService; -import org.eclipse.tractusx.edc.tests.transfer.iatp.IatpDimParticipant; import org.eclipse.tractusx.edc.tests.transfer.iatp.dispatchers.DimDispatcher; import org.eclipse.tractusx.edc.tests.transfer.iatp.dispatchers.KeycloakDispatcher; -import org.eclipse.tractusx.edc.tests.transfer.iatp.harness.DataspaceIssuer; -import org.eclipse.tractusx.edc.tests.transfer.iatp.harness.SecureTokenService; +import org.eclipse.tractusx.edc.tests.transfer.iatp.harness.IatpParticipant; import org.eclipse.tractusx.edc.tests.transfer.iatp.runtime.IatpParticipantRuntime; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.extension.RegisterExtension; import java.io.IOException; -import java.net.URI; import java.security.PrivateKey; import java.time.Clock; import java.util.HashMap; import java.util.Map; import java.util.function.Supplier; -import static org.eclipse.edc.util.io.Ports.getFreePort; -import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.CX_CREDENTIAL_NS; -import static org.eclipse.tractusx.edc.tests.helpers.PolicyHelperFunctions.frameworkPolicy; import static org.eclipse.tractusx.edc.tests.transfer.iatp.harness.IatpHelperFunctions.configureParticipant; +import static org.eclipse.tractusx.edc.tests.transfer.iatp.runtime.Runtimes.dimRuntime; @EndToEndTest -public class DimHttpConsumerPullWithProxyInMemoryTest extends AbstractHttpConsumerPullWithProxyTest { +public class DimHttpConsumerPullTest extends AbstractIatpConsumerPullTest { - protected static final URI DIM_URI = URI.create("http://localhost:" + getFreePort()); - protected static final DataspaceIssuer DATASPACE_ISSUER_PARTICIPANT = new DataspaceIssuer(); - protected static final SecureTokenService STS_PARTICIPANT = new SecureTokenService(); - protected static final IatpDimParticipant PLATO_IATP = new IatpDimParticipant(PLATO, STS_PARTICIPANT.stsUri(), DIM_URI); @RegisterExtension - protected static final IatpParticipantRuntime PLATO_RUNTIME = new IatpParticipantRuntime( - ":edc-tests:runtime:iatp:runtime-memory-iatp-dim-ih", - PLATO.getName(), - PLATO_IATP.iatpConfiguration(SOKRATES), - PLATO_IATP.getKeyPair() - ); - protected static final IatpDimParticipant SOKRATES_IATP = new IatpDimParticipant(SOKRATES, STS_PARTICIPANT.stsUri(), DIM_URI); + protected static final IatpParticipantRuntime SOKRATES_RUNTIME = dimRuntime(SOKRATES.getName(), SOKRATES.iatpConfiguration(PLATO), SOKRATES.getKeyPair()); @RegisterExtension - protected static final IatpParticipantRuntime SOKRATES_RUNTIME = new IatpParticipantRuntime( - ":edc-tests:runtime:iatp:runtime-memory-iatp-dim-ih", - SOKRATES.getName(), - SOKRATES_IATP.iatpConfiguration(PLATO), - SOKRATES_IATP.getKeyPair() - ); + protected static final IatpParticipantRuntime PLATO_RUNTIME = dimRuntime(PLATO.getName(), PLATO.iatpConfiguration(SOKRATES), PLATO.getKeyPair()); private static MockWebServer oauthServer; private static MockWebServer dimDispatcher; @@ -82,12 +61,12 @@ static void prepare() throws IOException { var tokenGeneration = new JwtGenerationService(); var generatorServices = Map.of( - SOKRATES_IATP.didUrl(), tokenServiceFor(tokenGeneration, SOKRATES_IATP), - PLATO_IATP.didUrl(), tokenServiceFor(tokenGeneration, PLATO_IATP)); + SOKRATES.getDid(), tokenServiceFor(tokenGeneration, SOKRATES), + PLATO.getDid(), tokenServiceFor(tokenGeneration, PLATO)); oauthServer = new MockWebServer(); - oauthServer.start(STS_PARTICIPANT.stsUri().getPort()); - oauthServer.setDispatcher(new KeycloakDispatcher(STS_PARTICIPANT.stsUri().getPath() + "/token")); + oauthServer.start(STS.stsUri().getPort()); + oauthServer.setDispatcher(new KeycloakDispatcher(STS.stsUri().getPath() + "/token")); dimDispatcher = new MockWebServer(); dimDispatcher.start(DIM_URI.getPort()); @@ -96,11 +75,11 @@ static void prepare() throws IOException { // create the DIDs cache var dids = new HashMap(); dids.put(DATASPACE_ISSUER_PARTICIPANT.didUrl(), DATASPACE_ISSUER_PARTICIPANT.didDocument()); - dids.put(SOKRATES_IATP.didUrl(), SOKRATES_IATP.didDocument()); - dids.put(PLATO_IATP.didUrl(), PLATO_IATP.didDocument()); + dids.put(SOKRATES.getDid(), SOKRATES.getDidDocument()); + dids.put(PLATO.getDid(), PLATO.getDidDocument()); - configureParticipant(DATASPACE_ISSUER_PARTICIPANT, SOKRATES_IATP, SOKRATES_RUNTIME, dids, null); - configureParticipant(DATASPACE_ISSUER_PARTICIPANT, PLATO_IATP, PLATO_RUNTIME, dids, null); + configureParticipant(DATASPACE_ISSUER_PARTICIPANT, SOKRATES, SOKRATES_RUNTIME, dids, null); + configureParticipant(DATASPACE_ISSUER_PARTICIPANT, PLATO, PLATO_RUNTIME, dids, null); } @@ -110,22 +89,17 @@ static void unwind() throws IOException { dimDispatcher.shutdown(); } - private static EmbeddedSecureTokenService tokenServiceFor(TokenGenerationService tokenGenerationService, IatpDimParticipant iatpDimParticipant) { + private static EmbeddedSecureTokenService tokenServiceFor(TokenGenerationService tokenGenerationService, IatpParticipant iatpDimParticipant) { return new EmbeddedSecureTokenService(tokenGenerationService, privateKeySupplier(iatpDimParticipant), publicIdSupplier(iatpDimParticipant), Clock.systemUTC(), 60 * 60); } - private static Supplier privateKeySupplier(IatpDimParticipant participant) { + private static Supplier privateKeySupplier(IatpParticipant participant) { return () -> participant.getKeyPair().getPrivate(); } - private static Supplier publicIdSupplier(IatpDimParticipant participant) { + private static Supplier publicIdSupplier(IatpParticipant participant) { return participant::verificationId; } - @Override - protected JsonObject createContractPolicy(String bpn) { - return frameworkPolicy(Map.of(CX_CREDENTIAL_NS + "Membership", "active")); - } - } diff --git a/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/IatpHttpConsumerPullWithProxyInMemoryTest.java b/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/IatpHttpConsumerPullWithProxyInMemoryTest.java deleted file mode 100644 index 73b2993ec..000000000 --- a/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/IatpHttpConsumerPullWithProxyInMemoryTest.java +++ /dev/null @@ -1,223 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.tests.transfer; - -import jakarta.json.Json; -import jakarta.json.JsonObject; -import okhttp3.mockwebserver.MockResponse; -import org.eclipse.edc.connector.transfer.spi.types.TransferProcessStates; -import org.eclipse.edc.iam.did.spi.document.DidDocument; -import org.eclipse.edc.junit.annotations.EndToEndTest; -import org.eclipse.edc.policy.model.Operator; -import org.eclipse.tractusx.edc.tests.transfer.iatp.IatpParticipant; -import org.eclipse.tractusx.edc.tests.transfer.iatp.harness.DataspaceIssuer; -import org.eclipse.tractusx.edc.tests.transfer.iatp.harness.SecureTokenService; -import org.eclipse.tractusx.edc.tests.transfer.iatp.runtime.IatpParticipantRuntime; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.extension.ExtensionContext; -import org.junit.jupiter.api.extension.RegisterExtension; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.Arguments; -import org.junit.jupiter.params.provider.ArgumentsProvider; -import org.junit.jupiter.params.provider.ArgumentsSource; - -import java.io.IOException; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.atomic.AtomicReference; -import java.util.stream.Stream; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.awaitility.Awaitility.await; -import static org.awaitility.pollinterval.FibonacciPollInterval.fibonacci; -import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.CX_CREDENTIAL_NS; -import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.CX_POLICY_NS; -import static org.eclipse.tractusx.edc.tests.TxParticipant.ASYNC_TIMEOUT; -import static org.eclipse.tractusx.edc.tests.helpers.PolicyHelperFunctions.frameworkPolicy; -import static org.eclipse.tractusx.edc.tests.transfer.iatp.harness.IatpHelperFunctions.configureParticipant; - -@EndToEndTest -public class IatpHttpConsumerPullWithProxyInMemoryTest extends AbstractHttpConsumerPullWithProxyTest { - - protected static final DataspaceIssuer DATASPACE_ISSUER_PARTICIPANT = new DataspaceIssuer(); - protected static final SecureTokenService STS_PARTICIPANT = new SecureTokenService(); - protected static final IatpParticipant PLATO_IATP = new IatpParticipant(PLATO, STS_PARTICIPANT.stsUri()); - @RegisterExtension - protected static final IatpParticipantRuntime PLATO_RUNTIME = new IatpParticipantRuntime( - ":edc-tests:runtime:iatp:runtime-memory-iatp-ih", - PLATO.getName(), - PLATO_IATP.iatpConfiguration(SOKRATES), - PLATO_IATP.getKeyPair()); - protected static final IatpParticipant SOKRATES_IATP = new IatpParticipant(SOKRATES, STS_PARTICIPANT.stsUri()); - @RegisterExtension - protected static final IatpParticipantRuntime SOKRATES_RUNTIME = new IatpParticipantRuntime( - ":edc-tests:runtime:iatp:runtime-memory-iatp-ih", - SOKRATES.getName(), - SOKRATES_IATP.iatpConfiguration(PLATO), - SOKRATES_IATP.getKeyPair()); - - @RegisterExtension - protected static final IatpParticipantRuntime STS_RUNTIME = new IatpParticipantRuntime( - ":edc-tests:runtime:iatp:runtime-memory-sts", - STS_PARTICIPANT.getName(), - STS_PARTICIPANT.stsConfiguration(SOKRATES_IATP, PLATO_IATP), - STS_PARTICIPANT.getKeyPair()); - - @BeforeAll - static void prepare() { - - // create the DIDs cache - var dids = new HashMap(); - dids.put(DATASPACE_ISSUER_PARTICIPANT.didUrl(), DATASPACE_ISSUER_PARTICIPANT.didDocument()); - dids.put(SOKRATES_IATP.didUrl(), SOKRATES_IATP.didDocument()); - dids.put(PLATO_IATP.didUrl(), PLATO_IATP.didDocument()); - - configureParticipant(DATASPACE_ISSUER_PARTICIPANT, SOKRATES_IATP, SOKRATES_RUNTIME, dids, STS_RUNTIME); - configureParticipant(DATASPACE_ISSUER_PARTICIPANT, PLATO_IATP, PLATO_RUNTIME, dids, STS_RUNTIME); - - } - - @DisplayName("Contract policy is fulfilled") - @ParameterizedTest(name = "{1}") - @ArgumentsSource(ValidContractPolicyProvider.class) - void transferData_whenContractPolicyFulfilled(JsonObject contractPolicy, String description) throws IOException, InterruptedException { - var assetId = "api-asset-1"; - var url = server.url("/mock/api"); - server.start(); - - var authCodeHeaderName = "test-authkey"; - var authCode = "test-authcode"; - - Map dataAddress = Map.of( - "baseUrl", url.toString(), - "type", "HttpData", - "contentType", "application/json", - "authKey", authCodeHeaderName, - "authCode", authCode - ); - - PLATO.createAsset(assetId, Map.of(), dataAddress); - - var accessPolicyId = PLATO.createPolicyDefinition(createAccessPolicy(SOKRATES.getBpn())); - var contractPolicyId = PLATO.createPolicyDefinition(contractPolicy); - PLATO.createContractDefinition(assetId, "def-1", accessPolicyId, contractPolicyId); - var transferProcessId = SOKRATES.requestAsset(PLATO, assetId, Json.createObjectBuilder().build(), createProxyRequest()); - - var edr = new AtomicReference(); - - // wait until transfer process completes - await().pollInterval(fibonacci()) - .atMost(ASYNC_TIMEOUT) - .untilAsserted(() -> { - var tpState = SOKRATES.getTransferProcessState(transferProcessId); - assertThat(tpState).isNotNull().isEqualTo(TransferProcessStates.STARTED.toString()); - }); - - // wait until EDC is available on the consumer side - server.enqueue(new MockResponse().setBody("test response").setResponseCode(200)); - await().pollInterval(fibonacci()) - .atMost(ASYNC_TIMEOUT) - .untilAsserted(() -> { - edr.set(SOKRATES.edrs().getEdr(transferProcessId)); - assertThat(edr).isNotNull(); - }); - - // pull data out of provider's backend service: - // Cons-DP -> Prov-DP -> Prov-backend - assertThat(SOKRATES.data().pullData(edr.get(), Map.of())).isEqualTo("test response"); - var rq = server.takeRequest(); - assertThat(rq.getHeader(authCodeHeaderName)).isEqualTo(authCode); - assertThat(rq.getHeader("Edc-Contract-Agreement-Id")).isNotNull(); - assertThat(rq.getHeader("Edc-Bpn")).isEqualTo(SOKRATES.getBpn()); - assertThat(rq.getMethod()).isEqualToIgnoringCase("GET"); - } - - @DisplayName("Contract policy is NOT fulfilled") - @ParameterizedTest(name = "{1}") - @ArgumentsSource(InvalidContractPolicyProvider.class) - void transferData_whenContractPolicyNotFulfilled(JsonObject contractPolicy, String description) throws IOException { - var assetId = "api-asset-1"; - var url = server.url("/mock/api"); - server.start(); - - var authCodeHeaderName = "test-authkey"; - var authCode = "test-authcode"; - - Map dataAddress = Map.of( - "baseUrl", url.toString(), - "type", "HttpData", - "contentType", "application/json", - "authKey", authCodeHeaderName, - "authCode", authCode - ); - - PLATO.createAsset(assetId, Map.of(), dataAddress); - - var accessPolicyId = PLATO.createPolicyDefinition(createAccessPolicy(SOKRATES.getBpn())); - var contractPolicyId = PLATO.createPolicyDefinition(contractPolicy); - PLATO.createContractDefinition(assetId, "def-1", accessPolicyId, contractPolicyId); - var negotiationId = SOKRATES.initContractNegotiation(PLATO, assetId); - - await().pollInterval(fibonacci()) - .atMost(ASYNC_TIMEOUT) - .untilAsserted(() -> { - var contractNegotiationState = SOKRATES.getContractNegotiationState(negotiationId); - assertThat(contractNegotiationState).isEqualTo("TERMINATED"); - }); - } - - @Override - protected JsonObject createContractPolicy(String bpn) { - return frameworkPolicy(Map.of(CX_CREDENTIAL_NS + "Membership", "active")); - } - - private static class ValidContractPolicyProvider implements ArgumentsProvider { - @Override - public Stream provideArguments(ExtensionContext extensionContext) { - return Stream.of( - Arguments.of(frameworkPolicy(Map.of(CX_POLICY_NS + "Membership", "active")), "MembershipCredential"), - Arguments.of(frameworkPolicy(Map.of(CX_POLICY_NS + "FrameworkAgreement.pcf", "active")), "PCF Use Case (legacy notation)"), - Arguments.of(frameworkPolicy(Map.of(CX_POLICY_NS + "FrameworkAgreement", "pcf")), "PCF Use Case (new notation)"), - Arguments.of(frameworkPolicy(Map.of(CX_POLICY_NS + "Dismantler", "active")), "Dismantler Credential"), - Arguments.of(frameworkPolicy(Map.of(CX_POLICY_NS + "Dismantler.activityType", "vehicleDismantle")), "Dismantler Cred (activity type)"), - Arguments.of(frameworkPolicy(CX_POLICY_NS + "Dismantler.allowedBrands", Operator.IS_ANY_OF, List.of("Moskvich", "Tatra")), "Dismantler allowedBrands (IS_ANY_OF, one intersects)"), - Arguments.of(frameworkPolicy(CX_POLICY_NS + "Dismantler.allowedBrands", Operator.EQ, List.of("Moskvich", "Lada")), "Dismantler allowedBrands (EQ, exact match)"), - Arguments.of(frameworkPolicy(CX_POLICY_NS + "Dismantler.allowedBrands", Operator.IS_NONE_OF, List.of("Yugo", "Tatra")), "Dismantler allowedBrands (IS_NONE_OF, no intersect)"), - Arguments.of(frameworkPolicy(CX_POLICY_NS + "Dismantler.allowedBrands", Operator.IN, List.of("Moskvich", "Tatra", "Yugo", "Lada")), "Dismantler allowedBrands (IN, fully contained)") - ); - } - } - - private static class InvalidContractPolicyProvider implements ArgumentsProvider { - @Override - public Stream provideArguments(ExtensionContext extensionContext) { - return Stream.of( - Arguments.of(frameworkPolicy(Map.of(CX_POLICY_NS + "FrameworkAgreement.sustainability", "active")), "Sustainability Use Case (legacy notation)"), - Arguments.of(frameworkPolicy(Map.of(CX_POLICY_NS + "FrameworkAgreement", "traceability")), "Traceability Use Case (new notation)"), - Arguments.of(frameworkPolicy(Map.of(CX_POLICY_NS + "Dismantler.activityType", "vehicleScrap")), "Dismantler activityType does not match"), - Arguments.of(frameworkPolicy(CX_POLICY_NS + "Dismantler.allowedBrands", Operator.NEQ, List.of("Moskvich", "Lada")), "Dismantler allowedBrands (NEQ, but is equal)"), - Arguments.of(frameworkPolicy(CX_POLICY_NS + "Dismantler.allowedBrands", Operator.IS_NONE_OF, List.of("Yugo", "Lada")), "Dismantler allowedBrands (IS_NONE_OF, but is one contains)"), - Arguments.of(frameworkPolicy(CX_POLICY_NS + "Dismantler.allowedBrands", Operator.IN, List.of("Moskvich", "Tatra", "Yugo")), "Dismantler allowedBrands (IN, but not subset)") - ); - } - } -} diff --git a/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/StsHttpConsumerPullTest.java b/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/StsHttpConsumerPullTest.java new file mode 100644 index 000000000..4ec46af14 --- /dev/null +++ b/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/StsHttpConsumerPullTest.java @@ -0,0 +1,61 @@ +/******************************************************************************** + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +package org.eclipse.tractusx.edc.tests.transfer; + +import org.eclipse.edc.iam.did.spi.document.DidDocument; +import org.eclipse.edc.junit.annotations.EndToEndTest; +import org.eclipse.tractusx.edc.tests.transfer.iatp.runtime.IatpParticipantRuntime; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.extension.RegisterExtension; + +import java.util.HashMap; + +import static org.eclipse.tractusx.edc.tests.transfer.iatp.harness.IatpHelperFunctions.configureParticipant; +import static org.eclipse.tractusx.edc.tests.transfer.iatp.runtime.Runtimes.iatpRuntime; +import static org.eclipse.tractusx.edc.tests.transfer.iatp.runtime.Runtimes.stsRuntime; + +@EndToEndTest +public class StsHttpConsumerPullTest extends AbstractIatpConsumerPullTest { + + + @RegisterExtension + protected static final IatpParticipantRuntime SOKRATES_RUNTIME = iatpRuntime(SOKRATES.getName(), SOKRATES.iatpConfiguration(PLATO), SOKRATES.getKeyPair()); + + @RegisterExtension + protected static final IatpParticipantRuntime PLATO_RUNTIME = iatpRuntime(PLATO.getName(), PLATO.iatpConfiguration(SOKRATES), PLATO.getKeyPair()); + + @RegisterExtension + protected static final IatpParticipantRuntime STS_RUNTIME = stsRuntime(STS.getName(), STS.stsConfiguration(SOKRATES, PLATO), STS.getKeyPair()); + + @BeforeAll + static void prepare() { + + // create the DIDs cache + var dids = new HashMap(); + dids.put(DATASPACE_ISSUER_PARTICIPANT.didUrl(), DATASPACE_ISSUER_PARTICIPANT.didDocument()); + dids.put(SOKRATES.getDid(), SOKRATES.getDidDocument()); + dids.put(PLATO.getDid(), PLATO.getDidDocument()); + + configureParticipant(DATASPACE_ISSUER_PARTICIPANT, SOKRATES, SOKRATES_RUNTIME, dids, STS_RUNTIME); + configureParticipant(DATASPACE_ISSUER_PARTICIPANT, PLATO, PLATO_RUNTIME, dids, STS_RUNTIME); + + } + +} diff --git a/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/iatp/IatpParticipant.java b/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/iatp/IatpParticipant.java deleted file mode 100644 index f0a205c1b..000000000 --- a/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/iatp/IatpParticipant.java +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -package org.eclipse.tractusx.edc.tests.transfer.iatp; - -import org.eclipse.edc.iam.did.spi.document.DidDocument; -import org.eclipse.edc.iam.did.spi.document.Service; -import org.eclipse.edc.iam.did.spi.document.VerificationMethod; -import org.eclipse.tractusx.edc.tests.IdentityParticipant; -import org.eclipse.tractusx.edc.tests.TxParticipant; - -import java.net.URI; -import java.util.Arrays; -import java.util.Base64; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.stream.Stream; - -import static org.eclipse.edc.util.io.Ports.getFreePort; -import static org.eclipse.tractusx.edc.tests.transfer.iatp.harness.DataspaceIssuer.DATASPACE_ISSUER; - -/** - * Wrapper of {@link TxParticipant} with IATP specific configurations - */ -public class IatpParticipant extends IdentityParticipant { - - public static final String DID_EXAMPLE = "did:example:"; - protected final URI csService = URI.create("http://localhost:" + getFreePort() + "/api/resolution"); - private final TxParticipant participant; - private final URI stsUri; - private final DidDocument didDocument; - - public IatpParticipant(TxParticipant participant, URI stsUri) { - this.participant = participant; - this.stsUri = stsUri; - this.didDocument = generateDidDocument(); - } - - public String getBpn() { - return participant.getBpn(); - } - - public String getName() { - return participant.getName(); - } - - public Map iatpConfiguration(TxParticipant... others) { - var did = DID_EXAMPLE + participant.getName().toLowerCase(); - var iatpConfiguration = new HashMap<>(participant.getConfiguration()) { - { - - put("edc.iam.sts.oauth.token.url", stsUri + "/token"); - put("edc.iam.sts.oauth.client.id", getBpn()); - put("edc.iam.sts.oauth.client.secret.alias", "client_secret_alias"); - put("edc.iam.issuer.id", did); - put("edc.ih.iam.id", participant.getBpn()); - put("tx.vault.seed.secrets", "client_secret_alias:client_secret"); - put("edc.ih.iam.publickey.alias", getFullKeyId()); - put("web.http.resolution.port", String.valueOf(csService.getPort())); - put("web.http.resolution.path", csService.getPath()); - put("edc.agent.identity.key", "client_id"); - put("edc.iam.trusted-issuer.issuer.id", DATASPACE_ISSUER); - - put("edc.transfer.proxy.token.signer.privatekey.alias", getPrivateKeyAlias()); - put("edc.transfer.proxy.token.verifier.publickey.alias", getFullKeyId()); - } - }; - - Stream.concat(Stream.of(participant), Arrays.stream(others)).forEach(p -> { - var prefix = "tx.iam.iatp.audiences.%s".formatted(p.getName().toLowerCase()); - var participantDid = DID_EXAMPLE + p.getName().toLowerCase(); - iatpConfiguration.put("%s_endpoint.from".formatted(prefix), p.getProtocolEndpoint().getUrl().toString()); - iatpConfiguration.put("%s_endpoint.to".formatted(prefix), participantDid); - iatpConfiguration.put("%s_id.from".formatted(prefix), p.getBpn()); - iatpConfiguration.put("%s_id.to".formatted(prefix), participantDid); - }); - return iatpConfiguration; - } - - public String didUrl() { - return DID_EXAMPLE + participant.getName().toLowerCase(); - } - - public String verificationId() { - return didUrl() + "#" + getKeyId(); - } - - public DidDocument didDocument() { - return didDocument; - } - - @Override - public String getFullKeyId() { - return verificationId(); - } - - - private DidDocument generateDidDocument() { - var service = new Service(); - service.setId("#credential-service"); - service.setType("CredentialService"); - service.setServiceEndpoint(csService + "/v1/participants/" + toBase64(didUrl())); - - var ecKey = getKeyPairAsJwk(); - - var verificationMethod = VerificationMethod.Builder.newInstance() - .id(verificationId()) - .controller(didUrl()) - .type("JsonWebKey2020") - .publicKeyJwk(ecKey.toPublicJWK().toJSONObject()) - .build(); - - return DidDocument.Builder.newInstance() - .id(didUrl()) - .service(List.of(service)) - .authentication(List.of("#key1")) - .verificationMethod(List.of(verificationMethod)) - .build(); - } - - private String toBase64(String s) { - return Base64.getUrlEncoder().encodeToString(s.getBytes()); - } -} diff --git a/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/iatp/harness/DataspaceIssuer.java b/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/iatp/harness/DataspaceIssuer.java index 56fa04427..89d61968a 100644 --- a/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/iatp/harness/DataspaceIssuer.java +++ b/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/iatp/harness/DataspaceIssuer.java @@ -1,5 +1,5 @@ -/* - * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft +/******************************************************************************** + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) * * See the NOTICE file(s) distributed with this work for additional * information regarding copyright ownership. @@ -15,7 +15,7 @@ * under the License. * * SPDX-License-Identifier: Apache-2.0 - */ + ********************************************************************************/ package org.eclipse.tractusx.edc.tests.transfer.iatp.harness; @@ -37,7 +37,6 @@ import org.eclipse.edc.security.signature.jws2020.JwsSignature2020Suite; import org.eclipse.edc.verifiablecredentials.linkeddata.LdpIssuer; import org.eclipse.tractusx.edc.tests.IdentityParticipant; -import org.eclipse.tractusx.edc.tests.transfer.iatp.IatpParticipant; import java.net.URI; import java.time.Instant; @@ -78,7 +77,7 @@ public String verificationId() { return DATASPACE_ISSUER + "#" + getKeyId(); } - public VerifiableCredentialResource issueCredential(IatpParticipant participant, JsonLd jsonLd, String type, Supplier credentialSubjectSupplier, Supplier subjectSupplier) { + public VerifiableCredentialResource issueCredential(String did, String bpn, JsonLd jsonLd, String type, Supplier credentialSubjectSupplier, Supplier subjectSupplier) { var credential = VerifiableCredential.Builder.newInstance() .type(type) .credentialSubject(credentialSubjectSupplier.get()) @@ -89,40 +88,40 @@ public VerifiableCredentialResource issueCredential(IatpParticipant participant, var rawVc = createLdpVc(jsonLd, type, subjectSupplier); return VerifiableCredentialResource.Builder.newInstance() .issuerId(didUrl()) - .participantId(participant.didUrl()) - .holderId(participant.getBpn()) + .participantId(did) + .holderId(bpn) .credential(new VerifiableCredentialContainer(rawVc, CredentialFormat.JSON_LD, credential)) .build(); } - public VerifiableCredentialResource issueMembershipCredential(IatpParticipant participant, JsonLd jsonLd) { - return issueCredential(participant, jsonLd, "MembershipCredential", () -> CredentialSubject.Builder.newInstance() - .claim("holderIdentifier", participant.getBpn()) + public VerifiableCredentialResource issueMembershipCredential(String did, String bpn, JsonLd jsonLd) { + return issueCredential(did, bpn, jsonLd, "MembershipCredential", () -> CredentialSubject.Builder.newInstance() + .claim("holderIdentifier", bpn) .build(), - () -> membershipSubject(participant.didUrl(), participant.getBpn())); + () -> membershipSubject(did, bpn)); } - public VerifiableCredentialResource issueDismantlerCredential(IatpParticipant participant, JsonLd jsonLd) { - return issueCredential(participant, jsonLd, "DismantlerCredential", () -> CredentialSubject.Builder.newInstance() - .claim("holderIdentifier", participant.didUrl()) + public VerifiableCredentialResource issueDismantlerCredential(String did, String bpn, JsonLd jsonLd) { + return issueCredential(did, bpn, jsonLd, "DismantlerCredential", () -> CredentialSubject.Builder.newInstance() + .claim("holderIdentifier", bpn) .claim("activityType", "vehicleDismantle") .claim("allowedVehicleBrands", List.of("Moskvich", "Lada")) .build(), () -> Json.createObjectBuilder() - .add("type", "MembershipCredential") - .add("holderIdentifier", participant.didUrl()) + .add("type", "DismantlerCredential") + .add("holderIdentifier", bpn) .add("activityType", "vehicleDismantle") .add("allowedVehicleBrands", Json.createArrayBuilder().add("Moskvich").add("Lada").build()) - .add("id", participant.didUrl()) + .add("id", did) .build()); } - public VerifiableCredentialResource issueFrameworkCredential(IatpParticipant participant, JsonLd jsonLd, String credentialType) { - return issueCredential(participant, jsonLd, credentialType, () -> CredentialSubject.Builder.newInstance() - .claim("holderIdentifier", participant.getBpn()) + public VerifiableCredentialResource issueFrameworkCredential(String did, String bpn, JsonLd jsonLd, String credentialType) { + return issueCredential(did, bpn, jsonLd, credentialType, () -> CredentialSubject.Builder.newInstance() + .claim("holderIdentifier", bpn) .build(), - () -> frameworkAgreementSubject(participant.didUrl(), participant.getBpn(), credentialType)); + () -> frameworkAgreementSubject(did, bpn, credentialType)); } diff --git a/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/iatp/harness/DidExampleResolver.java b/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/iatp/harness/DidExampleResolver.java index eee98794e..c9297a456 100644 --- a/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/iatp/harness/DidExampleResolver.java +++ b/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/iatp/harness/DidExampleResolver.java @@ -1,5 +1,5 @@ -/* - * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft +/******************************************************************************** + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) * * See the NOTICE file(s) distributed with this work for additional * information regarding copyright ownership. @@ -15,7 +15,7 @@ * under the License. * * SPDX-License-Identifier: Apache-2.0 - */ + ********************************************************************************/ package org.eclipse.tractusx.edc.tests.transfer.iatp.harness; diff --git a/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/iatp/harness/IatpHelperFunctions.java b/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/iatp/harness/IatpHelperFunctions.java index f16e88153..36485819d 100644 --- a/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/iatp/harness/IatpHelperFunctions.java +++ b/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/iatp/harness/IatpHelperFunctions.java @@ -1,5 +1,5 @@ -/* - * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft +/******************************************************************************** + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) * * See the NOTICE file(s) distributed with this work for additional * information regarding copyright ownership. @@ -15,7 +15,7 @@ * under the License. * * SPDX-License-Identifier: Apache-2.0 - */ + ********************************************************************************/ package org.eclipse.tractusx.edc.tests.transfer.iatp.harness; @@ -32,7 +32,6 @@ import org.eclipse.edc.jsonld.spi.JsonLd; import org.eclipse.edc.junit.extensions.EdcExtension; import org.eclipse.edc.spi.security.Vault; -import org.eclipse.tractusx.edc.tests.transfer.iatp.IatpParticipant; import java.time.Instant; import java.util.List; @@ -105,8 +104,8 @@ public static void configureParticipant(DataspaceIssuer issuer, IatpParticipant .build(); var participantManifest = ParticipantManifest.Builder.newInstance() - .participantId(participant.didUrl()) - .did(participant.didUrl()) + .participantId(participant.getDid()) + .did(participant.getDid()) .key(key) .build(); @@ -124,9 +123,9 @@ private static void storeCredentials(DataspaceIssuer issuer, IatpParticipant par private static List issueCredentials(DataspaceIssuer issuer, IatpParticipant participant, JsonLd jsonLd) { return List.of( - issuer.issueMembershipCredential(participant, jsonLd), - issuer.issueDismantlerCredential(participant, jsonLd), - issuer.issueFrameworkCredential(participant, jsonLd, "PcfCredential")); + issuer.issueMembershipCredential(participant.getDid(), participant.getBpn(), jsonLd), + issuer.issueDismantlerCredential(participant.getDid(), participant.getBpn(), jsonLd), + issuer.issueFrameworkCredential(participant.getDid(), participant.getBpn(), jsonLd, "PcfCredential")); } } diff --git a/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/iatp/harness/IatpParticipant.java b/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/iatp/harness/IatpParticipant.java new file mode 100644 index 000000000..b4edf7502 --- /dev/null +++ b/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/iatp/harness/IatpParticipant.java @@ -0,0 +1,112 @@ +/******************************************************************************** + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +package org.eclipse.tractusx.edc.tests.transfer.iatp.harness; + +import org.eclipse.edc.iam.did.spi.document.DidDocument; +import org.eclipse.edc.iam.did.spi.document.Service; +import org.eclipse.edc.iam.did.spi.document.VerificationMethod; +import org.eclipse.tractusx.edc.tests.participant.TractusxIatpParticipantBase; + +import java.net.URI; +import java.util.Base64; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static org.eclipse.edc.util.io.Ports.getFreePort; + +public class IatpParticipant extends TractusxIatpParticipantBase { + + protected final URI csService = URI.create("http://localhost:" + getFreePort() + "/api/resolution"); + protected URI dimUri; + + private DidDocument didDocument; + + public DidDocument getDidDocument() { + return didDocument; + } + + public String verificationId() { + return did + "#" + getKeyId(); + } + + @Override + public Map getConfiguration() { + var cfg = new HashMap<>(super.getConfiguration()); + cfg.put("web.http.resolution.port", String.valueOf(csService.getPort())); + cfg.put("web.http.resolution.path", csService.getPath()); + if (dimUri != null) { + cfg.put("edc.iam.sts.dim.url", dimUri.toString()); + } + return cfg; + } + + public static class Builder extends TractusxIatpParticipantBase.Builder { + + protected Builder() { + super(new IatpParticipant()); + } + + public static Builder newInstance() { + return new Builder(); + } + + @Override + public IatpParticipant build() { + super.build(); + participant.didDocument = generateDidDocument(); + return participant; + } + + public Builder dimUri(URI dimUri) { + participant.dimUri = dimUri; + return self(); + } + + private DidDocument generateDidDocument() { + var service = new Service(); + service.setId("#credential-service"); + service.setType("CredentialService"); + service.setServiceEndpoint(participant.csService + "/v1/participants/" + toBase64(participant.did)); + + var ecKey = participant.getKeyPairAsJwk(); + + var verificationMethod = VerificationMethod.Builder.newInstance() + .id(participant.verificationId()) + .controller(participant.did) + .type("JsonWebKey2020") + .publicKeyJwk(ecKey.toPublicJWK().toJSONObject()) + .build(); + + return DidDocument.Builder.newInstance() + .id(participant.did) + .service(List.of(service)) + .authentication(List.of("#key1")) + .verificationMethod(List.of(verificationMethod)) + .build(); + } + + + private String toBase64(String s) { + return Base64.getUrlEncoder().encodeToString(s.getBytes()); + } + + } +} diff --git a/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/iatp/harness/SecureTokenService.java b/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/iatp/harness/StsParticipant.java similarity index 63% rename from edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/iatp/harness/SecureTokenService.java rename to edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/iatp/harness/StsParticipant.java index 190a74742..3671cb60e 100644 --- a/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/iatp/harness/SecureTokenService.java +++ b/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/iatp/harness/StsParticipant.java @@ -1,5 +1,5 @@ -/* - * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft +/******************************************************************************** + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) * * See the NOTICE file(s) distributed with this work for additional * information regarding copyright ownership. @@ -15,14 +15,12 @@ * under the License. * * SPDX-License-Identifier: Apache-2.0 - */ + ********************************************************************************/ package org.eclipse.tractusx.edc.tests.transfer.iatp.harness; -import org.eclipse.tractusx.edc.tests.IdentityParticipant; -import org.eclipse.tractusx.edc.tests.TxParticipant; -import org.eclipse.tractusx.edc.tests.transfer.iatp.IatpParticipant; +import org.eclipse.tractusx.edc.tests.participant.TractusxParticipantBase; import java.net.URI; import java.util.Arrays; @@ -36,54 +34,60 @@ /** * STS configurations */ -public class SecureTokenService extends IdentityParticipant { +public class StsParticipant extends TractusxParticipantBase { protected final URI stsUri = URI.create("http://localhost:" + getFreePort() + "/api/v1/sts"); - protected final TxParticipant stsParticipant = TxParticipant.Builder.newInstance() - .name("STS") - .id("STS") - .build(); + + private StsParticipant() { + } public Map stsConfiguration(IatpParticipant... participants) { - var stsConfiguration = new HashMap() { - { - put("web.http.sts.port", String.valueOf(stsUri.getPort())); - put("web.http.sts.path", stsUri.getPath()); - put("edc.dataplane.token.validation.endpoint", ""); - put("tx.vault.seed.secrets", "client_secret_alias:client_secret"); - } - }; + var stsConfiguration = new HashMap<>(super.getConfiguration()); + + stsConfiguration.put("web.http.sts.port", String.valueOf(stsUri.getPort())); + stsConfiguration.put("web.http.sts.path", stsUri.getPath()); + stsConfiguration.put("edc.dataplane.token.validation.endpoint", ""); + stsConfiguration.put("tx.vault.seed.secrets", "client_secret_alias:client_secret"); Arrays.stream(participants).forEach(participant -> { var prefix = format("edc.iam.sts.clients.%s", participant.getName().toLowerCase()); stsConfiguration.put(prefix + ".name", participant.getName()); stsConfiguration.put(prefix + ".id", UUID.randomUUID().toString()); stsConfiguration.put(prefix + ".client_id", participant.getBpn()); - stsConfiguration.put(prefix + ".did", participant.didUrl()); + stsConfiguration.put(prefix + ".did", participant.getDid()); stsConfiguration.put(prefix + ".secret.alias", "client_secret_alias"); stsConfiguration.put(prefix + ".private-key.alias", participant.verificationId()); stsConfiguration.put(prefix + ".public-key.reference", participant.verificationId()); }); - var baseConfiguration = stsParticipant.getConfiguration(); - stsConfiguration.putAll(baseConfiguration); return stsConfiguration; } - public String getBpn() { - return stsParticipant.getBpn(); - } - public String getName() { - return stsParticipant.getName(); + @Override + public String getFullKeyId() { + return "sts-" + getKeyId(); } + public URI stsUri() { return stsUri; } - @Override - public String getFullKeyId() { - return "sts-" + getKeyId(); + public static class Builder extends TractusxParticipantBase.Builder { + + protected Builder() { + super(new StsParticipant()); + } + + public static Builder newInstance() { + return new Builder(); + } + + @Override + public StsParticipant build() { + super.build(); + return participant; + } } } diff --git a/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/iatp/runtime/Runtimes.java b/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/iatp/runtime/Runtimes.java new file mode 100644 index 000000000..8dcce0fdc --- /dev/null +++ b/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/iatp/runtime/Runtimes.java @@ -0,0 +1,49 @@ +/******************************************************************************** + * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +package org.eclipse.tractusx.edc.tests.transfer.iatp.runtime; + +import java.security.KeyPair; +import java.util.Map; + +public interface Runtimes { + + static IatpParticipantRuntime dimRuntime(String name, Map properties, KeyPair keyPair) { + return new IatpParticipantRuntime(":edc-tests:runtime:iatp:runtime-memory-iatp-dim-ih", + name, + properties, + keyPair); + } + + static IatpParticipantRuntime iatpRuntime(String name, Map properties, KeyPair keyPair) { + return new IatpParticipantRuntime(":edc-tests:runtime:iatp:runtime-memory-iatp-ih", + name, + properties, + keyPair); + } + + static IatpParticipantRuntime stsRuntime(String name, Map properties, KeyPair keyPair) { + return new IatpParticipantRuntime( + ":edc-tests:runtime:iatp:runtime-memory-sts", + name, + properties, + keyPair); + } + +} diff --git a/edc-tests/edc-controlplane/policy-tests/src/test/java/org/eclipse/tractusx/edc/tests/policy/AbstractPolicyMonitorTest.java b/edc-tests/edc-controlplane/policy-tests/src/test/java/org/eclipse/tractusx/edc/tests/policy/AbstractPolicyMonitorTest.java deleted file mode 100644 index e4dcc0b01..000000000 --- a/edc-tests/edc-controlplane/policy-tests/src/test/java/org/eclipse/tractusx/edc/tests/policy/AbstractPolicyMonitorTest.java +++ /dev/null @@ -1,120 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.tests.policy; - -import jakarta.json.Json; -import jakarta.json.JsonObject; -import okhttp3.mockwebserver.Dispatcher; -import okhttp3.mockwebserver.MockResponse; -import okhttp3.mockwebserver.MockWebServer; -import okhttp3.mockwebserver.RecordedRequest; -import org.eclipse.tractusx.edc.tests.TxParticipant; -import org.jetbrains.annotations.NotNull; -import org.junit.jupiter.api.Test; - -import java.io.IOException; -import java.util.Map; -import java.util.UUID; - -import static jakarta.json.Json.createObjectBuilder; -import static org.assertj.core.api.Assertions.assertThat; -import static org.awaitility.Awaitility.await; -import static org.eclipse.edc.connector.transfer.spi.types.TransferProcessStates.STARTED; -import static org.eclipse.edc.connector.transfer.spi.types.TransferProcessStates.TERMINATED; -import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.TYPE; -import static org.eclipse.edc.spi.CoreConstants.EDC_NAMESPACE; -import static org.eclipse.edc.test.system.utils.PolicyFixtures.inForceDatePolicy; -import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.PLATO_BPN; -import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.PLATO_NAME; -import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.SOKRATES_BPN; -import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.SOKRATES_NAME; -import static org.eclipse.tractusx.edc.tests.TxParticipant.ASYNC_TIMEOUT; - -public abstract class AbstractPolicyMonitorTest { - - protected static final TxParticipant SOKRATES = TxParticipant.Builder.newInstance() - .name(SOKRATES_NAME) - .id(SOKRATES_BPN) - .build(); - - - protected static final TxParticipant PLATO = TxParticipant.Builder.newInstance() - .name(PLATO_NAME) - .id(PLATO_BPN) - .build(); - private final MockWebServer server = new MockWebServer(); - - @Test - void shouldTerminateTransfer_whenPolicyExpires() throws IOException { - var assetId = UUID.randomUUID().toString(); - - Map dataAddress = Map.of( - "name", "transfer-test", - "baseUrl", "http://localhost:" + server.getPort(), - "type", "HttpData", - "contentType", "application/json", - "proxyQueryParams", "true" - ); - PLATO.createAsset(assetId, Map.of(), dataAddress); - startHttpServerProvider(); - - var policy = inForceDatePolicy("gteq", "contractAgreement+0s", "lteq", "contractAgreement+10s"); - var policyId = PLATO.createPolicyDefinition(policy); - PLATO.createContractDefinition(assetId, UUID.randomUUID().toString(), policyId, policyId); - - var consumerUrl = server.url("/mock/api/consumer"); - var destination = httpDataAddress(consumerUrl.toString()); - - var transferProcessId = SOKRATES.requestAsset(PLATO, assetId, Json.createObjectBuilder().build(), destination, "HttpData-PULL"); - await().atMost(ASYNC_TIMEOUT).untilAsserted(() -> { - var state = SOKRATES.getTransferProcessState(transferProcessId); - assertThat(state).isEqualTo(STARTED.name()); - }); - - await().atMost(ASYNC_TIMEOUT).untilAsserted(() -> { - var state = SOKRATES.getTransferProcessState(transferProcessId); - assertThat(state).isEqualTo(TERMINATED.name()); - }); - } - - private JsonObject httpDataAddress(String baseUrl) { - return createObjectBuilder() - .add(TYPE, EDC_NAMESPACE + "DataAddress") - .add(EDC_NAMESPACE + "type", "HttpData") - .add(EDC_NAMESPACE + "properties", createObjectBuilder() - .add(EDC_NAMESPACE + "baseUrl", baseUrl) - .build()) - .build(); - } - - private void startHttpServerProvider() throws IOException { - server.setDispatcher(new Dispatcher() { - @NotNull - @Override - public MockResponse dispatch(@NotNull RecordedRequest recordedRequest) { - if ("/mock/api/provider".equals(recordedRequest.getPath().split("\\?")[0])) { - return new MockResponse().setResponseCode(200); - } - return new MockResponse().setResponseCode(404); - } - }); - server.start(); - } -} diff --git a/edc-tests/edc-controlplane/policy-tests/src/test/java/org/eclipse/tractusx/edc/tests/policy/PolicyMonitorEndToEndTest.java b/edc-tests/edc-controlplane/policy-tests/src/test/java/org/eclipse/tractusx/edc/tests/policy/PolicyMonitorEndToEndTest.java new file mode 100644 index 000000000..793226960 --- /dev/null +++ b/edc-tests/edc-controlplane/policy-tests/src/test/java/org/eclipse/tractusx/edc/tests/policy/PolicyMonitorEndToEndTest.java @@ -0,0 +1,119 @@ +/******************************************************************************** + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +package org.eclipse.tractusx.edc.tests.policy; + +import jakarta.json.Json; +import org.eclipse.edc.junit.annotations.EndToEndTest; +import org.eclipse.edc.junit.annotations.PostgresqlIntegrationTest; +import org.eclipse.tractusx.edc.tests.participant.TransferParticipant; +import org.eclipse.tractusx.edc.tests.runtimes.ParticipantRuntime; +import org.eclipse.tractusx.edc.tests.runtimes.PgParticipantRuntime; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import java.util.Map; +import java.util.UUID; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.awaitility.Awaitility.await; +import static org.eclipse.edc.connector.transfer.spi.types.TransferProcessStates.STARTED; +import static org.eclipse.edc.connector.transfer.spi.types.TransferProcessStates.TERMINATED; +import static org.eclipse.edc.test.system.utils.PolicyFixtures.inForceDatePolicy; +import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.PLATO_BPN; +import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.PLATO_NAME; +import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.SOKRATES_BPN; +import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.SOKRATES_NAME; +import static org.eclipse.tractusx.edc.tests.helpers.TransferProcessHelperFunctions.createProxyRequest; +import static org.eclipse.tractusx.edc.tests.participant.TractusxParticipantBase.ASYNC_TIMEOUT; +import static org.eclipse.tractusx.edc.tests.runtimes.Runtimes.memoryRuntime; +import static org.eclipse.tractusx.edc.tests.runtimes.Runtimes.pgRuntime; + +public class PolicyMonitorEndToEndTest { + + protected static final TransferParticipant SOKRATES = TransferParticipant.Builder.newInstance() + .name(SOKRATES_NAME) + .id(SOKRATES_BPN) + .build(); + + + protected static final TransferParticipant PLATO = TransferParticipant.Builder.newInstance() + .name(PLATO_NAME) + .id(PLATO_BPN) + .build(); + + abstract static class Tests { + + @Test + void shouldTerminateTransfer_whenPolicyExpires() { + var assetId = UUID.randomUUID().toString(); + + Map dataAddress = Map.of( + "name", "transfer-test", + "baseUrl", "http://localhost:8080", + "type", "HttpData", + "contentType", "application/json", + "proxyQueryParams", "true" + ); + PLATO.createAsset(assetId, Map.of(), dataAddress); + + var policy = inForceDatePolicy("gteq", "contractAgreement+0s", "lteq", "contractAgreement+10s"); + var policyId = PLATO.createPolicyDefinition(policy); + PLATO.createContractDefinition(assetId, UUID.randomUUID().toString(), policyId, policyId); + + + var transferProcessId = SOKRATES.requestAsset(PLATO, assetId, Json.createObjectBuilder().build(), createProxyRequest(), "HttpData-PULL"); + await().atMost(ASYNC_TIMEOUT).untilAsserted(() -> { + var state = SOKRATES.getTransferProcessState(transferProcessId); + assertThat(state).isEqualTo(STARTED.name()); + }); + + await().atMost(ASYNC_TIMEOUT).untilAsserted(() -> { + var state = SOKRATES.getTransferProcessState(transferProcessId); + assertThat(state).isEqualTo(TERMINATED.name()); + }); + } + + } + + @Nested + @EndToEndTest + class InMemory extends Tests { + + @RegisterExtension + protected static final ParticipantRuntime SOKRATES_RUNTIME = memoryRuntime(SOKRATES.getName(), SOKRATES.getBpn(), SOKRATES.getConfiguration()); + + @RegisterExtension + protected static final ParticipantRuntime PLATO_RUNTIME = memoryRuntime(PLATO.getName(), PLATO.getBpn(), PLATO.getConfiguration()); + + } + + @Nested + @PostgresqlIntegrationTest + class Postgres extends Tests { + + @RegisterExtension + protected static final PgParticipantRuntime SOKRATES_RUNTIME = pgRuntime(SOKRATES.getName(), SOKRATES.getBpn(), SOKRATES.getConfiguration()); + + @RegisterExtension + protected static final PgParticipantRuntime PLATO_RUNTIME = pgRuntime(PLATO.getName(), PLATO.getBpn(), PLATO.getConfiguration()); + + } +} diff --git a/edc-tests/edc-controlplane/policy-tests/src/test/java/org/eclipse/tractusx/edc/tests/policy/PolicyMonitorInMemoryTest.java b/edc-tests/edc-controlplane/policy-tests/src/test/java/org/eclipse/tractusx/edc/tests/policy/PolicyMonitorInMemoryTest.java deleted file mode 100644 index 198e4d494..000000000 --- a/edc-tests/edc-controlplane/policy-tests/src/test/java/org/eclipse/tractusx/edc/tests/policy/PolicyMonitorInMemoryTest.java +++ /dev/null @@ -1,59 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.tests.policy; - -import com.nimbusds.jose.util.Base64; -import org.eclipse.edc.junit.annotations.EndToEndTest; -import org.eclipse.edc.spi.security.Vault; -import org.eclipse.tractusx.edc.tests.runtimes.ParticipantRuntime; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.extension.RegisterExtension; - -import java.security.SecureRandom; - -@EndToEndTest -public class PolicyMonitorInMemoryTest extends AbstractPolicyMonitorTest { - - @RegisterExtension - protected static final ParticipantRuntime SOKRATES_RUNTIME = new ParticipantRuntime( - ":edc-tests:runtime:runtime-memory", - SOKRATES.getName(), - SOKRATES.getBpn(), - SOKRATES.getConfiguration() - ); - - @RegisterExtension - protected static final ParticipantRuntime PLATO_RUNTIME = new ParticipantRuntime( - ":edc-tests:runtime:runtime-memory", - PLATO.getName(), - PLATO.getBpn(), - PLATO.getConfiguration() - ); - - @BeforeAll - static void prepare() { - var bytes = new byte[32]; - - new SecureRandom().nextBytes(bytes); - var value = Base64.encode(bytes).toString(); - SOKRATES_RUNTIME.getContext().getService(Vault.class).storeSecret("test-alias", value); - PLATO_RUNTIME.getContext().getService(Vault.class).storeSecret("test-alias", value); - } -} diff --git a/edc-tests/edc-controlplane/policy-tests/src/test/java/org/eclipse/tractusx/edc/tests/policy/PolicyMonitorPostgresqlTest.java b/edc-tests/edc-controlplane/policy-tests/src/test/java/org/eclipse/tractusx/edc/tests/policy/PolicyMonitorPostgresqlTest.java deleted file mode 100644 index b8ab7ed2b..000000000 --- a/edc-tests/edc-controlplane/policy-tests/src/test/java/org/eclipse/tractusx/edc/tests/policy/PolicyMonitorPostgresqlTest.java +++ /dev/null @@ -1,43 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.tests.policy; - -import org.eclipse.edc.junit.annotations.PostgresqlIntegrationTest; -import org.eclipse.tractusx.edc.tests.runtimes.PgParticipantRuntime; -import org.junit.jupiter.api.extension.RegisterExtension; - -@PostgresqlIntegrationTest -public class PolicyMonitorPostgresqlTest extends AbstractPolicyMonitorTest { - - @RegisterExtension - protected static final PgParticipantRuntime SOKRATES_RUNTIME = new PgParticipantRuntime( - ":edc-tests:runtime:runtime-postgresql", - SOKRATES.getName(), - SOKRATES.getBpn(), - SOKRATES.getConfiguration() - ); - @RegisterExtension - protected static final PgParticipantRuntime PLATO_RUNTIME = new PgParticipantRuntime( - ":edc-tests:runtime:runtime-postgresql", - PLATO.getName(), - PLATO.getBpn(), - PLATO.getConfiguration() - ); -} diff --git a/edc-tests/edc-controlplane/ssi-summarycred-tests/src/test/java/org/eclipse/tractusx/edc/tests/SsiParticipant.java b/edc-tests/edc-controlplane/ssi-summarycred-tests/src/test/java/org/eclipse/tractusx/edc/tests/MiwParticipant.java similarity index 72% rename from edc-tests/edc-controlplane/ssi-summarycred-tests/src/test/java/org/eclipse/tractusx/edc/tests/SsiParticipant.java rename to edc-tests/edc-controlplane/ssi-summarycred-tests/src/test/java/org/eclipse/tractusx/edc/tests/MiwParticipant.java index 38faa7f1c..ebe238996 100644 --- a/edc-tests/edc-controlplane/ssi-summarycred-tests/src/test/java/org/eclipse/tractusx/edc/tests/SsiParticipant.java +++ b/edc-tests/edc-controlplane/ssi-summarycred-tests/src/test/java/org/eclipse/tractusx/edc/tests/MiwParticipant.java @@ -19,13 +19,15 @@ package org.eclipse.tractusx.edc.tests; +import org.eclipse.tractusx.edc.tests.participant.TractusxParticipantBase; + import java.net.URI; import java.util.HashMap; import java.util.Map; import static org.eclipse.edc.util.io.Ports.getFreePort; -public class SsiParticipant { +public class MiwParticipant extends TractusxParticipantBase { private final URI miwUri = URI.create("http://localhost:" + getFreePort()); private final URI oauthTokenUri = URI.create("http://localhost:" + getFreePort()); @@ -33,8 +35,8 @@ public class SsiParticipant { /** * Returns the SSI configuration */ - public Map ssiConfiguration(TxParticipant forParticipant) { - var ssiConfiguration = new HashMap() { + public Map getConfiguration() { + return new HashMap<>(super.getConfiguration()) { { put("tx.ssi.miw.url", miwUri.toString()); put("tx.ssi.oauth.token.url", oauthTokenUri.toString()); @@ -43,12 +45,9 @@ public Map ssiConfiguration(TxParticipant forParticipant) { put("tx.ssi.miw.authority.id", "authorityId"); put("tx.ssi.miw.authority.issuer", "did:web:example.com"); put("tx.vault.seed.secrets", "client_secret_alias:client_secret"); - put("tx.ssi.endpoint.audience", forParticipant.getProtocolEndpoint().getUrl().toString()); + put("tx.ssi.endpoint.audience", getProtocolEndpoint().getUrl().toString()); } }; - var baseConfiguration = forParticipant.getConfiguration(); - ssiConfiguration.putAll(baseConfiguration); - return ssiConfiguration; } /** @@ -64,4 +63,21 @@ public URI miwEndpoint() { public URI authTokenEndpoint() { return oauthTokenUri; } + + public static class Builder extends TractusxParticipantBase.Builder { + + protected Builder() { + super(new MiwParticipant()); + } + + public static Builder newInstance() { + return new Builder(); + } + + @Override + public MiwParticipant build() { + super.build(); + return participant; + } + } } \ No newline at end of file diff --git a/edc-tests/edc-controlplane/ssi-summarycred-tests/src/test/java/org/eclipse/tractusx/edc/tests/negotiation/AbstractContractNegotiateTest.java b/edc-tests/edc-controlplane/ssi-summarycred-tests/src/test/java/org/eclipse/tractusx/edc/tests/negotiation/AbstractContractNegotiateTest.java index 59a17559b..2ea74e8f9 100644 --- a/edc-tests/edc-controlplane/ssi-summarycred-tests/src/test/java/org/eclipse/tractusx/edc/tests/negotiation/AbstractContractNegotiateTest.java +++ b/edc-tests/edc-controlplane/ssi-summarycred-tests/src/test/java/org/eclipse/tractusx/edc/tests/negotiation/AbstractContractNegotiateTest.java @@ -21,8 +21,7 @@ import org.eclipse.edc.connector.contract.spi.types.negotiation.ContractNegotiationStates; import org.eclipse.edc.policy.model.Operator; -import org.eclipse.tractusx.edc.tests.SsiParticipant; -import org.eclipse.tractusx.edc.tests.TxParticipant; +import org.eclipse.tractusx.edc.tests.MiwParticipant; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -35,24 +34,22 @@ import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.PLATO_NAME; import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.SOKRATES_BPN; import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.SOKRATES_NAME; -import static org.eclipse.tractusx.edc.tests.TxParticipant.ASYNC_POLL_INTERVAL; -import static org.eclipse.tractusx.edc.tests.TxParticipant.ASYNC_TIMEOUT; import static org.eclipse.tractusx.edc.tests.helpers.PolicyHelperFunctions.bpnGroupPolicy; import static org.eclipse.tractusx.edc.tests.helpers.PolicyHelperFunctions.frameworkPolicy; +import static org.eclipse.tractusx.edc.tests.participant.TractusxParticipantBase.ASYNC_POLL_INTERVAL; +import static org.eclipse.tractusx.edc.tests.participant.TractusxParticipantBase.ASYNC_TIMEOUT; public abstract class AbstractContractNegotiateTest { - protected static final TxParticipant SOKRATES = TxParticipant.Builder.newInstance() + protected static final MiwParticipant SOKRATES = MiwParticipant.Builder.newInstance() .name(SOKRATES_NAME) .id(SOKRATES_BPN) .build(); - protected static final TxParticipant PLATO = TxParticipant.Builder.newInstance() + protected static final MiwParticipant PLATO = MiwParticipant.Builder.newInstance() .name(PLATO_NAME) .id(PLATO_BPN) .build(); - protected static final SsiParticipant PLATO_SSI = new SsiParticipant(); - protected static final SsiParticipant SOKRATES_SSI = new SsiParticipant(); @Test diff --git a/edc-tests/edc-controlplane/ssi-summarycred-tests/src/test/java/org/eclipse/tractusx/edc/tests/negotiation/SsiContractNegotiationInMemoryTest.java b/edc-tests/edc-controlplane/ssi-summarycred-tests/src/test/java/org/eclipse/tractusx/edc/tests/negotiation/SsiContractNegotiationInMemoryTest.java index f28900b7c..baf01089d 100644 --- a/edc-tests/edc-controlplane/ssi-summarycred-tests/src/test/java/org/eclipse/tractusx/edc/tests/negotiation/SsiContractNegotiationInMemoryTest.java +++ b/edc-tests/edc-controlplane/ssi-summarycred-tests/src/test/java/org/eclipse/tractusx/edc/tests/negotiation/SsiContractNegotiationInMemoryTest.java @@ -43,7 +43,7 @@ public class SsiContractNegotiationInMemoryTest extends AbstractContractNegotiat ":edc-tests:runtime:runtime-memory-ssi", PLATO.getName(), PLATO.getBpn(), - PLATO_SSI.ssiConfiguration(PLATO) + PLATO.getConfiguration() ); @RegisterExtension @@ -51,7 +51,7 @@ public class SsiContractNegotiationInMemoryTest extends AbstractContractNegotiat ":edc-tests:runtime:runtime-memory-ssi", SOKRATES.getName(), SOKRATES.getBpn(), - SOKRATES_SSI.ssiConfiguration(SOKRATES) + SOKRATES.getConfiguration() ); private static MockWebServer miwSokratesServer; private static MockWebServer miwPlatoServer; @@ -69,16 +69,16 @@ static void setup() throws IOException { var credentialSubjectId = "did:web:example.com"; - miwSokratesServer.start(SOKRATES_SSI.miwEndpoint().getPort()); + miwSokratesServer.start(SOKRATES.miwEndpoint().getPort()); miwSokratesServer.setDispatcher(new MiwDispatcher(SOKRATES_BPN, SUMMARY_VC_TEMPLATE, credentialSubjectId, PLATO.getProtocolEndpoint().getUrl().toString())); - miwPlatoServer.start(PLATO_SSI.miwEndpoint().getPort()); + miwPlatoServer.start(PLATO.miwEndpoint().getPort()); miwPlatoServer.setDispatcher(new MiwDispatcher(PLATO_BPN, SUMMARY_VC_TEMPLATE, credentialSubjectId, SOKRATES.getProtocolEndpoint().getUrl().toString())); - sokratesOauthServer.start(SOKRATES_SSI.authTokenEndpoint().getPort()); + sokratesOauthServer.start(SOKRATES.authTokenEndpoint().getPort()); sokratesOauthServer.setDispatcher(new KeycloakDispatcher()); - platoOauthServer.start(PLATO_SSI.authTokenEndpoint().getPort()); + platoOauthServer.start(PLATO.authTokenEndpoint().getPort()); platoOauthServer.setDispatcher(new KeycloakDispatcher()); } diff --git a/edc-tests/edc-controlplane/ssi-summarycred-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/AbstractHttpConsumerPullWithProxyTest.java b/edc-tests/edc-controlplane/ssi-summarycred-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/AbstractHttpConsumerPullWithProxyTest.java deleted file mode 100644 index 7c77cc296..000000000 --- a/edc-tests/edc-controlplane/ssi-summarycred-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/AbstractHttpConsumerPullWithProxyTest.java +++ /dev/null @@ -1,145 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.tests.transfer; - -import jakarta.json.Json; -import jakarta.json.JsonObject; -import okhttp3.mockwebserver.MockResponse; -import okhttp3.mockwebserver.MockWebServer; -import org.eclipse.edc.connector.transfer.spi.types.TransferProcessStates; -import org.eclipse.tractusx.edc.tests.SsiParticipant; -import org.eclipse.tractusx.edc.tests.TxParticipant; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import java.io.IOException; -import java.util.Map; -import java.util.concurrent.atomic.AtomicReference; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.awaitility.Awaitility.await; -import static org.awaitility.pollinterval.FibonacciPollInterval.fibonacci; -import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.TYPE; -import static org.eclipse.edc.spi.CoreConstants.EDC_NAMESPACE; -import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.PLATO_BPN; -import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.PLATO_NAME; -import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.SOKRATES_BPN; -import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.SOKRATES_NAME; -import static org.eclipse.tractusx.edc.tests.TxParticipant.ASYNC_TIMEOUT; -import static org.eclipse.tractusx.edc.tests.helpers.PolicyHelperFunctions.bnpPolicy; - -public abstract class AbstractHttpConsumerPullWithProxyTest { - - protected static final TxParticipant SOKRATES = (TxParticipant.Builder.newInstance() - .name(SOKRATES_NAME) - .id(SOKRATES_BPN) - .build()); - - protected static final TxParticipant PLATO = (TxParticipant.Builder.newInstance() - .name(PLATO_NAME) - .id(PLATO_BPN) - .build()); - - protected static final SsiParticipant PLATO_SSI = new SsiParticipant(); - protected static final SsiParticipant SOKRATES_SSI = new SsiParticipant(); - - protected MockWebServer server; - - @BeforeEach - void setup() throws IOException { - server = new MockWebServer(); - } - - @Test - void transferData_privateBackend() throws IOException, InterruptedException { - var assetId = "api-asset-1"; - var url = server.url("/mock/api"); - server.start(); - - var authCodeHeaderName = "test-authkey"; - var authCode = "test-authcode"; - - Map dataAddress = Map.of( - "baseUrl", url.toString(), - "type", "HttpData", - "contentType", "application/json", - "authKey", authCodeHeaderName, - "authCode", authCode - ); - - PLATO.createAsset(assetId, Map.of(), dataAddress); - - var accessPolicyId = PLATO.createPolicyDefinition(createAccessPolicy(SOKRATES.getBpn())); - var contractPolicyId = PLATO.createPolicyDefinition(createContractPolicy(SOKRATES.getBpn())); - PLATO.createContractDefinition(assetId, "def-1", accessPolicyId, contractPolicyId); - var transferProcessId = SOKRATES.requestAsset(PLATO, assetId, Json.createObjectBuilder().build(), createProxyRequest(), "HttpData-PULL"); - - var contractAgreementId = new AtomicReference(); - var edr = new AtomicReference(); - - // wait until transfer process completes - await().pollInterval(fibonacci()) - .atMost(ASYNC_TIMEOUT) - .untilAsserted(() -> { - var tpState = SOKRATES.getTransferProcessState(transferProcessId); - assertThat(tpState).isNotNull().isEqualTo(TransferProcessStates.STARTED.toString()); - }); - - // wait until EDC is available on the consumer side - server.enqueue(new MockResponse().setBody("test response").setResponseCode(200)); - await().pollInterval(fibonacci()) - .atMost(ASYNC_TIMEOUT) - .untilAsserted(() -> { - edr.set(SOKRATES.edrs().getEdr(transferProcessId)); - assertThat(edr).isNotNull(); - }); - - // pull data out of provider's backend service: - // Cons-DP -> Prov-DP -> Prov-backend - assertThat(SOKRATES.data().pullData(edr.get(), Map.of())).isEqualTo("test response"); - var rq = server.takeRequest(); - assertThat(rq.getHeader(authCodeHeaderName)).isEqualTo(authCode); - assertThat(rq.getHeader("Edc-Contract-Agreement-Id")).isNotNull(); - assertThat(rq.getHeader("Edc-Bpn")).isEqualTo(SOKRATES.getBpn()); - assertThat(rq.getMethod()).isEqualToIgnoringCase("GET"); - } - - @AfterEach - void teardown() throws IOException { - server.shutdown(); - } - - protected JsonObject createAccessPolicy(String bpn) { - return bnpPolicy(bpn); - } - - protected JsonObject createContractPolicy(String bpn) { - return bnpPolicy(bpn); - } - - private JsonObject createProxyRequest() { - return Json.createObjectBuilder() - .add(TYPE, EDC_NAMESPACE + "DataAddress") - .add(EDC_NAMESPACE + "type", "HttpProxy") - .build(); - - } -} diff --git a/edc-tests/edc-controlplane/ssi-summarycred-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/SsiHttpConsumerPullWithProxyInMemoryTest.java b/edc-tests/edc-controlplane/ssi-summarycred-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/SsiHttpConsumerPullWithProxyInMemoryTest.java index db071c67a..4335630a2 100644 --- a/edc-tests/edc-controlplane/ssi-summarycred-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/SsiHttpConsumerPullWithProxyInMemoryTest.java +++ b/edc-tests/edc-controlplane/ssi-summarycred-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/SsiHttpConsumerPullWithProxyInMemoryTest.java @@ -24,6 +24,8 @@ import org.eclipse.edc.junit.annotations.EndToEndTest; import org.eclipse.tractusx.edc.tests.KeycloakDispatcher; import org.eclipse.tractusx.edc.tests.MiwDispatcher; +import org.eclipse.tractusx.edc.tests.MiwParticipant; +import org.eclipse.tractusx.edc.tests.participant.TractusxParticipantBase; import org.eclipse.tractusx.edc.tests.runtimes.ParticipantRuntime; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; @@ -34,27 +36,37 @@ import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.TX_NAMESPACE; import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.PLATO_BPN; +import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.PLATO_NAME; import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.SOKRATES_BPN; +import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.SOKRATES_NAME; import static org.eclipse.tractusx.edc.tests.helpers.PolicyHelperFunctions.frameworkPolicy; @EndToEndTest -public class SsiHttpConsumerPullWithProxyInMemoryTest extends AbstractHttpConsumerPullWithProxyTest { +public class SsiHttpConsumerPullWithProxyInMemoryTest extends HttpConsumerPullBaseTest { public static final String SUMMARY_VC_TEMPLATE = "summary-vc.json"; + protected static final MiwParticipant SOKRATES = MiwParticipant.Builder.newInstance() + .name(SOKRATES_NAME) + .id(SOKRATES_BPN) + .build(); + protected static final MiwParticipant PLATO = MiwParticipant.Builder.newInstance() + .name(PLATO_NAME) + .id(PLATO_BPN) + .build(); @RegisterExtension protected static final ParticipantRuntime SOKRATES_RUNTIME = new ParticipantRuntime( ":edc-tests:runtime:runtime-memory-ssi", SOKRATES.getName(), SOKRATES.getBpn(), - SOKRATES_SSI.ssiConfiguration(SOKRATES) + SOKRATES.getConfiguration() ); @RegisterExtension protected static final ParticipantRuntime PLATO_RUNTIME = new ParticipantRuntime( ":edc-tests:runtime:runtime-memory-ssi", PLATO.getName(), PLATO.getBpn(), - PLATO_SSI.ssiConfiguration(PLATO) + PLATO.getConfiguration() ); private static MockWebServer sokratesOauthServer; @@ -71,16 +83,16 @@ static void prepare() throws IOException { var credentialSubjectId = "did:web:example.com"; - miwSokratesServer.start(SOKRATES_SSI.miwEndpoint().getPort()); + miwSokratesServer.start(SOKRATES.miwEndpoint().getPort()); miwSokratesServer.setDispatcher(new MiwDispatcher(SOKRATES_BPN, SUMMARY_VC_TEMPLATE, credentialSubjectId, PLATO.getProtocolEndpoint().getUrl().toString())); - miwPlatoServer.start(PLATO_SSI.miwEndpoint().getPort()); + miwPlatoServer.start(PLATO.miwEndpoint().getPort()); miwPlatoServer.setDispatcher(new MiwDispatcher(PLATO_BPN, SUMMARY_VC_TEMPLATE, credentialSubjectId, SOKRATES.getProtocolEndpoint().getUrl().toString())); - sokratesOauthServer.start(SOKRATES_SSI.authTokenEndpoint().getPort()); + sokratesOauthServer.start(SOKRATES.authTokenEndpoint().getPort()); sokratesOauthServer.setDispatcher(new KeycloakDispatcher()); - platoOauthServer.start(PLATO_SSI.authTokenEndpoint().getPort()); + platoOauthServer.start(PLATO.authTokenEndpoint().getPort()); platoOauthServer.setDispatcher(new KeycloakDispatcher()); } @@ -92,6 +104,16 @@ static void unwind() throws IOException { platoOauthServer.shutdown(); } + @Override + public TractusxParticipantBase plato() { + return PLATO; + } + + @Override + public TractusxParticipantBase sokrates() { + return SOKRATES; + } + @Override protected JsonObject createAccessPolicy(String bpn) { return frameworkPolicy(Map.of(TX_NAMESPACE + "Dismantler", "active")); diff --git a/edc-tests/edc-controlplane/transfer-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/AbstractHttpConsumerPullWithProxyTest.java b/edc-tests/edc-controlplane/transfer-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/AbstractHttpConsumerPullWithProxyTest.java deleted file mode 100644 index 8e41f23df..000000000 --- a/edc-tests/edc-controlplane/transfer-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/AbstractHttpConsumerPullWithProxyTest.java +++ /dev/null @@ -1,131 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.tests.transfer; - -import jakarta.json.Json; -import jakarta.json.JsonObject; -import org.eclipse.edc.connector.transfer.spi.types.TransferProcessStates; -import org.eclipse.tractusx.edc.tests.TxParticipant; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.mockserver.integration.ClientAndServer; -import org.mockserver.verify.VerificationTimes; - -import java.util.Map; -import java.util.concurrent.atomic.AtomicReference; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.awaitility.Awaitility.await; -import static org.awaitility.pollinterval.FibonacciPollInterval.fibonacci; -import static org.eclipse.edc.util.io.Ports.getFreePort; -import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.PLATO_BPN; -import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.PLATO_NAME; -import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.SOKRATES_BPN; -import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.SOKRATES_NAME; -import static org.eclipse.tractusx.edc.tests.TxParticipant.ASYNC_TIMEOUT; -import static org.eclipse.tractusx.edc.tests.helpers.PolicyHelperFunctions.bnpPolicy; -import static org.eclipse.tractusx.edc.tests.transfer.TransferProcessHelperFunctions.createProxyRequest; -import static org.mockserver.model.HttpRequest.request; -import static org.mockserver.model.HttpResponse.response; - -public abstract class AbstractHttpConsumerPullWithProxyTest { - - public static final String MOCK_BACKEND_REMOTEHOST = "localhost"; - public static final String MOCK_BACKEND_PATH = "/mock/api"; - protected static final TxParticipant SOKRATES = TxParticipant.Builder.newInstance() - .name(SOKRATES_NAME) - .id(SOKRATES_BPN) - .build(); - protected static final TxParticipant PLATO = TxParticipant.Builder.newInstance() - .name(PLATO_NAME) - .id(PLATO_BPN) - .build(); - protected ClientAndServer server; - private String privateBackendUrl; - - @BeforeEach - void setup() { - server = ClientAndServer.startClientAndServer(MOCK_BACKEND_REMOTEHOST, getFreePort()); - privateBackendUrl = "http://%s:%d%s".formatted(MOCK_BACKEND_REMOTEHOST, server.getPort(), MOCK_BACKEND_PATH); - } - - @Test - void transferData_privateBackend() { - var assetId = "api-asset-1"; - - - Map dataAddress = Map.of( - "baseUrl", privateBackendUrl, - "type", "HttpData", - "contentType", "application/json" - ); - - PLATO.createAsset(assetId, Map.of(), dataAddress); - - var accessPolicyId = PLATO.createPolicyDefinition(createAccessPolicy(SOKRATES.getBpn())); - var contractPolicyId = PLATO.createPolicyDefinition(createContractPolicy(SOKRATES.getBpn())); - PLATO.createContractDefinition(assetId, "def-1", accessPolicyId, contractPolicyId); - var transferProcessId = SOKRATES.requestAsset(PLATO, assetId, Json.createObjectBuilder().build(), createProxyRequest()); - - var edr = new AtomicReference(); - - // wait until transfer process completes - await().pollInterval(fibonacci()) - .atMost(ASYNC_TIMEOUT) - .untilAsserted(() -> { - var tpState = SOKRATES.getTransferProcessState(transferProcessId); - assertThat(tpState).isNotNull().isEqualTo(TransferProcessStates.STARTED.toString()); - }); - - // wait until EDC is available on the consumer side - server.when(request().withMethod("GET").withPath(MOCK_BACKEND_PATH)).respond(response().withStatusCode(200).withBody("test response")); - await().pollInterval(fibonacci()) - .atMost(ASYNC_TIMEOUT) - .untilAsserted(() -> { - edr.set(SOKRATES.edrs().getEdr(transferProcessId)); - assertThat(edr).isNotNull(); - }); - - // pull data out of provider's backend service: - // Prov-DP -> Prov-backend - assertThat(SOKRATES.data().pullData(edr.get(), Map.of())).isEqualTo("test response"); - - server.verify(request() - .withPath(MOCK_BACKEND_PATH) - .withHeader("Edc-Contract-Agreement-Id") - .withHeader("Edc-Bpn", SOKRATES_BPN) - .withMethod("GET"), VerificationTimes.exactly(1)); - - } - - @AfterEach - void teardown() { - server.stop(); - } - - protected JsonObject createAccessPolicy(String bpn) { - return bnpPolicy(bpn); - } - - protected JsonObject createContractPolicy(String bpn) { - return bnpPolicy(bpn); - } -} diff --git a/edc-tests/edc-controlplane/transfer-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/HttpConsumerPullWithProxyInMemoryTest.java b/edc-tests/edc-controlplane/transfer-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/HttpConsumerPullWithProxyInMemoryTest.java deleted file mode 100644 index e86b25f23..000000000 --- a/edc-tests/edc-controlplane/transfer-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/HttpConsumerPullWithProxyInMemoryTest.java +++ /dev/null @@ -1,62 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.tests.transfer; - -import com.nimbusds.jose.util.Base64; -import org.eclipse.edc.junit.annotations.EndToEndTest; -import org.eclipse.edc.spi.security.Vault; -import org.eclipse.tractusx.edc.tests.runtimes.ParticipantRuntime; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.extension.RegisterExtension; - -import java.security.SecureRandom; - -@EndToEndTest -public class HttpConsumerPullWithProxyInMemoryTest extends AbstractHttpConsumerPullWithProxyTest { - - @RegisterExtension - protected static final ParticipantRuntime SOKRATES_RUNTIME = new ParticipantRuntime( - ":edc-tests:runtime:runtime-memory", - SOKRATES.getName(), - SOKRATES.getBpn(), - SOKRATES.getConfiguration() - ); - - @RegisterExtension - protected static final ParticipantRuntime PLATO_RUNTIME = new ParticipantRuntime( - ":edc-tests:runtime:runtime-memory", - PLATO.getName(), - PLATO.getBpn(), - PLATO.getConfiguration() - ); - - @BeforeAll - static void prepare() { - var bytes = new byte[32]; - - new SecureRandom().nextBytes(bytes); - var value = Base64.encode(bytes).toString(); - var vault = SOKRATES_RUNTIME.getContext().getService(Vault.class); - vault.storeSecret("test-alias", value); - vault = PLATO_RUNTIME.getContext().getService(Vault.class); - vault.storeSecret("test-alias", value); - - } -} diff --git a/edc-tests/edc-controlplane/transfer-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/HttpConsumerPullWithProxyPostgresqlTest.java b/edc-tests/edc-controlplane/transfer-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/HttpConsumerPullWithProxyPostgresqlTest.java deleted file mode 100644 index d1002cbd8..000000000 --- a/edc-tests/edc-controlplane/transfer-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/HttpConsumerPullWithProxyPostgresqlTest.java +++ /dev/null @@ -1,45 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.tests.transfer; - -import org.eclipse.edc.junit.annotations.PostgresqlIntegrationTest; -import org.eclipse.tractusx.edc.tests.runtimes.PgParticipantRuntime; -import org.junit.jupiter.api.extension.RegisterExtension; - -@PostgresqlIntegrationTest -public class HttpConsumerPullWithProxyPostgresqlTest extends AbstractHttpConsumerPullWithProxyTest { - - - @RegisterExtension - protected static final PgParticipantRuntime SOKRATES_RUNTIME = new PgParticipantRuntime( - ":edc-tests:runtime:runtime-postgresql", - SOKRATES.getName(), - SOKRATES.getBpn(), - SOKRATES.getConfiguration() - ); - @RegisterExtension - protected static final PgParticipantRuntime PLATO_RUNTIME = new PgParticipantRuntime( - ":edc-tests:runtime:runtime-postgresql", - PLATO.getName(), - PLATO.getBpn(), - PLATO.getConfiguration() - ); - -} diff --git a/edc-tests/edc-controlplane/transfer-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/HttpProviderPushInMemoryTest.java b/edc-tests/edc-controlplane/transfer-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/HttpProviderPushInMemoryTest.java deleted file mode 100644 index dd481bd53..000000000 --- a/edc-tests/edc-controlplane/transfer-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/HttpProviderPushInMemoryTest.java +++ /dev/null @@ -1,44 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.tests.transfer; - -import org.eclipse.edc.junit.annotations.EndToEndTest; -import org.eclipse.tractusx.edc.tests.runtimes.ParticipantRuntime; -import org.junit.jupiter.api.extension.RegisterExtension; - -@EndToEndTest -public class HttpProviderPushInMemoryTest extends AbstractHttpProviderPushTest { - - @RegisterExtension - protected static final ParticipantRuntime SOKRATES_RUNTIME = new ParticipantRuntime( - ":edc-tests:runtime:runtime-memory", - SOKRATES.getName(), - SOKRATES.getBpn(), - SOKRATES.getConfiguration() - ); - - @RegisterExtension - protected static final ParticipantRuntime PLATO_RUNTIME = new ParticipantRuntime( - ":edc-tests:runtime:runtime-memory", - PLATO.getName(), - PLATO.getBpn(), - PLATO.getConfiguration() - ); -} diff --git a/edc-tests/edc-controlplane/transfer-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/HttpProviderPushInPostgresqlTest.java b/edc-tests/edc-controlplane/transfer-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/HttpProviderPushInPostgresqlTest.java deleted file mode 100644 index 79bd34a2d..000000000 --- a/edc-tests/edc-controlplane/transfer-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/HttpProviderPushInPostgresqlTest.java +++ /dev/null @@ -1,43 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.tests.transfer; - -import org.eclipse.edc.junit.annotations.PostgresqlIntegrationTest; -import org.eclipse.tractusx.edc.tests.runtimes.PgParticipantRuntime; -import org.junit.jupiter.api.extension.RegisterExtension; - -@PostgresqlIntegrationTest -public class HttpProviderPushInPostgresqlTest extends AbstractHttpProviderPushTest { - - @RegisterExtension - protected static final PgParticipantRuntime SOKRATES_RUNTIME = new PgParticipantRuntime( - ":edc-tests:runtime:runtime-postgresql", - SOKRATES.getName(), - SOKRATES.getBpn(), - SOKRATES.getConfiguration() - ); - @RegisterExtension - protected static final PgParticipantRuntime PLATO_RUNTIME = new PgParticipantRuntime( - ":edc-tests:runtime:runtime-postgresql", - PLATO.getName(), - PLATO.getBpn(), - PLATO.getConfiguration() - ); -} diff --git a/edc-tests/edc-controlplane/transfer-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/TransferPullEndToEndTest.java b/edc-tests/edc-controlplane/transfer-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/TransferPullEndToEndTest.java new file mode 100644 index 000000000..ddd2a983f --- /dev/null +++ b/edc-tests/edc-controlplane/transfer-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/TransferPullEndToEndTest.java @@ -0,0 +1,86 @@ +/******************************************************************************** + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +package org.eclipse.tractusx.edc.tests.transfer; + +import org.eclipse.edc.junit.annotations.EndToEndTest; +import org.eclipse.edc.junit.annotations.PostgresqlIntegrationTest; +import org.eclipse.tractusx.edc.tests.participant.TractusxParticipantBase; +import org.eclipse.tractusx.edc.tests.participant.TransferParticipant; +import org.eclipse.tractusx.edc.tests.runtimes.ParticipantRuntime; +import org.eclipse.tractusx.edc.tests.runtimes.PgParticipantRuntime; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.extension.RegisterExtension; + +import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.PLATO_BPN; +import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.PLATO_NAME; +import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.SOKRATES_BPN; +import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.SOKRATES_NAME; +import static org.eclipse.tractusx.edc.tests.runtimes.Runtimes.memoryRuntime; +import static org.eclipse.tractusx.edc.tests.runtimes.Runtimes.pgRuntime; + +public class TransferPullEndToEndTest { + + abstract static class Tests extends HttpConsumerPullBaseTest { + + protected static final TransferParticipant SOKRATES = TransferParticipant.Builder.newInstance() + .name(SOKRATES_NAME) + .id(SOKRATES_BPN) + .build(); + protected static final TransferParticipant PLATO = TransferParticipant.Builder.newInstance() + .name(PLATO_NAME) + .id(PLATO_BPN) + .build(); + + @Override + public TractusxParticipantBase plato() { + return PLATO; + } + + @Override + public TractusxParticipantBase sokrates() { + return SOKRATES; + } + + } + + @Nested + @EndToEndTest + class InMemory extends Tests { + + @RegisterExtension + protected static final ParticipantRuntime SOKRATES_RUNTIME = memoryRuntime(SOKRATES.getName(), SOKRATES.getBpn(), SOKRATES.getConfiguration()); + + @RegisterExtension + protected static final ParticipantRuntime PLATO_RUNTIME = memoryRuntime(PLATO.getName(), PLATO.getBpn(), PLATO.getConfiguration()); + + } + + @Nested + @PostgresqlIntegrationTest + class Postgres extends Tests { + + @RegisterExtension + protected static final PgParticipantRuntime SOKRATES_RUNTIME = pgRuntime(SOKRATES.getName(), SOKRATES.getBpn(), SOKRATES.getConfiguration()); + + @RegisterExtension + protected static final PgParticipantRuntime PLATO_RUNTIME = pgRuntime(PLATO.getName(), PLATO.getBpn(), PLATO.getConfiguration()); + + } +} \ No newline at end of file diff --git a/edc-tests/edc-controlplane/transfer-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/TransferPushEndToEndTest.java b/edc-tests/edc-controlplane/transfer-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/TransferPushEndToEndTest.java new file mode 100644 index 000000000..ad9d34e71 --- /dev/null +++ b/edc-tests/edc-controlplane/transfer-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/TransferPushEndToEndTest.java @@ -0,0 +1,86 @@ +/******************************************************************************** + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +package org.eclipse.tractusx.edc.tests.transfer; + +import org.eclipse.edc.junit.annotations.EndToEndTest; +import org.eclipse.edc.junit.annotations.PostgresqlIntegrationTest; +import org.eclipse.tractusx.edc.tests.participant.TractusxParticipantBase; +import org.eclipse.tractusx.edc.tests.participant.TransferParticipant; +import org.eclipse.tractusx.edc.tests.runtimes.ParticipantRuntime; +import org.eclipse.tractusx.edc.tests.runtimes.PgParticipantRuntime; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.extension.RegisterExtension; + +import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.PLATO_BPN; +import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.PLATO_NAME; +import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.SOKRATES_BPN; +import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.SOKRATES_NAME; +import static org.eclipse.tractusx.edc.tests.runtimes.Runtimes.memoryRuntime; +import static org.eclipse.tractusx.edc.tests.runtimes.Runtimes.pgRuntime; + +public class TransferPushEndToEndTest { + + abstract static class Tests extends ProviderPushBaseTest { + + protected static final TransferParticipant SOKRATES = TransferParticipant.Builder.newInstance() + .name(SOKRATES_NAME) + .id(SOKRATES_BPN) + .build(); + protected static final TransferParticipant PLATO = TransferParticipant.Builder.newInstance() + .name(PLATO_NAME) + .id(PLATO_BPN) + .build(); + + @Override + public TractusxParticipantBase plato() { + return PLATO; + } + + @Override + public TractusxParticipantBase sokrates() { + return SOKRATES; + } + + } + + @Nested + @EndToEndTest + class InMemory extends Tests { + + @RegisterExtension + protected static final ParticipantRuntime SOKRATES_RUNTIME = memoryRuntime(SOKRATES.getName(), SOKRATES.getBpn(), SOKRATES.getConfiguration()); + + @RegisterExtension + protected static final ParticipantRuntime PLATO_RUNTIME = memoryRuntime(PLATO.getName(), PLATO.getBpn(), PLATO.getConfiguration()); + + } + + @Nested + @PostgresqlIntegrationTest + class Postgres extends Tests { + + @RegisterExtension + protected static final PgParticipantRuntime SOKRATES_RUNTIME = pgRuntime(SOKRATES.getName(), SOKRATES.getBpn(), SOKRATES.getConfiguration()); + + @RegisterExtension + protected static final PgParticipantRuntime PLATO_RUNTIME = pgRuntime(PLATO.getName(), PLATO.getBpn(), PLATO.getConfiguration()); + + } +} \ No newline at end of file diff --git a/edc-tests/edc-controlplane/transfer-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/TransferWithTokenRefreshTest.java b/edc-tests/edc-controlplane/transfer-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/TransferWithTokenRefreshTest.java index 2134525c5..d82e6edce 100644 --- a/edc-tests/edc-controlplane/transfer-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/TransferWithTokenRefreshTest.java +++ b/edc-tests/edc-controlplane/transfer-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/TransferWithTokenRefreshTest.java @@ -19,23 +19,19 @@ package org.eclipse.tractusx.edc.tests.transfer; -import com.nimbusds.jose.util.Base64; import jakarta.json.Json; import jakarta.json.JsonObject; import org.eclipse.edc.connector.transfer.spi.types.TransferProcessStates; import org.eclipse.edc.junit.annotations.EndToEndTest; -import org.eclipse.edc.spi.security.Vault; -import org.eclipse.tractusx.edc.tests.TxParticipant; +import org.eclipse.tractusx.edc.tests.participant.TransferParticipant; import org.eclipse.tractusx.edc.tests.runtimes.ParticipantRuntime; import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; import org.mockserver.integration.ClientAndServer; import org.mockserver.verify.VerificationTimes; -import java.security.SecureRandom; import java.time.Duration; import java.util.HashMap; import java.util.Map; @@ -50,9 +46,10 @@ import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.PLATO_NAME; import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.SOKRATES_BPN; import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.SOKRATES_NAME; -import static org.eclipse.tractusx.edc.tests.TxParticipant.ASYNC_TIMEOUT; import static org.eclipse.tractusx.edc.tests.helpers.PolicyHelperFunctions.bnpPolicy; -import static org.eclipse.tractusx.edc.tests.transfer.TransferProcessHelperFunctions.createProxyRequest; +import static org.eclipse.tractusx.edc.tests.helpers.TransferProcessHelperFunctions.createProxyRequest; +import static org.eclipse.tractusx.edc.tests.participant.TractusxParticipantBase.ASYNC_TIMEOUT; +import static org.eclipse.tractusx.edc.tests.runtimes.Runtimes.memoryRuntime; import static org.mockserver.model.HttpRequest.request; import static org.mockserver.model.HttpResponse.response; @@ -64,46 +61,26 @@ @EndToEndTest public class TransferWithTokenRefreshTest { - public static final String MOCK_BACKEND_REMOTEHOST = "localhost"; + public static final String MOCK_BACKEND_REMOTE_HOST = "localhost"; public static final String MOCK_BACKEND_PATH = "/mock/api"; - protected static final TxParticipant SOKRATES = TxParticipant.Builder.newInstance() + protected static final TransferParticipant SOKRATES = TransferParticipant.Builder.newInstance() .name(SOKRATES_NAME) .id(SOKRATES_BPN) .build(); - protected static final TxParticipant PLATO = TxParticipant.Builder.newInstance() + protected static final TransferParticipant PLATO = TransferParticipant.Builder.newInstance() .name(PLATO_NAME) .id(PLATO_BPN) .build(); + @RegisterExtension - protected static final ParticipantRuntime SOKRATES_RUNTIME = new ParticipantRuntime( - ":edc-tests:runtime:runtime-memory", - SOKRATES.getName(), - SOKRATES.getBpn(), - SOKRATES.getConfiguration() - ); + protected static final ParticipantRuntime SOKRATES_RUNTIME = memoryRuntime(SOKRATES.getName(), SOKRATES.getBpn(), SOKRATES.getConfiguration()); private static final Long VERY_SHORT_TOKEN_EXPIRY = 3L; + @RegisterExtension - protected static final ParticipantRuntime PLATO_RUNTIME = new ParticipantRuntime( - ":edc-tests:runtime:runtime-memory", - PLATO.getName(), - PLATO.getBpn(), - forConfig(PLATO.getConfiguration()) - ); + protected static final ParticipantRuntime PLATO_RUNTIME = memoryRuntime(PLATO.getName(), PLATO.getBpn(), forConfig(PLATO.getConfiguration())); protected ClientAndServer server; private String privateBackendUrl; - @BeforeAll - static void prepare() { - var bytes = new byte[32]; - - new SecureRandom().nextBytes(bytes); - var value = Base64.encode(bytes).toString(); - var vault = SOKRATES_RUNTIME.getContext().getService(Vault.class); - vault.storeSecret("test-alias", value); - vault = PLATO_RUNTIME.getContext().getService(Vault.class); - vault.storeSecret("test-alias", value); - - } private static Map forConfig(Map originalConfig) { var newConfig = new HashMap<>(originalConfig); @@ -114,8 +91,8 @@ private static Map forConfig(Map originalConfig) @BeforeEach void setup() { - server = ClientAndServer.startClientAndServer(MOCK_BACKEND_REMOTEHOST, getFreePort()); - privateBackendUrl = "http://%s:%d%s".formatted(MOCK_BACKEND_REMOTEHOST, server.getPort(), MOCK_BACKEND_PATH); + server = ClientAndServer.startClientAndServer(MOCK_BACKEND_REMOTE_HOST, getFreePort()); + privateBackendUrl = "http://%s:%d%s".formatted(MOCK_BACKEND_REMOTE_HOST, server.getPort(), MOCK_BACKEND_PATH); } @Test @@ -133,7 +110,7 @@ void transferData_withExpiredEdr_shouldReturn4xx() { var accessPolicyId = PLATO.createPolicyDefinition(createAccessPolicy(SOKRATES.getBpn())); var contractPolicyId = PLATO.createPolicyDefinition(createContractPolicy(SOKRATES.getBpn())); PLATO.createContractDefinition(assetId, "def-1", accessPolicyId, contractPolicyId); - var transferProcessId = SOKRATES.requestAsset(PLATO, assetId, Json.createObjectBuilder().build(), createProxyRequest()); + var transferProcessId = SOKRATES.requestAsset(PLATO, assetId, Json.createObjectBuilder().build(), createProxyRequest(), "HttpData-PULL"); var edr = new AtomicReference(); @@ -202,7 +179,7 @@ void transferData_withAutomaticRefresh() { var accessPolicyId = PLATO.createPolicyDefinition(createAccessPolicy(SOKRATES.getBpn())); var contractPolicyId = PLATO.createPolicyDefinition(createContractPolicy(SOKRATES.getBpn())); PLATO.createContractDefinition(assetId, "def-1", accessPolicyId, contractPolicyId); - var transferProcessId = SOKRATES.requestAsset(PLATO, assetId, Json.createObjectBuilder().build(), createProxyRequest()); + var transferProcessId = SOKRATES.requestAsset(PLATO, assetId, Json.createObjectBuilder().build(), createProxyRequest(), "HttpData-PULL"); var edr = new AtomicReference(); From 7101253d75d711f0810018724f8690e932b2161a Mon Sep 17 00:00:00 2001 From: Paul Latzelsperger <43503240+paullatzelsperger@users.noreply.github.com> Date: Fri, 29 Mar 2024 13:28:01 +0100 Subject: [PATCH 080/100] chore: remove MIW from code base (#1170) * delete modules * delete miw tests * fix refresh token tests * remove ssi mem runtime * add IATP as default identity service * exclude BDRS from tests * update helm docs * fix tests * DEPENDENCIES * fix tests * DEPENDENCIES * DEPENDENCIES * DEPENDENCIES, removed printClassPAth --- .github/workflows/verify.yaml | 37 - DEPENDENCIES | 356 ++- build.gradle.kts | 7 - .../tractusx-connector-azure-vault/README.md | 5 - .../templates/deployment-controlplane.yaml | 16 - .../values.yaml | 15 - charts/tractusx-connector-memory/README.md | 5 - .../templates/deployment-runtime.yaml | 17 - charts/tractusx-connector-memory/values.yaml | 15 - .../templates/deployment-controlplane.yaml | 24 - .../edc-controlplane-base/build.gradle.kts | 12 +- .../edc-dataplane-base/build.gradle.kts | 2 +- edc-extensions/bdrs-client/build.gradle.kts | 1 + .../identity/mapper/BdrsClientExtension.java | 3 +- .../mapper/BdrsClientExtensionTest.java | 4 +- .../cx-policy-legacy/build.gradle.kts | 33 - .../edc/policy/cx/CxPolicyExtension.java | 55 - ...ctDynamicCredentialConstraintFunction.java | 80 - .../common/AbstractVpConstraintFunction.java | 130 - .../edc/policy/cx/common/PolicyScopes.java | 33 - .../cx/summary/SummaryConstraintFunction.java | 117 - .../SummaryConstraintFunctionsProvider.java | 113 - .../summary/SummaryTokenPolicyFunction.java | 47 - ...rg.eclipse.edc.spi.system.ServiceExtension | 21 - .../edc/policy/cx/CredentialFunctions.java | 90 - .../AbstractVpConstraintFunctionTest.java | 114 - .../SummaryConstraintFunctionTest.java | 71 - ...ummaryConstraintFunctionsProviderTest.java | 96 - .../SummaryTokenPolicyFunctionTest.java | 49 - edc-extensions/cx-policy/build.gradle.kts | 2 - .../token-refresh-api/build.gradle.kts | 2 + .../tokenrefresh/api/v1/TokenRefreshApi.java | 2 +- .../api/v1/TokenRefreshApiController.java | 7 + .../DataPlaneTokenRefreshServiceImpl.java | 2 +- .../iatp/tx-iatp-sts-dim/build.gradle.kts | 2 +- .../iatp/sts/dim/DimSecureTokenService.java | 2 +- edc-extensions/iatp/tx-iatp/build.gradle.kts | 2 +- .../ssi/ssi-identity-core/README.md | 25 - .../ssi/ssi-identity-core/build.gradle.kts | 33 - .../iam/ssi/identity/SsiIdentityService.java | 58 - .../identity/SsiIdentityServiceExtension.java | 75 - .../SsiTokenValidationServiceImpl.java | 62 - .../rule/SsiAudienceValidationRule.java | 50 - ...rg.eclipse.edc.spi.system.ServiceExtension | 20 - .../SsiIdentityServiceExtensionTest.java | 60 - .../ssi/identity/SsiIdentityServiceTest.java | 99 - .../SsiTokenValidationServiceImplTest.java | 102 - .../rule/SsiAudienceValidationRuleTest.java | 72 - .../ssi-identity-extractor/build.gradle.kts | 31 - .../CredentialIdentityExtractor.java | 87 - .../SsiIdentityExtractorExtension.java | 45 - ...rg.eclipse.edc.spi.system.ServiceExtension | 20 - .../CredentialIdentityExtractorTest.java | 87 - .../SsiIdentityExtractorExtensionTest.java | 48 - .../ssi/ssi-miw-credential-client/README.md | 34 - .../build.gradle.kts | 40 - .../iam/ssi/miw/SsiMiwApiClientExtension.java | 66 - .../ssi/miw/SsiMiwConfigurationExtension.java | 69 - .../miw/SsiMiwCredentialClientExtension.java | 58 - .../ssi/miw/SsiMiwOauth2ClientExtension.java | 83 - .../miw/SsiMiwValidationRuleExtension.java | 57 - .../edc/iam/ssi/miw/api/MiwApiClient.java | 39 - .../edc/iam/ssi/miw/api/MiwApiClientImpl.java | 208 -- .../iam/ssi/miw/api/MiwClientException.java | 43 - .../iam/ssi/miw/api/MiwFallbackFactories.java | 60 - .../ssi/miw/config/SsiMiwConfiguration.java | 75 - .../credentials/SsiMiwCredentialClient.java | 130 - .../iam/ssi/miw/oauth2/MiwOauth2Client.java | 32 - .../oauth2/MiwOauth2ClientConfiguration.java | 82 - .../ssi/miw/oauth2/MiwOauth2ClientImpl.java | 63 - .../SsiCredentialIssuerValidationRule.java | 104 - .../SsiCredentialSubjectIdValidationRule.java | 105 - ...rg.eclipse.edc.spi.system.ServiceExtension | 24 - .../ssi/miw/SsiMiwApiClientExtensionTest.java | 60 - .../miw/SsiMiwConfigurationExtensionTest.java | 116 - .../SsiMiwCredentialClientExtensionTest.java | 48 - .../miw/SsiMiwOauth2ClientExtensionTest.java | 93 - .../SsiMiwValidationRuleExtensionTest.java | 62 - .../iam/ssi/miw/api/MiwApiClientImplTest.java | 301 -- .../SsiMiwCredentialClientTest.java | 157 -- .../miw/oauth2/MiwOauth2ClientImplTest.java | 82 - ...SsiCredentialIssuerValidationRuleTest.java | 65 - ...CredentialSubjectIdValidationRuleTest.java | 82 - .../edc/lifecycle/MiwParticipant.java | 82 - .../tractusx/edc/tag/MiwIntegrationTest.java | 36 - .../edc/tests/catalog/MiwSsiCatalogTest.java | 88 - .../ssi-summarycred-tests/build.gradle.kts | 41 - .../edc/tests/KeycloakDispatcher.java | 56 - .../tractusx/edc/tests/MiwDispatcher.java | 142 - .../tractusx/edc/tests/MiwParticipant.java | 83 - .../AbstractContractNegotiateTest.java | 90 - .../SsiContractNegotiationInMemoryTest.java | 93 - ...HttpConsumerPullWithProxyInMemoryTest.java | 121 - .../src/test/resources/framework-policy.json | 24 - .../resources/summary-vc-no-dismantler.json | 37 - .../src/test/resources/summary-vc.json | 38 - .../build.gradle.kts | 1 + .../DataPlaneTokenRefreshEndToEndTest.java | 109 +- edc-tests/miw-tests/README.md | 3 - edc-tests/miw-tests/build.gradle.kts | 64 - .../tractusx/edc/tag/MiwIntegrationTest.java | 36 - .../eclipse/tractusx/edc/tests/miw/README.md | 72 - .../tractusx/edc/tests/miw/WalletTest.java | 395 --- .../docker-environment/docker-compose.yaml | 92 - .../keycloak/health-check.sh | 33 - .../keycloak/miw_test_realm.json | 2479 ----------------- .../docker-environment/postgres/db.sh | 28 - .../docker-environment/postgres/seed.sh | 29 - .../src/test/resources/env-files/env.docker | 52 - .../build.gradle.kts | 9 +- .../runtime-memory-iatp-dim/build.gradle.kts | 11 +- .../runtime-memory-iatp-ih/build.gradle.kts | 9 +- .../iatp/runtime-memory-sts/build.gradle.kts | 1 - .../runtime/runtime-memory-ssi/README.md | 3 - .../runtime-memory-ssi/build.gradle.kts | 57 - .../runtime/runtime-memory/build.gradle.kts | 1 - .../runtime-postgresql/build.gradle.kts | 1 - gradle/libs.versions.toml | 9 +- .../multitenancy/MultiTenantRuntime.java | 5 - settings.gradle.kts | 8 - spi/ssi-spi/build.gradle.kts | 35 - .../edc/iam/ssi/spi/SsiConstants.java | 25 - .../edc/iam/ssi/spi/SsiCredentialClient.java | 53 - .../ssi/spi/SsiTokenValidationService.java | 38 - .../ssi/spi/jsonld/CredentialsNamespaces.java | 49 - .../ssi/spi/jsonld/JsonLdFieldExtractor.java | 98 - .../ssi/spi/jsonld/JsonLdTypeFunctions.java | 111 - .../ssi/spi/jsonld/JsonLdValueFunctions.java | 76 - .../spi/jsonld/JsonLdFieldExtractorTest.java | 80 - .../spi/jsonld/JsonLdTypeFunctionsTest.java | 132 - .../spi/jsonld/JsonLdValueFunctionsTest.java | 70 - .../ssi/spi/jsonld/JsonLdTextFixtures.java | 95 - .../iam/ssi/spi/jsonld/SummaryContext.java | 54 - .../iam/ssi/spi/jsonld/SummaryCredential.java | 153 - .../edc/iam/ssi/spi/jsonld/W3cVcContext.java | 268 -- 135 files changed, 310 insertions(+), 10466 deletions(-) delete mode 100644 edc-extensions/cx-policy-legacy/build.gradle.kts delete mode 100644 edc-extensions/cx-policy-legacy/src/main/java/org/eclipse/tractusx/edc/policy/cx/CxPolicyExtension.java delete mode 100644 edc-extensions/cx-policy-legacy/src/main/java/org/eclipse/tractusx/edc/policy/cx/common/AbstractDynamicCredentialConstraintFunction.java delete mode 100644 edc-extensions/cx-policy-legacy/src/main/java/org/eclipse/tractusx/edc/policy/cx/common/AbstractVpConstraintFunction.java delete mode 100644 edc-extensions/cx-policy-legacy/src/main/java/org/eclipse/tractusx/edc/policy/cx/common/PolicyScopes.java delete mode 100644 edc-extensions/cx-policy-legacy/src/main/java/org/eclipse/tractusx/edc/policy/cx/summary/SummaryConstraintFunction.java delete mode 100644 edc-extensions/cx-policy-legacy/src/main/java/org/eclipse/tractusx/edc/policy/cx/summary/SummaryConstraintFunctionsProvider.java delete mode 100644 edc-extensions/cx-policy-legacy/src/main/java/org/eclipse/tractusx/edc/policy/cx/summary/SummaryTokenPolicyFunction.java delete mode 100644 edc-extensions/cx-policy-legacy/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension delete mode 100644 edc-extensions/cx-policy-legacy/src/test/java/org/eclipse/tractusx/edc/policy/cx/CredentialFunctions.java delete mode 100644 edc-extensions/cx-policy-legacy/src/test/java/org/eclipse/tractusx/edc/policy/cx/common/AbstractVpConstraintFunctionTest.java delete mode 100644 edc-extensions/cx-policy-legacy/src/test/java/org/eclipse/tractusx/edc/policy/cx/summary/SummaryConstraintFunctionTest.java delete mode 100644 edc-extensions/cx-policy-legacy/src/test/java/org/eclipse/tractusx/edc/policy/cx/summary/SummaryConstraintFunctionsProviderTest.java delete mode 100644 edc-extensions/cx-policy-legacy/src/test/java/org/eclipse/tractusx/edc/policy/cx/summary/SummaryTokenPolicyFunctionTest.java delete mode 100644 edc-extensions/ssi/ssi-identity-core/README.md delete mode 100644 edc-extensions/ssi/ssi-identity-core/build.gradle.kts delete mode 100644 edc-extensions/ssi/ssi-identity-core/src/main/java/org/eclipse/tractusx/edc/iam/ssi/identity/SsiIdentityService.java delete mode 100644 edc-extensions/ssi/ssi-identity-core/src/main/java/org/eclipse/tractusx/edc/iam/ssi/identity/SsiIdentityServiceExtension.java delete mode 100644 edc-extensions/ssi/ssi-identity-core/src/main/java/org/eclipse/tractusx/edc/iam/ssi/identity/SsiTokenValidationServiceImpl.java delete mode 100644 edc-extensions/ssi/ssi-identity-core/src/main/java/org/eclipse/tractusx/edc/iam/ssi/identity/rule/SsiAudienceValidationRule.java delete mode 100644 edc-extensions/ssi/ssi-identity-core/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension delete mode 100644 edc-extensions/ssi/ssi-identity-core/src/test/java/org/eclipse/tractusx/edc/iam/ssi/identity/SsiIdentityServiceExtensionTest.java delete mode 100644 edc-extensions/ssi/ssi-identity-core/src/test/java/org/eclipse/tractusx/edc/iam/ssi/identity/SsiIdentityServiceTest.java delete mode 100644 edc-extensions/ssi/ssi-identity-core/src/test/java/org/eclipse/tractusx/edc/iam/ssi/identity/SsiTokenValidationServiceImplTest.java delete mode 100644 edc-extensions/ssi/ssi-identity-core/src/test/java/org/eclipse/tractusx/edc/iam/ssi/identity/rule/SsiAudienceValidationRuleTest.java delete mode 100644 edc-extensions/ssi/ssi-identity-extractor/build.gradle.kts delete mode 100644 edc-extensions/ssi/ssi-identity-extractor/src/main/java/org/eclipse/tractusx/edc/iam/ssi/identity/extractor/CredentialIdentityExtractor.java delete mode 100644 edc-extensions/ssi/ssi-identity-extractor/src/main/java/org/eclipse/tractusx/edc/iam/ssi/identity/extractor/SsiIdentityExtractorExtension.java delete mode 100644 edc-extensions/ssi/ssi-identity-extractor/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension delete mode 100644 edc-extensions/ssi/ssi-identity-extractor/src/test/java/org/eclipse/tractusx/edc/iam/ssi/identity/extractor/CredentialIdentityExtractorTest.java delete mode 100644 edc-extensions/ssi/ssi-identity-extractor/src/test/java/org/eclipse/tractusx/edc/iam/ssi/identity/extractor/SsiIdentityExtractorExtensionTest.java delete mode 100644 edc-extensions/ssi/ssi-miw-credential-client/README.md delete mode 100644 edc-extensions/ssi/ssi-miw-credential-client/build.gradle.kts delete mode 100644 edc-extensions/ssi/ssi-miw-credential-client/src/main/java/org/eclipse/tractusx/edc/iam/ssi/miw/SsiMiwApiClientExtension.java delete mode 100644 edc-extensions/ssi/ssi-miw-credential-client/src/main/java/org/eclipse/tractusx/edc/iam/ssi/miw/SsiMiwConfigurationExtension.java delete mode 100644 edc-extensions/ssi/ssi-miw-credential-client/src/main/java/org/eclipse/tractusx/edc/iam/ssi/miw/SsiMiwCredentialClientExtension.java delete mode 100644 edc-extensions/ssi/ssi-miw-credential-client/src/main/java/org/eclipse/tractusx/edc/iam/ssi/miw/SsiMiwOauth2ClientExtension.java delete mode 100644 edc-extensions/ssi/ssi-miw-credential-client/src/main/java/org/eclipse/tractusx/edc/iam/ssi/miw/SsiMiwValidationRuleExtension.java delete mode 100644 edc-extensions/ssi/ssi-miw-credential-client/src/main/java/org/eclipse/tractusx/edc/iam/ssi/miw/api/MiwApiClient.java delete mode 100644 edc-extensions/ssi/ssi-miw-credential-client/src/main/java/org/eclipse/tractusx/edc/iam/ssi/miw/api/MiwApiClientImpl.java delete mode 100644 edc-extensions/ssi/ssi-miw-credential-client/src/main/java/org/eclipse/tractusx/edc/iam/ssi/miw/api/MiwClientException.java delete mode 100644 edc-extensions/ssi/ssi-miw-credential-client/src/main/java/org/eclipse/tractusx/edc/iam/ssi/miw/api/MiwFallbackFactories.java delete mode 100644 edc-extensions/ssi/ssi-miw-credential-client/src/main/java/org/eclipse/tractusx/edc/iam/ssi/miw/config/SsiMiwConfiguration.java delete mode 100644 edc-extensions/ssi/ssi-miw-credential-client/src/main/java/org/eclipse/tractusx/edc/iam/ssi/miw/credentials/SsiMiwCredentialClient.java delete mode 100644 edc-extensions/ssi/ssi-miw-credential-client/src/main/java/org/eclipse/tractusx/edc/iam/ssi/miw/oauth2/MiwOauth2Client.java delete mode 100644 edc-extensions/ssi/ssi-miw-credential-client/src/main/java/org/eclipse/tractusx/edc/iam/ssi/miw/oauth2/MiwOauth2ClientConfiguration.java delete mode 100644 edc-extensions/ssi/ssi-miw-credential-client/src/main/java/org/eclipse/tractusx/edc/iam/ssi/miw/oauth2/MiwOauth2ClientImpl.java delete mode 100644 edc-extensions/ssi/ssi-miw-credential-client/src/main/java/org/eclipse/tractusx/edc/iam/ssi/miw/rule/SsiCredentialIssuerValidationRule.java delete mode 100644 edc-extensions/ssi/ssi-miw-credential-client/src/main/java/org/eclipse/tractusx/edc/iam/ssi/miw/rule/SsiCredentialSubjectIdValidationRule.java delete mode 100644 edc-extensions/ssi/ssi-miw-credential-client/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension delete mode 100644 edc-extensions/ssi/ssi-miw-credential-client/src/test/java/org/eclipse/tractusx/edc/iam/ssi/miw/SsiMiwApiClientExtensionTest.java delete mode 100644 edc-extensions/ssi/ssi-miw-credential-client/src/test/java/org/eclipse/tractusx/edc/iam/ssi/miw/SsiMiwConfigurationExtensionTest.java delete mode 100644 edc-extensions/ssi/ssi-miw-credential-client/src/test/java/org/eclipse/tractusx/edc/iam/ssi/miw/SsiMiwCredentialClientExtensionTest.java delete mode 100644 edc-extensions/ssi/ssi-miw-credential-client/src/test/java/org/eclipse/tractusx/edc/iam/ssi/miw/SsiMiwOauth2ClientExtensionTest.java delete mode 100644 edc-extensions/ssi/ssi-miw-credential-client/src/test/java/org/eclipse/tractusx/edc/iam/ssi/miw/SsiMiwValidationRuleExtensionTest.java delete mode 100644 edc-extensions/ssi/ssi-miw-credential-client/src/test/java/org/eclipse/tractusx/edc/iam/ssi/miw/api/MiwApiClientImplTest.java delete mode 100644 edc-extensions/ssi/ssi-miw-credential-client/src/test/java/org/eclipse/tractusx/edc/iam/ssi/miw/credentials/SsiMiwCredentialClientTest.java delete mode 100644 edc-extensions/ssi/ssi-miw-credential-client/src/test/java/org/eclipse/tractusx/edc/iam/ssi/miw/oauth2/MiwOauth2ClientImplTest.java delete mode 100644 edc-extensions/ssi/ssi-miw-credential-client/src/test/java/org/eclipse/tractusx/edc/iam/ssi/miw/rule/SsiCredentialIssuerValidationRuleTest.java delete mode 100644 edc-extensions/ssi/ssi-miw-credential-client/src/test/java/org/eclipse/tractusx/edc/iam/ssi/miw/rule/SsiCredentialSubjectIdValidationRuleTest.java delete mode 100644 edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/MiwParticipant.java delete mode 100644 edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tag/MiwIntegrationTest.java delete mode 100644 edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/catalog/MiwSsiCatalogTest.java delete mode 100644 edc-tests/edc-controlplane/ssi-summarycred-tests/build.gradle.kts delete mode 100644 edc-tests/edc-controlplane/ssi-summarycred-tests/src/test/java/org/eclipse/tractusx/edc/tests/KeycloakDispatcher.java delete mode 100644 edc-tests/edc-controlplane/ssi-summarycred-tests/src/test/java/org/eclipse/tractusx/edc/tests/MiwDispatcher.java delete mode 100644 edc-tests/edc-controlplane/ssi-summarycred-tests/src/test/java/org/eclipse/tractusx/edc/tests/MiwParticipant.java delete mode 100644 edc-tests/edc-controlplane/ssi-summarycred-tests/src/test/java/org/eclipse/tractusx/edc/tests/negotiation/AbstractContractNegotiateTest.java delete mode 100644 edc-tests/edc-controlplane/ssi-summarycred-tests/src/test/java/org/eclipse/tractusx/edc/tests/negotiation/SsiContractNegotiationInMemoryTest.java delete mode 100644 edc-tests/edc-controlplane/ssi-summarycred-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/SsiHttpConsumerPullWithProxyInMemoryTest.java delete mode 100644 edc-tests/edc-controlplane/ssi-summarycred-tests/src/test/resources/framework-policy.json delete mode 100644 edc-tests/edc-controlplane/ssi-summarycred-tests/src/test/resources/summary-vc-no-dismantler.json delete mode 100644 edc-tests/edc-controlplane/ssi-summarycred-tests/src/test/resources/summary-vc.json delete mode 100644 edc-tests/miw-tests/README.md delete mode 100644 edc-tests/miw-tests/build.gradle.kts delete mode 100644 edc-tests/miw-tests/src/test/java/org/eclipse/tractusx/edc/tag/MiwIntegrationTest.java delete mode 100644 edc-tests/miw-tests/src/test/java/org/eclipse/tractusx/edc/tests/miw/README.md delete mode 100644 edc-tests/miw-tests/src/test/java/org/eclipse/tractusx/edc/tests/miw/WalletTest.java delete mode 100644 edc-tests/miw-tests/src/test/resources/docker-environment/docker-compose.yaml delete mode 100755 edc-tests/miw-tests/src/test/resources/docker-environment/keycloak/health-check.sh delete mode 100644 edc-tests/miw-tests/src/test/resources/docker-environment/keycloak/miw_test_realm.json delete mode 100755 edc-tests/miw-tests/src/test/resources/docker-environment/postgres/db.sh delete mode 100755 edc-tests/miw-tests/src/test/resources/docker-environment/postgres/seed.sh delete mode 100644 edc-tests/miw-tests/src/test/resources/env-files/env.docker delete mode 100644 edc-tests/runtime/runtime-memory-ssi/README.md delete mode 100644 edc-tests/runtime/runtime-memory-ssi/build.gradle.kts delete mode 100644 spi/ssi-spi/build.gradle.kts delete mode 100644 spi/ssi-spi/src/main/java/org/eclipse/tractusx/edc/iam/ssi/spi/SsiConstants.java delete mode 100644 spi/ssi-spi/src/main/java/org/eclipse/tractusx/edc/iam/ssi/spi/SsiCredentialClient.java delete mode 100644 spi/ssi-spi/src/main/java/org/eclipse/tractusx/edc/iam/ssi/spi/SsiTokenValidationService.java delete mode 100644 spi/ssi-spi/src/main/java/org/eclipse/tractusx/edc/iam/ssi/spi/jsonld/CredentialsNamespaces.java delete mode 100644 spi/ssi-spi/src/main/java/org/eclipse/tractusx/edc/iam/ssi/spi/jsonld/JsonLdFieldExtractor.java delete mode 100644 spi/ssi-spi/src/main/java/org/eclipse/tractusx/edc/iam/ssi/spi/jsonld/JsonLdTypeFunctions.java delete mode 100644 spi/ssi-spi/src/main/java/org/eclipse/tractusx/edc/iam/ssi/spi/jsonld/JsonLdValueFunctions.java delete mode 100644 spi/ssi-spi/src/test/java/org/eclipse/tractusx/edc/iam/ssi/spi/jsonld/JsonLdFieldExtractorTest.java delete mode 100644 spi/ssi-spi/src/test/java/org/eclipse/tractusx/edc/iam/ssi/spi/jsonld/JsonLdTypeFunctionsTest.java delete mode 100644 spi/ssi-spi/src/test/java/org/eclipse/tractusx/edc/iam/ssi/spi/jsonld/JsonLdValueFunctionsTest.java delete mode 100644 spi/ssi-spi/src/testFixtures/java/org/eclipse/tractusx/edc/iam/ssi/spi/jsonld/JsonLdTextFixtures.java delete mode 100644 spi/ssi-spi/src/testFixtures/java/org/eclipse/tractusx/edc/iam/ssi/spi/jsonld/SummaryContext.java delete mode 100644 spi/ssi-spi/src/testFixtures/java/org/eclipse/tractusx/edc/iam/ssi/spi/jsonld/SummaryCredential.java delete mode 100644 spi/ssi-spi/src/testFixtures/java/org/eclipse/tractusx/edc/iam/ssi/spi/jsonld/W3cVcContext.java diff --git a/.github/workflows/verify.yaml b/.github/workflows/verify.yaml index a1df254d0..b57bdf745 100644 --- a/.github/workflows/verify.yaml +++ b/.github/workflows/verify.yaml @@ -116,7 +116,6 @@ jobs: { dir: edc-tests/edc-controlplane/edr-api-tests }, { dir: edc-tests/edc-controlplane/iatp-tests }, { dir: edc-tests/edc-controlplane/policy-tests }, - { dir: edc-tests/edc-controlplane/ssi-summarycred-tests }, { dir: edc-tests/edc-controlplane/transfer-tests } ] steps: @@ -154,39 +153,3 @@ jobs: - name: Run Azure/S3 dataplane tests run: ./gradlew -p edc-tests/edc-dataplane test -DincludeTags="AzureCosmosDbIntegrationTest,AwsS3IntegrationTest" - - miw-integration-tests: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: ./.github/actions/setup-java - - uses: actions/checkout@v4 - - name: Starting MIW, Keycloak and Postgres Servers - run: | - cd edc-tests/miw-tests/src/test/resources/docker-environment - docker compose up --wait - - - uses: nick-fields/retry@v3 - name: Wait for MIW - with: - timeout_minutes: 5 - max_attempts: 3 - command: | - code=$(curl -IL -sw "%{http_code}" http://localhost:8000/api/actuator/health -o /dev/null) - if [ "$code" -ne "401" ]; then - echo "MIW not ready yet, status = $code" - exit 1; - fi - - - name: Seed test data - run: | - docker exec docker-environment-postgres-1 /opt/seed.sh - - - name: Run MIW Integration tests - run: | - ./gradlew -p edc-tests/miw-tests test -DincludeTags="MiwIntegrationTest" - - name: Run SSI E2E tests - run: | - pwd - ./gradlew compileJava compileTestJava - ./gradlew -p edc-tests/e2e-tests test -DincludeTags="MiwIntegrationTest" diff --git a/DEPENDENCIES b/DEPENDENCIES index 551567877..f48b6d9d7 100644 --- a/DEPENDENCIES +++ b/DEPENDENCIES @@ -31,7 +31,6 @@ maven/mavencentral/com.fasterxml.jackson.core/jackson-annotations/2.17.0, Apache maven/mavencentral/com.fasterxml.jackson.core/jackson-core/2.13.5, Apache-2.0, approved, #2133 maven/mavencentral/com.fasterxml.jackson.core/jackson-core/2.14.1, Apache-2.0 AND MIT, approved, #4303 maven/mavencentral/com.fasterxml.jackson.core/jackson-core/2.15.1, MIT AND Apache-2.0, approved, #7932 -maven/mavencentral/com.fasterxml.jackson.core/jackson-core/2.16.2, Apache-2.0 AND MIT, approved, #11602 maven/mavencentral/com.fasterxml.jackson.core/jackson-core/2.17.0, , approved, #13665 maven/mavencentral/com.fasterxml.jackson.core/jackson-databind/2.11.0, Apache-2.0, approved, CQ23093 maven/mavencentral/com.fasterxml.jackson.core/jackson-databind/2.13.4.2, Apache-2.0, approved, #2134 @@ -45,32 +44,30 @@ maven/mavencentral/com.fasterxml.jackson.core/jackson-databind/2.15.3, Apache-2. maven/mavencentral/com.fasterxml.jackson.core/jackson-databind/2.16.2, Apache-2.0, approved, #11605 maven/mavencentral/com.fasterxml.jackson.core/jackson-databind/2.17.0, Apache-2.0, approved, #13671 maven/mavencentral/com.fasterxml.jackson.dataformat/jackson-dataformat-toml/2.15.2, Apache-2.0, approved, #9160 -maven/mavencentral/com.fasterxml.jackson.dataformat/jackson-dataformat-toml/2.16.2, Apache-2.0, approved, #13145 +maven/mavencentral/com.fasterxml.jackson.dataformat/jackson-dataformat-toml/2.17.0, Apache-2.0, approved, #14192 maven/mavencentral/com.fasterxml.jackson.dataformat/jackson-dataformat-xml/2.13.5, Apache-2.0, approved, #3768 -maven/mavencentral/com.fasterxml.jackson.dataformat/jackson-dataformat-xml/2.16.2, Apache-2.0, approved, #12438 +maven/mavencentral/com.fasterxml.jackson.dataformat/jackson-dataformat-xml/2.17.0, Apache-2.0, approved, #13666 maven/mavencentral/com.fasterxml.jackson.dataformat/jackson-dataformat-yaml/2.14.0, Apache-2.0, approved, #5933 maven/mavencentral/com.fasterxml.jackson.dataformat/jackson-dataformat-yaml/2.15.1, Apache-2.0, approved, #8802 maven/mavencentral/com.fasterxml.jackson.dataformat/jackson-dataformat-yaml/2.15.2, Apache-2.0, approved, #8802 -maven/mavencentral/com.fasterxml.jackson.dataformat/jackson-dataformat-yaml/2.16.2, Apache-2.0, approved, #11855 +maven/mavencentral/com.fasterxml.jackson.dataformat/jackson-dataformat-yaml/2.17.0, Apache-2.0, approved, #13669 maven/mavencentral/com.fasterxml.jackson.datatype/jackson-datatype-jakarta-jsonp/2.16.2, Apache-2.0, approved, #11854 maven/mavencentral/com.fasterxml.jackson.datatype/jackson-datatype-jakarta-jsonp/2.17.0, Apache-2.0, approved, #14161 maven/mavencentral/com.fasterxml.jackson.datatype/jackson-datatype-jsr310/2.13.5, Apache-2.0, approved, clearlydefined maven/mavencentral/com.fasterxml.jackson.datatype/jackson-datatype-jsr310/2.14.0, Apache-2.0, approved, #4699 maven/mavencentral/com.fasterxml.jackson.datatype/jackson-datatype-jsr310/2.15.1, Apache-2.0, approved, #7930 maven/mavencentral/com.fasterxml.jackson.datatype/jackson-datatype-jsr310/2.15.2, Apache-2.0, approved, #7930 -maven/mavencentral/com.fasterxml.jackson.datatype/jackson-datatype-jsr310/2.16.2, Apache-2.0, approved, #11853 maven/mavencentral/com.fasterxml.jackson.datatype/jackson-datatype-jsr310/2.17.0, Apache-2.0, approved, #14160 -maven/mavencentral/com.fasterxml.jackson.jakarta.rs/jackson-jakarta-rs-base/2.16.2, Apache-2.0, approved, #11851 +maven/mavencentral/com.fasterxml.jackson.jakarta.rs/jackson-jakarta-rs-base/2.17.0, Apache-2.0, approved, #14194 maven/mavencentral/com.fasterxml.jackson.jakarta.rs/jackson-jakarta-rs-json-provider/2.15.1, Apache-2.0, approved, #9236 maven/mavencentral/com.fasterxml.jackson.jakarta.rs/jackson-jakarta-rs-json-provider/2.15.2, Apache-2.0, approved, #9236 -maven/mavencentral/com.fasterxml.jackson.jakarta.rs/jackson-jakarta-rs-json-provider/2.16.2, Apache-2.0, approved, #11858 +maven/mavencentral/com.fasterxml.jackson.jakarta.rs/jackson-jakarta-rs-json-provider/2.17.0, Apache-2.0, approved, #14195 maven/mavencentral/com.fasterxml.jackson.module/jackson-module-jakarta-xmlbind-annotations/2.15.3, Apache-2.0, approved, #9241 -maven/mavencentral/com.fasterxml.jackson.module/jackson-module-jakarta-xmlbind-annotations/2.16.2, Apache-2.0, approved, #11856 +maven/mavencentral/com.fasterxml.jackson.module/jackson-module-jakarta-xmlbind-annotations/2.17.0, Apache-2.0, approved, #13668 maven/mavencentral/com.fasterxml.jackson/jackson-bom/2.15.1, Apache-2.0, approved, #7929 -maven/mavencentral/com.fasterxml.jackson/jackson-bom/2.16.2, Apache-2.0, approved, #11852 maven/mavencentral/com.fasterxml.jackson/jackson-bom/2.17.0, Apache-2.0, approved, #14162 maven/mavencentral/com.fasterxml.uuid/java-uuid-generator/4.1.0, Apache-2.0, approved, clearlydefined -maven/mavencentral/com.fasterxml.woodstox/woodstox-core/6.5.1, Apache-2.0, approved, #7950 +maven/mavencentral/com.fasterxml.woodstox/woodstox-core/6.6.1, Apache-2.0, approved, #12789 maven/mavencentral/com.github.cliftonlabs/json-simple/3.0.2, Apache-2.0, approved, clearlydefined maven/mavencentral/com.github.docker-java/docker-java-api/3.3.6, Apache-2.0, approved, #10346 maven/mavencentral/com.github.docker-java/docker-java-transport-zerodep/3.3.6, Apache-2.0 AND (Apache-2.0 AND BSD-3-Clause), approved, #7946 @@ -255,7 +252,6 @@ maven/mavencentral/jakarta.activation/jakarta.activation-api/1.2.1, EPL-2.0 OR B maven/mavencentral/jakarta.activation/jakarta.activation-api/2.1.0, EPL-2.0 OR BSD-3-Clause OR GPL-2.0-only with Classpath-exception-2.0, approved, ee4j.jaf maven/mavencentral/jakarta.annotation/jakarta.annotation-api/2.1.1, EPL-2.0 OR GPL-2.0-only with Classpath-exception-2.0, approved, ee4j.ca maven/mavencentral/jakarta.inject/jakarta.inject-api/2.0.1, Apache-2.0, approved, ee4j.cdi -maven/mavencentral/jakarta.json/jakarta.json-api/2.1.1, EPL-2.0 OR GPL-2.0-only with Classpath-exception-2.0, approved, ee4j.jsonp maven/mavencentral/jakarta.json/jakarta.json-api/2.1.3, EPL-2.0 OR GPL-2.0-only with Classpath-exception-2.0, approved, ee4j.jsonp maven/mavencentral/jakarta.transaction/jakarta.transaction-api/2.0.0, EPL-2.0 OR GPL-2.0-only with Classpath-exception-2.0, approved, ee4j.jta maven/mavencentral/jakarta.validation/jakarta.validation-api/2.0.2, Apache-2.0, approved, ee4j.validation @@ -339,174 +335,174 @@ maven/mavencentral/org.codehaus.plexus/plexus-component-annotations/2.1.0, Apach maven/mavencentral/org.codehaus.plexus/plexus-container-default/2.1.0, Apache-2.0, approved, clearlydefined maven/mavencentral/org.codehaus.plexus/plexus-utils/3.1.1, , approved, CQ16492 maven/mavencentral/org.codehaus.plexus/plexus-utils/3.3.0, , approved, CQ21066 -maven/mavencentral/org.codehaus.woodstox/stax2-api/4.2.1, BSD-2-Clause, approved, #2670 +maven/mavencentral/org.codehaus.woodstox/stax2-api/4.2.2, BSD-2-Clause, approved, #2670 maven/mavencentral/org.eclipse.angus/angus-activation/1.0.0, EPL-2.0 OR GPL-2.0-only with Classpath-exception-2.0, approved, ee4j.angus -maven/mavencentral/org.eclipse.edc/api-core/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/api-observability/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/asset-api/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/asset-index-sql/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/asset-spi/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/auth-spi/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/auth-tokenbased/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/autodoc-processor/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/aws-s3-core/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/aws-s3-test/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/azure-blob-core/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/azure-test/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/boot-lib/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/boot/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/callback-event-dispatcher/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/callback-http-dispatcher/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/catalog-api/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/catalog-core/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/catalog-spi/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/configuration-filesystem/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/connector-core/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/contract-agreement-api/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/contract-core/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/contract-definition-api/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/contract-definition-store-sql/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/contract-negotiation-api/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/contract-negotiation-store-sql/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/contract-spi/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/control-api-configuration/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/control-plane-aggregate-services/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/control-plane-api-client-spi/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/control-plane-api-client/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/control-plane-api/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/control-plane-core/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/control-plane-policies-lib/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/control-plane-spi/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/core-spi/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/crypto-common-lib/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-address-http-data-spi/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-plane-aws-s3/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-plane-azure-storage/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-plane-client-embedded/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-plane-control-api/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-plane-core/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-plane-http-oauth2-core/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-plane-http-oauth2/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-plane-http-spi/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-plane-http/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-plane-public-api-v2/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-plane-selector-core/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-plane-selector-spi/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-plane-signaling-api-configuration/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-plane-signaling-api/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-plane-signaling-client/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-plane-signaling-transform/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-plane-spi/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-plane-util/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-api-configuration/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-catalog-api/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-catalog-http-dispatcher/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-catalog-transform/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-catalog/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-http-core/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-http-spi/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-negotiation-api/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-negotiation-http-dispatcher/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-negotiation-transform/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-negotiation/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-spi/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-transfer-process-api/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-transfer-process-http-dispatcher/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-transfer-process-transform/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-transfer-process/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-version-api/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/edr-store-core/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/edr-store-receiver/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/edr-store-spi/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/http-lib/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/http-spi/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/http/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/iam-mock/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-did-core/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-did-spi/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-did-web/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-hub-api/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-hub-credentials/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-hub-did-spi/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-hub-did/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-hub-keypairs/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-hub-participants/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-hub-spi/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-hub-store-spi/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-trust-core/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-trust-issuers-configuration/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-trust-service/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-trust-spi/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-trust-sts-api/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-trust-sts-client-configuration/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-trust-sts-core/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-trust-sts-embedded/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-trust-sts-remote-core/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-trust-sts-remote/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-trust-sts-spi/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-trust-transform/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/jersey-core/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/jersey-micrometer/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/jersey-providers-lib/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/jetty-core/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/jetty-micrometer/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/json-ld-lib/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/json-ld-spi/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/json-ld/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/junit-base/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/junit/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/jws2020/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/jwt-spi/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/jwt-verifiable-credentials/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/keys-lib/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/keys-spi/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/ldp-verifiable-credentials/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/management-api-configuration/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/management-api-test-fixtures/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/management-api/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/micrometer-core/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/oauth2-client/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/oauth2-spi/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/policy-definition-api/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/policy-definition-store-sql/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/policy-engine-lib/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/policy-engine-spi/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/policy-evaluator-lib/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/policy-model/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/policy-monitor-core/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/policy-monitor-spi/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/policy-monitor-store-sql/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/policy-spi/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/query-lib/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/runtime-metamodel/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/security/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/sql-core/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/sql-lease/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/sql-pool-apache-commons/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/state-machine-lib/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/store-lib/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/token-core/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/token-spi/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/transaction-datasource-spi/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/transaction-local/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/transaction-spi/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/transfer-core/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/transfer-data-plane-signaling/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/transfer-data-plane-spi/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/transfer-process-api/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/transfer-process-store-sql/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/transfer-pull-http-dynamic-receiver/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/transfer-spi/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/transform-core/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/transform-spi/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/util/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/validator-core/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/validator-data-address-http-data/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/validator-spi/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/vault-azure/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/vault-hashicorp/0.6.0, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/web-spi/0.6.0, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/api-core/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/api-observability/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/asset-api/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/asset-index-sql/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/asset-spi/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/auth-spi/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/auth-tokenbased/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/autodoc-processor/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/aws-s3-core/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/aws-s3-test/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/azure-blob-core/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/azure-test/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/boot-lib/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/boot/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/callback-event-dispatcher/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/callback-http-dispatcher/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/catalog-api/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/catalog-core/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/catalog-spi/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/configuration-filesystem/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/connector-core/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/contract-agreement-api/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/contract-core/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/contract-definition-api/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/contract-definition-store-sql/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/contract-negotiation-api/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/contract-negotiation-store-sql/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/contract-spi/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/control-api-configuration/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/control-plane-aggregate-services/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/control-plane-api-client-spi/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/control-plane-api-client/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/control-plane-api/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/control-plane-core/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/control-plane-policies-lib/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/control-plane-spi/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/core-spi/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/crypto-common-lib/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-address-http-data-spi/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-aws-s3/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-azure-storage/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-client-embedded/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-control-api/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-core/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-http-oauth2-core/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-http-oauth2/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-http-spi/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-http/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-public-api-v2/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-selector-core/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-selector-spi/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-signaling-api-configuration/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-signaling-api/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-signaling-client/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-signaling-transform/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-spi/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-util/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-api-configuration/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-catalog-api/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-catalog-http-dispatcher/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-catalog-transform/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-catalog/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-http-core/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-http-spi/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-negotiation-api/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-negotiation-http-dispatcher/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-negotiation-transform/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-negotiation/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-spi/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-transfer-process-api/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-transfer-process-http-dispatcher/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-transfer-process-transform/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-transfer-process/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-version-api/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/edr-store-core/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/edr-store-receiver/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/edr-store-spi/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/http-lib/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/http-spi/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/http/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/iam-mock/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-did-core/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-did-spi/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-did-web/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-hub-api/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-hub-credentials/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-hub-did-spi/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-hub-did/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-hub-keypairs/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-hub-participants/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-hub-spi/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-hub-store-spi/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-trust-core/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-trust-issuers-configuration/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-trust-service/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-trust-spi/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-trust-sts-api/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-trust-sts-client-configuration/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-trust-sts-core/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-trust-sts-embedded/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-trust-sts-remote-core/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-trust-sts-remote/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-trust-sts-spi/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-trust-transform/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/jersey-core/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/jersey-micrometer/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/jersey-providers-lib/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/jetty-core/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/jetty-micrometer/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/json-ld-lib/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/json-ld-spi/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/json-ld/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/junit-base/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/junit/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/jws2020/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/jwt-spi/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/jwt-verifiable-credentials/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/keys-lib/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/keys-spi/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/ldp-verifiable-credentials/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/management-api-configuration/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/management-api-test-fixtures/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/management-api/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/micrometer-core/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/oauth2-client/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/oauth2-spi/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/policy-definition-api/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/policy-definition-store-sql/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/policy-engine-lib/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/policy-engine-spi/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/policy-evaluator-lib/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/policy-model/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/policy-monitor-core/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/policy-monitor-spi/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/policy-monitor-store-sql/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/policy-spi/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/query-lib/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/runtime-metamodel/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/security/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/sql-core/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/sql-lease/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/sql-pool-apache-commons/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/state-machine-lib/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/store-lib/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/token-core/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/token-spi/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/transaction-datasource-spi/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/transaction-local/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/transaction-spi/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/transfer-core/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/transfer-data-plane-signaling/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/transfer-data-plane-spi/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/transfer-process-api/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/transfer-process-store-sql/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/transfer-pull-http-dynamic-receiver/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/transfer-spi/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/transform-core/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/transform-spi/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/util/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/validator-core/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/validator-data-address-http-data/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/validator-spi/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/vault-azure/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/vault-hashicorp/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/web-spi/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.jetty.toolchain/jetty-jakarta-servlet-api/5.0.2, EPL-2.0 OR Apache-2.0, approved, rt.jetty maven/mavencentral/org.eclipse.jetty.toolchain/jetty-jakarta-websocket-api/2.0.0, EPL-2.0 OR Apache-2.0, approved, rt.jetty maven/mavencentral/org.eclipse.jetty.websocket/websocket-core-client/11.0.20, EPL-2.0 OR Apache-2.0, approved, rt.jetty @@ -560,10 +556,10 @@ maven/mavencentral/org.javassist/javassist/3.29.2-GA, Apache-2.0 AND LGPL-2.1-or maven/mavencentral/org.jetbrains.kotlin/kotlin-stdlib-common/1.9.10, Apache-2.0, approved, #14186 maven/mavencentral/org.jetbrains.kotlin/kotlin-stdlib-jdk7/1.8.0, Apache-2.0, approved, #8807 maven/mavencentral/org.jetbrains.kotlin/kotlin-stdlib-jdk7/1.8.21, Apache-2.0, approved, #8807 -maven/mavencentral/org.jetbrains.kotlin/kotlin-stdlib-jdk7/1.9.10, None, restricted, #14188 +maven/mavencentral/org.jetbrains.kotlin/kotlin-stdlib-jdk7/1.9.10, None, restricted, #14193 maven/mavencentral/org.jetbrains.kotlin/kotlin-stdlib-jdk8/1.8.0, Apache-2.0, approved, #8919 maven/mavencentral/org.jetbrains.kotlin/kotlin-stdlib-jdk8/1.8.21, Apache-2.0, approved, #8919 -maven/mavencentral/org.jetbrains.kotlin/kotlin-stdlib-jdk8/1.9.10, None, restricted, #14185 +maven/mavencentral/org.jetbrains.kotlin/kotlin-stdlib-jdk8/1.9.10, None, restricted, #14191 maven/mavencentral/org.jetbrains.kotlin/kotlin-stdlib/1.8.21, Apache-2.0, approved, #8865 maven/mavencentral/org.jetbrains.kotlin/kotlin-stdlib/1.9.10, Apache-2.0, approved, #11827 maven/mavencentral/org.jetbrains.kotlin/kotlin-stdlib/1.9.21, Apache-2.0, approved, #11827 diff --git a/build.gradle.kts b/build.gradle.kts index b7dc88f81..42c028ca8 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -138,13 +138,6 @@ allprojects { } } - // EdcRuntimeExtension uses this to determine the runtime classpath of the module to run. - tasks.register("printClasspath") { - doLast { - println(sourceSets["main"].runtimeClasspath.asPath) - } - } - } // the "dockerize" task is added to all projects that use the `shadowJar` plugin diff --git a/charts/tractusx-connector-azure-vault/README.md b/charts/tractusx-connector-azure-vault/README.md index f8d970605..e056ee64f 100644 --- a/charts/tractusx-connector-azure-vault/README.md +++ b/charts/tractusx-connector-azure-vault/README.md @@ -160,11 +160,6 @@ helm install my-release tractusx-edc/tractusx-connector-azure-vault --version 0. | controlplane.securityContext.runAsUser | int | `10001` | The container's process will run with the specified uid | | controlplane.service.annotations | object | `{}` | | | controlplane.service.type | string | `"ClusterIP"` | [Service type](https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services-service-types) to expose the running application on a set of Pods as a network service. | -| controlplane.ssi.miw.authorityId | string | `""` | The BPN of the issuer authority | -| controlplane.ssi.miw.url | string | `""` | MIW URL | -| controlplane.ssi.oauth.client.id | string | `""` | The client ID for KeyCloak | -| controlplane.ssi.oauth.client.secretAlias | string | `"client-secret"` | The alias under which the client secret is stored in the vault. | -| controlplane.ssi.oauth.tokenurl | string | `""` | The URL (of KeyCloak), where access tokens can be obtained | | controlplane.tolerations | list | `[]` | | | controlplane.url.protocol | string | `""` | Explicitly declared url for reaching the dsp api (e.g. if ingresses not used) | | controlplane.volumeMounts | string | `nil` | declare where to mount [volumes](https://kubernetes.io/docs/concepts/storage/volumes/) into the container | diff --git a/charts/tractusx-connector-azure-vault/templates/deployment-controlplane.yaml b/charts/tractusx-connector-azure-vault/templates/deployment-controlplane.yaml index cc533e5d1..f5e187f1c 100644 --- a/charts/tractusx-connector-azure-vault/templates/deployment-controlplane.yaml +++ b/charts/tractusx-connector-azure-vault/templates/deployment-controlplane.yaml @@ -147,22 +147,6 @@ spec: - name: EDC_PARTICIPANT_ID value: {{ .Values.participant.id | required ".Values.participant.id is required" | quote }} - ########################## - # SSI / MIW CONFIGURATION - ########################## - - name: "TX_SSI_MIW_URL" - value: {{ .Values.controlplane.ssi.miw.url | quote }} - - name: "TX_SSI_MIW_AUTHORITY_ID" - value: {{ .Values.controlplane.ssi.miw.authorityId | quote }} - - name: "TX_SSI_OAUTH_TOKEN_URL" - value: {{ .Values.controlplane.ssi.oauth.tokenurl | quote }} - - name: "TX_SSI_OAUTH_CLIENT_ID" - value: {{ .Values.controlplane.ssi.oauth.client.id | quote }} - - name: "TX_SSI_OAUTH_CLIENT_SECRET_ALIAS" - value: {{ .Values.controlplane.ssi.oauth.client.secretAlias | quote }} - - name: "TX_SSI_ENDPOINT_AUDIENCE" - value: {{ printf "%s%s" (include "txdc.controlplane.url.protocol" .) .Values.controlplane.endpoints.protocol.path | quote }} - ####### # API # ####### diff --git a/charts/tractusx-connector-azure-vault/values.yaml b/charts/tractusx-connector-azure-vault/values.yaml index 38a24c0e9..157fcb2b8 100644 --- a/charts/tractusx-connector-azure-vault/values.yaml +++ b/charts/tractusx-connector-azure-vault/values.yaml @@ -119,21 +119,6 @@ controlplane: agreementValidation: true edr: transferProxyTokenValidity: "2592000" - # SSI configuration - ssi: - miw: - # -- MIW URL - url: "" - # -- The BPN of the issuer authority - authorityId: "" - oauth: - # -- The URL (of KeyCloak), where access tokens can be obtained - tokenurl: "" - client: - # -- The client ID for KeyCloak - id: "" - # -- The alias under which the client secret is stored in the vault. - secretAlias: "client-secret" service: # -- [Service type](https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services-service-types) to expose the running application on a set of Pods as a network service. diff --git a/charts/tractusx-connector-memory/README.md b/charts/tractusx-connector-memory/README.md index 48a35e060..5fa0c2d74 100644 --- a/charts/tractusx-connector-memory/README.md +++ b/charts/tractusx-connector-memory/README.md @@ -147,11 +147,6 @@ helm install my-release tractusx-edc/tractusx-connector-memory --version 0.6.0 \ | runtime.securityContext.runAsUser | int | `10001` | The container's process will run with the specified uid | | runtime.service.annotations | object | `{}` | | | runtime.service.type | string | `"ClusterIP"` | [Service type](https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services-service-types) to expose the running application on a set of Pods as a network service. | -| runtime.ssi.miw.authorityId | string | `""` | The BPN of the issuer authority | -| runtime.ssi.miw.url | string | `""` | MIW URL | -| runtime.ssi.oauth.client.id | string | `""` | The client ID for KeyCloak | -| runtime.ssi.oauth.client.secretAlias | string | `"client-secret"` | The alias under which the client secret is stored in the vault. | -| runtime.ssi.oauth.tokenurl | string | `""` | The URL (of KeyCloak), where access tokens can be obtained | | runtime.tolerations | list | `[]` | | | runtime.url.protocol | string | `""` | Explicitly declared url for reaching the dsp api (e.g. if ingresses not used) | | runtime.url.public | string | `""` | | diff --git a/charts/tractusx-connector-memory/templates/deployment-runtime.yaml b/charts/tractusx-connector-memory/templates/deployment-runtime.yaml index 8e8daf0fe..a9453bcec 100644 --- a/charts/tractusx-connector-memory/templates/deployment-runtime.yaml +++ b/charts/tractusx-connector-memory/templates/deployment-runtime.yaml @@ -147,23 +147,6 @@ spec: - name: EDC_PARTICIPANT_ID value: {{ .Values.participant.id | required ".Values.participant.id is required" | quote }} - ########################## - # SSI / MIW CONFIGURATION - ########################## - - name: "TX_SSI_MIW_URL" - value: {{ .Values.runtime.ssi.miw.url | quote }} - - name: "TX_SSI_MIW_AUTHORITY_ID" - value: {{ .Values.runtime.ssi.miw.authorityId | quote }} - - name: "TX_SSI_OAUTH_TOKEN_URL" - value: {{ .Values.runtime.ssi.oauth.tokenurl | quote }} - - name: "TX_SSI_OAUTH_CLIENT_ID" - value: {{ .Values.runtime.ssi.oauth.client.id | quote }} - - name: "TX_SSI_OAUTH_CLIENT_SECRET_ALIAS" - value: {{ .Values.runtime.ssi.oauth.client.secretAlias | quote }} - - name: "TX_SSI_ENDPOINT_AUDIENCE" - value: {{ printf "%s%s" (include "txdc.runtime.url.protocol" .) .Values.runtime.endpoints.protocol.path | quote }} - - ####### # API # ####### diff --git a/charts/tractusx-connector-memory/values.yaml b/charts/tractusx-connector-memory/values.yaml index 047c40093..886610abb 100644 --- a/charts/tractusx-connector-memory/values.yaml +++ b/charts/tractusx-connector-memory/values.yaml @@ -114,21 +114,6 @@ runtime: agreementValidation: true edr: transferProxyTokenValidity: "2592000" - # SSI configuration - ssi: - miw: - # -- MIW URL - url: "" - # -- The BPN of the issuer authority - authorityId: "" - oauth: - # -- The URL (of KeyCloak), where access tokens can be obtained - tokenurl: "" - client: - # -- The client ID for KeyCloak - id: "" - # -- The alias under which the client secret is stored in the vault. - secretAlias: "client-secret" service: # -- [Service type](https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services-service-types) to expose the running application on a set of Pods as a network service. diff --git a/charts/tractusx-connector/templates/deployment-controlplane.yaml b/charts/tractusx-connector/templates/deployment-controlplane.yaml index ad26c55e7..06c482763 100644 --- a/charts/tractusx-connector/templates/deployment-controlplane.yaml +++ b/charts/tractusx-connector/templates/deployment-controlplane.yaml @@ -147,22 +147,6 @@ spec: - name: EDC_PARTICIPANT_ID value: {{ .Values.participant.id | required ".Values.participant.id is required" | quote }} - ########################## - # SSI / MIW CONFIGURATION - ########################## - - name: "TX_SSI_MIW_URL" - value: {{ .Values.controlplane.ssi.miw.url | quote }} - - name: "TX_SSI_MIW_AUTHORITY_ID" - value: {{ .Values.controlplane.ssi.miw.authorityId | quote }} - - name: "TX_SSI_OAUTH_TOKEN_URL" - value: {{ .Values.controlplane.ssi.oauth.tokenurl | quote }} - - name: "TX_SSI_OAUTH_CLIENT_ID" - value: {{ .Values.controlplane.ssi.oauth.client.id | quote }} - - name: "TX_SSI_OAUTH_CLIENT_SECRET_ALIAS" - value: {{ .Values.controlplane.ssi.oauth.client.secretAlias | quote }} - - name: "TX_SSI_ENDPOINT_AUDIENCE" - value: {{ printf "%s%s" (include "txdc.controlplane.url.protocol" .) .Values.controlplane.endpoints.protocol.path | quote }} - ####### # API # ####### @@ -336,14 +320,6 @@ spec: - name: "EDC_VAULT_HASHICORP_API_HEALTH_CHECK_PATH" value: {{ .Values.vault.hashicorp.paths.health | quote }} - ########################### - ## AAS WRAPPER EXTENSION ## - ########################### - - name: "EDC_CP_ADAPTER_CACHE_CATALOG_EXPIRE_AFTER" - value: "0" - - name: "EDC_CP_ADAPTER_REUSE_CONTRACT_AGREEMENT" - value: "0" - ########################### ## BUSINESS PARTNER NUMBER VALIDATION EXTENSION ## ########################### diff --git a/edc-controlplane/edc-controlplane-base/build.gradle.kts b/edc-controlplane/edc-controlplane-base/build.gradle.kts index 85fbd011c..fcd3ea7e0 100644 --- a/edc-controlplane/edc-controlplane-base/build.gradle.kts +++ b/edc-controlplane/edc-controlplane-base/build.gradle.kts @@ -35,17 +35,17 @@ dependencies { runtimeOnly(libs.edc.edr.store.receiver) runtimeOnly(libs.edc.dpf.transfer.signaling) - runtimeOnly(project(":edc-extensions:iatp:tx-iatp-sts-dim")) // needed for BPN validation runtimeOnly(project(":edc-extensions:bpn-validation")) - // needed for SSI integration + // needed for IATP integration runtimeOnly(project(":core:json-ld-core")) - runtimeOnly(project(":edc-extensions:ssi:ssi-identity-core")) - runtimeOnly(project(":edc-extensions:ssi:ssi-miw-credential-client")) - runtimeOnly(project(":edc-extensions:ssi:ssi-identity-extractor")) - runtimeOnly(project(":edc-extensions:cx-policy-legacy")) + runtimeOnly(libs.edc.core.did) + runtimeOnly(libs.edc.core.identitytrust) + runtimeOnly(project(":edc-extensions:iatp:tx-iatp-sts-dim")) + runtimeOnly(project(":edc-extensions:bdrs-client")) + runtimeOnly(libs.edc.core.connector) runtimeOnly(libs.edc.core.controlplane) diff --git a/edc-dataplane/edc-dataplane-base/build.gradle.kts b/edc-dataplane/edc-dataplane-base/build.gradle.kts index 49e47d00f..9132e462b 100644 --- a/edc-dataplane/edc-dataplane-base/build.gradle.kts +++ b/edc-dataplane/edc-dataplane-base/build.gradle.kts @@ -29,7 +29,7 @@ dependencies { runtimeOnly(project(":edc-extensions:dataplane:dataplane-token-refresh:token-refresh-api")) runtimeOnly(libs.edc.jsonld) // needed by the DataPlaneSignalingApi - runtimeOnly(libs.edc.identity.core.did) // for the DID Public Key Resolver + runtimeOnly(libs.edc.core.did) // for the DID Public Key Resolver runtimeOnly(libs.edc.config.filesystem) runtimeOnly(libs.edc.auth.tokenbased) runtimeOnly(libs.edc.dpf.awss3) diff --git a/edc-extensions/bdrs-client/build.gradle.kts b/edc-extensions/bdrs-client/build.gradle.kts index a7367d260..11da5875e 100644 --- a/edc-extensions/bdrs-client/build.gradle.kts +++ b/edc-extensions/bdrs-client/build.gradle.kts @@ -23,6 +23,7 @@ plugins { } dependencies { + implementation(project(":core:core-utils")) implementation(libs.edc.spi.core) implementation(libs.edc.spi.http) diff --git a/edc-extensions/bdrs-client/src/main/java/org/eclipse/tractusx/edc/identity/mapper/BdrsClientExtension.java b/edc-extensions/bdrs-client/src/main/java/org/eclipse/tractusx/edc/identity/mapper/BdrsClientExtension.java index 8232d9887..a9899db07 100644 --- a/edc-extensions/bdrs-client/src/main/java/org/eclipse/tractusx/edc/identity/mapper/BdrsClientExtension.java +++ b/edc-extensions/bdrs-client/src/main/java/org/eclipse/tractusx/edc/identity/mapper/BdrsClientExtension.java @@ -28,6 +28,7 @@ import org.eclipse.edc.spi.system.ServiceExtension; import org.eclipse.edc.spi.system.ServiceExtensionContext; import org.eclipse.edc.spi.types.TypeManager; +import org.eclipse.tractusx.edc.core.utils.RequiredConfigWarnings; import static org.eclipse.tractusx.edc.identity.mapper.BdrsClientExtension.NAME; @@ -56,7 +57,7 @@ public String name() { public AudienceResolver getBdrsAudienceResolver(ServiceExtensionContext context) { var baseUrl = context.getConfig().getString(BDRS_SERVER_URL_PROPERTY, null); if (baseUrl == null) { - context.getMonitor().severe("The following property was expected but was not provided: '%s'. This runtime will not work correctly!".formatted(BDRS_SERVER_URL_PROPERTY)); + RequiredConfigWarnings.warningNotPresent(context.getMonitor(), BDRS_SERVER_URL_PROPERTY); } var cacheValidity = context.getConfig().getInteger(BDRS_SERVER_CACHE_VALIDITY_PERIOD, DEFAULT_BDRS_CACHE_VALIDITY); return new BdrsClient(baseUrl, cacheValidity, httpClient, context.getMonitor(), typeManager.getMapper()); diff --git a/edc-extensions/bdrs-client/src/test/java/org/eclipse/tractusx/edc/identity/mapper/BdrsClientExtensionTest.java b/edc-extensions/bdrs-client/src/test/java/org/eclipse/tractusx/edc/identity/mapper/BdrsClientExtensionTest.java index 4ca60ab13..6123f1332 100644 --- a/edc-extensions/bdrs-client/src/test/java/org/eclipse/tractusx/edc/identity/mapper/BdrsClientExtensionTest.java +++ b/edc-extensions/bdrs-client/src/test/java/org/eclipse/tractusx/edc/identity/mapper/BdrsClientExtensionTest.java @@ -30,7 +30,6 @@ import static org.eclipse.tractusx.edc.identity.mapper.BdrsClientExtension.BDRS_SERVER_URL_PROPERTY; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.isNull; -import static org.mockito.ArgumentMatchers.matches; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -52,6 +51,7 @@ void createClient_whenUrlMissing_expectLogError(ServiceExtensionContext context, when(cfg.getString(eq(BDRS_SERVER_URL_PROPERTY), isNull())).thenReturn(null); extension.getBdrsAudienceResolver(context); - verify(monitor).severe(matches("^The following property was expected but was not provided: '.*'. This runtime will not work correctly!$")); + verify(monitor).severe(eq("Mandatory config value missing: 'tx.iam.iatp.bdrs.server.url'. This runtime will not be fully operational! Starting with v0.7.x this will be a runtime error.")); + } } \ No newline at end of file diff --git a/edc-extensions/cx-policy-legacy/build.gradle.kts b/edc-extensions/cx-policy-legacy/build.gradle.kts deleted file mode 100644 index def8283d6..000000000 --- a/edc-extensions/cx-policy-legacy/build.gradle.kts +++ /dev/null @@ -1,33 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -plugins { - `java-library` -} - -dependencies { - implementation(project(":spi:core-spi")) - implementation(project(":spi:ssi-spi")) - implementation(libs.edc.spi.policyengine) - implementation(libs.jakartaJson) - implementation(libs.edc.spi.identitytrust) - testImplementation(libs.jacksonJsonP) - testImplementation(libs.titaniumJsonLd) - testImplementation(testFixtures(project(":spi:ssi-spi"))) -} diff --git a/edc-extensions/cx-policy-legacy/src/main/java/org/eclipse/tractusx/edc/policy/cx/CxPolicyExtension.java b/edc-extensions/cx-policy-legacy/src/main/java/org/eclipse/tractusx/edc/policy/cx/CxPolicyExtension.java deleted file mode 100644 index a47c8b169..000000000 --- a/edc-extensions/cx-policy-legacy/src/main/java/org/eclipse/tractusx/edc/policy/cx/CxPolicyExtension.java +++ /dev/null @@ -1,55 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.policy.cx; - -import org.eclipse.edc.policy.engine.spi.PolicyEngine; -import org.eclipse.edc.policy.engine.spi.RuleBindingRegistry; -import org.eclipse.edc.runtime.metamodel.annotation.Inject; -import org.eclipse.edc.spi.system.ServiceExtension; -import org.eclipse.edc.spi.system.ServiceExtensionContext; - -import static org.eclipse.tractusx.edc.policy.cx.summary.SummaryConstraintFunctionsProvider.registerBindings; -import static org.eclipse.tractusx.edc.policy.cx.summary.SummaryConstraintFunctionsProvider.registerFunctions; - - -/** - * Provides implementations of standard CX usage policies. - */ -public class CxPolicyExtension implements ServiceExtension { - private static final String NAME = "CX Policy"; - - @Inject - private PolicyEngine policyEngine; - - @Inject - private RuleBindingRegistry bindingRegistry; - - @Override - public String name() { - return NAME; - } - - @Override - public void initialize(ServiceExtensionContext context) { - - registerBindings(bindingRegistry); - registerFunctions(policyEngine); - } -} diff --git a/edc-extensions/cx-policy-legacy/src/main/java/org/eclipse/tractusx/edc/policy/cx/common/AbstractDynamicCredentialConstraintFunction.java b/edc-extensions/cx-policy-legacy/src/main/java/org/eclipse/tractusx/edc/policy/cx/common/AbstractDynamicCredentialConstraintFunction.java deleted file mode 100644 index 164744403..000000000 --- a/edc-extensions/cx-policy-legacy/src/main/java/org/eclipse/tractusx/edc/policy/cx/common/AbstractDynamicCredentialConstraintFunction.java +++ /dev/null @@ -1,80 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.policy.cx.common; - -import org.eclipse.edc.identitytrust.model.VerifiableCredential; -import org.eclipse.edc.policy.engine.spi.DynamicAtomicConstraintFunction; -import org.eclipse.edc.policy.engine.spi.PolicyContext; -import org.eclipse.edc.policy.model.Operator; -import org.eclipse.edc.policy.model.Permission; -import org.eclipse.edc.spi.agent.ParticipantAgent; -import org.eclipse.edc.spi.result.Result; - -import java.util.Collection; -import java.util.List; - -/** - * This is a base class for dynamically bound Tractus-X constraint evaluation functions that implements some basic common functionality and defines some - * common constants - */ -public abstract class AbstractDynamicCredentialConstraintFunction implements DynamicAtomicConstraintFunction { - public static final String VC_CLAIM = "vc"; - public static final String ACTIVE = "active"; - public static final String CREDENTIAL_LITERAL = "Credential"; - protected static final Collection EQUALITY_OPERATORS = List.of(Operator.EQ, Operator.NEQ); - - protected boolean checkOperator(Operator actual, PolicyContext context, Collection expectedOperators) { - if (!expectedOperators.contains(actual)) { - context.reportProblem("Invalid operator: this constraint only allows the following operators: %s, but received '%s'.".formatted(EQUALITY_OPERATORS, actual)); - return false; - } - return true; - } - - protected Result extractParticipantAgent(PolicyContext context) { - // make sure the ParticipantAgent is there - var participantAgent = context.getContextData(ParticipantAgent.class); - if (participantAgent == null) { - return Result.failure("Required PolicyContext data not found: " + ParticipantAgent.class.getName()); - } - return Result.success(participantAgent); - } - - /** - * Extracts a {@link List} of {@link VerifiableCredential} objects from the {@link ParticipantAgent}. Credentials must be - * stored in the agent's claims map using the "vc" key. - */ - protected Result> getCredentialList(ParticipantAgent agent) { - var vcListClaim = agent.getClaims().get(VC_CLAIM); - - if (vcListClaim == null) { - return Result.failure("ParticipantAgent did not contain a '%s' claim.".formatted(VC_CLAIM)); - } - if (!(vcListClaim instanceof List)) { - return Result.failure("ParticipantAgent contains a '%s' claim, but the type is incorrect. Expected %s, received %s.".formatted(VC_CLAIM, List.class.getName(), vcListClaim.getClass().getName())); - } - var vcList = (List) vcListClaim; - if (vcList.isEmpty()) { - return Result.failure("ParticipantAgent contains a '%s' claim but it did not contain any VerifiableCredentials.".formatted(VC_CLAIM)); - } - return Result.success(vcList); - } - -} diff --git a/edc-extensions/cx-policy-legacy/src/main/java/org/eclipse/tractusx/edc/policy/cx/common/AbstractVpConstraintFunction.java b/edc-extensions/cx-policy-legacy/src/main/java/org/eclipse/tractusx/edc/policy/cx/common/AbstractVpConstraintFunction.java deleted file mode 100644 index f0a955f8f..000000000 --- a/edc-extensions/cx-policy-legacy/src/main/java/org/eclipse/tractusx/edc/policy/cx/common/AbstractVpConstraintFunction.java +++ /dev/null @@ -1,130 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.policy.cx.common; - -import jakarta.json.JsonObject; -import jakarta.json.JsonValue; -import org.eclipse.edc.policy.engine.spi.AtomicConstraintFunction; -import org.eclipse.edc.policy.engine.spi.PolicyContext; -import org.eclipse.edc.policy.model.Operator; -import org.eclipse.edc.policy.model.Permission; -import org.eclipse.tractusx.edc.iam.ssi.spi.jsonld.JsonLdFieldExtractor; -import org.jetbrains.annotations.Nullable; - -import java.util.stream.Collectors; - -import static jakarta.json.JsonValue.ValueType.OBJECT; -import static java.lang.String.format; -import static java.util.Arrays.stream; -import static java.util.Objects.requireNonNull; -import static java.util.stream.Collectors.joining; -import static org.eclipse.tractusx.edc.iam.ssi.spi.jsonld.CredentialsNamespaces.CREDENTIAL_SUBJECT; - -/** - * Base processing for constraint functions that verify a permission against a Catena-X verifiable presentation. - */ -public abstract class AbstractVpConstraintFunction implements AtomicConstraintFunction { - - protected static final String VALUE = "@value"; - private static final String ERROR_PREFIX_TEMPLATE = "Invalid %s VC format: "; - protected final String errorPrefix; - protected final String credentialType; - private JsonLdFieldExtractor credentialSubjectExtractor = JsonLdFieldExtractor.Builder.newInstance() - .field(CREDENTIAL_SUBJECT) - .fieldAlias("credentialSubject") - .build(); - - /** - * Ctor. - * - * @param credentialType the credential type that will be verified against. - */ - public AbstractVpConstraintFunction(String credentialType) { - requireNonNull(credentialType); - this.credentialType = credentialType; - this.errorPrefix = format(ERROR_PREFIX_TEMPLATE, credentialType); - this.credentialSubjectExtractor = JsonLdFieldExtractor.Builder.newInstance() - .field(CREDENTIAL_SUBJECT) - .fieldAlias("credentialSubject") - .errorPrefix(errorPrefix) - .build(); - } - - /** - * Validates the operator is in the set of expected operators. - */ - protected boolean validateOperator(Operator operator, PolicyContext context, Operator... expectedOperators) { - var set = stream(expectedOperators).collect(Collectors.toSet()); - if (!set.contains(operator)) { - var valid = set.stream().map(Enum::toString).collect(joining(",")); - context.reportProblem(format("Unsupported operator for %s credential constraint, only %s allowed: %s", credentialType, valid, operator)); - return false; - } - return true; - } - - /** - * Validates the VP by checking that it is a {@link JsonObject}. - */ - protected boolean validatePresentation(@Nullable Object vp, PolicyContext context) { - if (vp == null) { - context.reportProblem(format("%s VP not found", credentialType)); - return false; - } - - if (!(vp instanceof JsonValue jsonValue)) { - context.reportProblem(format("%s VP is not a JSON type: %s", credentialType, vp.getClass().getName())); - return false; - } - - if (!(OBJECT == jsonValue.getValueType())) { - context.reportProblem(format("%s VP must be type %s but was: %s", credentialType, OBJECT, jsonValue.getValueType())); - return false; - } - - return true; - } - - /** - * Returns the credential subject portion of a VC or null if there was an error. Error information will be reported to the context. - */ - @Nullable - protected JsonObject extractCredentialSubject(JsonObject credential, PolicyContext context) { - return credentialSubjectExtractor.extract(credential).onFailure(failure -> context.reportProblem(failure.getFailureDetail())).getContent(); - } - - /** - * Returns true if the actual operand value is a string literal case-insensitive equal to the expected value. - */ - protected boolean validateRightOperand(String expectedValue, Object actualValue, PolicyContext context) { - if (!(actualValue instanceof String)) { - context.reportProblem(format("Invalid right operand format specified for %s credential", credentialType)); - return false; - } - - if (!expectedValue.equalsIgnoreCase(actualValue.toString().trim())) { - context.reportProblem(format("Invalid right operand specified for %s credential: %s", credentialType, actualValue)); - return false; - } - - return true; - } - -} diff --git a/edc-extensions/cx-policy-legacy/src/main/java/org/eclipse/tractusx/edc/policy/cx/common/PolicyScopes.java b/edc-extensions/cx-policy-legacy/src/main/java/org/eclipse/tractusx/edc/policy/cx/common/PolicyScopes.java deleted file mode 100644 index 84311bf4c..000000000 --- a/edc-extensions/cx-policy-legacy/src/main/java/org/eclipse/tractusx/edc/policy/cx/common/PolicyScopes.java +++ /dev/null @@ -1,33 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.policy.cx.common; - -/** - * Defines standard EDC policy scopes. - */ -public interface PolicyScopes { - String CATALOG_REQUEST_SCOPE = "request.catalog"; - String NEGOTIATION_REQUEST_SCOPE = "request.contract.negotiation"; - String TRANSFER_PROCESS_REQUEST_SCOPE = "request.transfer.process"; - - String CATALOG_SCOPE = "catalog"; - String NEGOTIATION_SCOPE = "contract.negotiation"; - String TRANSFER_PROCESS_SCOPE = "transfer.process"; -} diff --git a/edc-extensions/cx-policy-legacy/src/main/java/org/eclipse/tractusx/edc/policy/cx/summary/SummaryConstraintFunction.java b/edc-extensions/cx-policy-legacy/src/main/java/org/eclipse/tractusx/edc/policy/cx/summary/SummaryConstraintFunction.java deleted file mode 100644 index cde06be3f..000000000 --- a/edc-extensions/cx-policy-legacy/src/main/java/org/eclipse/tractusx/edc/policy/cx/summary/SummaryConstraintFunction.java +++ /dev/null @@ -1,117 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.policy.cx.summary; - -import jakarta.json.JsonObject; -import jakarta.json.JsonString; -import jakarta.json.JsonValue; -import org.eclipse.edc.policy.engine.spi.PolicyContext; -import org.eclipse.edc.policy.model.Operator; -import org.eclipse.edc.policy.model.Permission; -import org.eclipse.edc.spi.agent.ParticipantAgent; -import org.eclipse.tractusx.edc.iam.ssi.spi.jsonld.CredentialsNamespaces; -import org.eclipse.tractusx.edc.policy.cx.common.AbstractVpConstraintFunction; - -import java.util.Map; - -import static jakarta.json.JsonValue.ValueType.ARRAY; -import static jakarta.json.JsonValue.ValueType.OBJECT; -import static jakarta.json.JsonValue.ValueType.STRING; -import static java.lang.String.format; -import static java.util.Objects.requireNonNull; -import static org.eclipse.edc.policy.model.Operator.EQ; -import static org.eclipse.tractusx.edc.iam.ssi.spi.jsonld.CredentialsNamespaces.SUMMARY_CREDENTIAL_TYPE; -import static org.eclipse.tractusx.edc.iam.ssi.spi.jsonld.CredentialsNamespaces.VP_PROPERTY; -import static org.eclipse.tractusx.edc.iam.ssi.spi.jsonld.JsonLdTypeFunctions.extractObjectsOfType; - - -/** - * Implements Catena-X policies by verifying policy constraints against the summary credential. - *

    - * Verifies the presence of an entry in the {@link #SUMMARY_CREDENTIAL_ITEMS} of a summary credential token. - */ -public class SummaryConstraintFunction extends AbstractVpConstraintFunction { - private static final String SUMMARY_CREDENTIAL_ITEMS = CredentialsNamespaces.CX_SUMMARY_NS + "/items"; - private static final String CREDENTIAL_SUBJECT = "credentialSubject"; - - private static final String ACTIVE = "active"; - - private final String summaryType; - - public SummaryConstraintFunction(String summaryType) { - super("Summary"); - requireNonNull(summaryType); - this.summaryType = summaryType; - } - - @Override - public boolean evaluate(Operator operator, Object rightValue, Permission rule, PolicyContext context) { - if (!validateOperator(operator, context, EQ)) { - return false; - } - - if (!validateRightOperand(ACTIVE, rightValue, context)) { - return false; - } - - var vp = (JsonObject) context.getContextData(ParticipantAgent.class).getClaims().get(VP_PROPERTY); - if (!validatePresentation(vp, context)) { - return false; - } - - return extractObjectsOfType(SUMMARY_CREDENTIAL_TYPE, vp).anyMatch(credential -> hasSummaryType(credential, context)); - } - - /** - * Returns true if the summary credential has the item specified by {@link #summaryType}. - */ - private boolean hasSummaryType(JsonObject credential, PolicyContext context) { - var credentialSubject = extractCredentialSubject(credential, context); - if (credentialSubject == null) { - return false; - } - var items = credentialSubject.get(SUMMARY_CREDENTIAL_ITEMS); - - if (items == null || items.getValueType() != ARRAY) { - context.reportProblem(format("%s items not found in %s", errorPrefix, CREDENTIAL_SUBJECT)); - return false; - } - - if (items.asJsonArray().isEmpty()) { - context.reportProblem(format("%s empty %s items graph container", errorPrefix, CREDENTIAL_SUBJECT)); - return false; - } - - return items.asJsonArray().stream().filter(e -> e.getValueType() == OBJECT) - .flatMap(o -> o.asJsonObject().entrySet().stream()) - .anyMatch(this::matchSummaryType); - } - - /** - * Returns true if the entry is a string and matches the Json-Ld {@link #VALUE} type. - */ - private boolean matchSummaryType(Map.Entry e) { - return VALUE.equals(e.getKey()) && - e.getValue().getValueType() == STRING && - summaryType.equals(((JsonString) e.getValue()).getString()); - } - - -} diff --git a/edc-extensions/cx-policy-legacy/src/main/java/org/eclipse/tractusx/edc/policy/cx/summary/SummaryConstraintFunctionsProvider.java b/edc-extensions/cx-policy-legacy/src/main/java/org/eclipse/tractusx/edc/policy/cx/summary/SummaryConstraintFunctionsProvider.java deleted file mode 100644 index d9218ee35..000000000 --- a/edc-extensions/cx-policy-legacy/src/main/java/org/eclipse/tractusx/edc/policy/cx/summary/SummaryConstraintFunctionsProvider.java +++ /dev/null @@ -1,113 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.policy.cx.summary; - -import org.eclipse.edc.policy.engine.spi.PolicyEngine; -import org.eclipse.edc.policy.engine.spi.RuleBindingRegistry; -import org.eclipse.edc.policy.model.Permission; - -import java.util.HashMap; -import java.util.Map; - -import static java.util.Collections.unmodifiableMap; -import static org.eclipse.edc.policy.model.OdrlNamespace.ODRL_SCHEMA; -import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.TX_NAMESPACE; -import static org.eclipse.tractusx.edc.policy.cx.common.PolicyScopes.CATALOG_REQUEST_SCOPE; -import static org.eclipse.tractusx.edc.policy.cx.common.PolicyScopes.CATALOG_SCOPE; -import static org.eclipse.tractusx.edc.policy.cx.common.PolicyScopes.NEGOTIATION_REQUEST_SCOPE; -import static org.eclipse.tractusx.edc.policy.cx.common.PolicyScopes.NEGOTIATION_SCOPE; -import static org.eclipse.tractusx.edc.policy.cx.common.PolicyScopes.TRANSFER_PROCESS_REQUEST_SCOPE; -import static org.eclipse.tractusx.edc.policy.cx.common.PolicyScopes.TRANSFER_PROCESS_SCOPE; - -/** - * Registers {@link SummaryConstraintFunction} and {@link SummaryTokenPolicyFunction} instances with the runtime policy engine. - */ -public class SummaryConstraintFunctionsProvider { - - /** - * Mappings from policy constraint left operand values to the corresponding item value in the summary VP. - */ - static final Map CREDENTIAL_MAPPINGS; - - - static { - var initialMappings = Map.of( - "Membership", "MembershipCredential", - "Dismantler", "DismantlerCredential", - "FrameworkAgreement.pcf", "PcfCredential", - "FrameworkAgreement.sustainability", "SustainabilityCredential", - "FrameworkAgreement.quality", "QualityCredential", - "FrameworkAgreement.traceability", "TraceabilityCredential", - "FrameworkAgreement.behavioraltwin", "BehaviorTwinCredential", - "BPN", "BpnCredential" - ); - var mappings = new HashMap<>(initialMappings); - initialMappings.forEach((credentialName, summaryType) -> { - mappings.put(TX_NAMESPACE + credentialName, summaryType); - }); - CREDENTIAL_MAPPINGS = unmodifiableMap(mappings); - } - - /** - * Configures and registers required summary functions with the policy engine. - */ - public static void registerFunctions(PolicyEngine engine) { - var tokenPolicyFunction = new SummaryTokenPolicyFunction(); - engine.registerPreValidator(CATALOG_REQUEST_SCOPE, tokenPolicyFunction); - engine.registerPreValidator(NEGOTIATION_REQUEST_SCOPE, tokenPolicyFunction); - engine.registerPreValidator(TRANSFER_PROCESS_REQUEST_SCOPE, tokenPolicyFunction); - - CREDENTIAL_MAPPINGS.forEach((constraintName, summaryType) -> { - - engine.registerFunction(CATALOG_SCOPE, - Permission.class, - constraintName, - new SummaryConstraintFunction(summaryType)); - - engine.registerFunction(NEGOTIATION_SCOPE, - Permission.class, - constraintName, - new SummaryConstraintFunction(summaryType)); - - engine.registerFunction(TRANSFER_PROCESS_SCOPE, - Permission.class, - constraintName, - new SummaryConstraintFunction(summaryType)); - }); - - } - - public static void registerBindings(RuleBindingRegistry registry) { - CREDENTIAL_MAPPINGS.forEach((constraintName, summaryType) -> { - registry.bind(constraintName, CATALOG_REQUEST_SCOPE); - registry.bind(constraintName, NEGOTIATION_REQUEST_SCOPE); - registry.bind(constraintName, TRANSFER_PROCESS_REQUEST_SCOPE); - registry.bind(constraintName, CATALOG_SCOPE); - registry.bind(constraintName, NEGOTIATION_SCOPE); - registry.bind(constraintName, TRANSFER_PROCESS_SCOPE); - }); - - registry.bind(ODRL_SCHEMA + "use", CATALOG_SCOPE); - registry.bind(ODRL_SCHEMA + "use", NEGOTIATION_SCOPE); - registry.bind(ODRL_SCHEMA + "use", TRANSFER_PROCESS_SCOPE); - - } - -} diff --git a/edc-extensions/cx-policy-legacy/src/main/java/org/eclipse/tractusx/edc/policy/cx/summary/SummaryTokenPolicyFunction.java b/edc-extensions/cx-policy-legacy/src/main/java/org/eclipse/tractusx/edc/policy/cx/summary/SummaryTokenPolicyFunction.java deleted file mode 100644 index 7125a1ae8..000000000 --- a/edc-extensions/cx-policy-legacy/src/main/java/org/eclipse/tractusx/edc/policy/cx/summary/SummaryTokenPolicyFunction.java +++ /dev/null @@ -1,47 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.policy.cx.summary; - -import org.eclipse.edc.policy.engine.spi.PolicyContext; -import org.eclipse.edc.policy.model.Policy; -import org.eclipse.edc.spi.EdcException; -import org.eclipse.edc.spi.iam.RequestScope; - -import java.util.function.BiFunction; - -import static java.lang.String.format; -import static org.eclipse.tractusx.edc.iam.ssi.spi.jsonld.CredentialsNamespaces.CX_SUMMARY_CREDENTIAL; - -/** - * Includes a summary credential in the token parameters. - */ -public class SummaryTokenPolicyFunction implements BiFunction { - - @Override - public Boolean apply(Policy policy, PolicyContext context) { - var scopes = context.getContextData(RequestScope.Builder.class); - if (scopes == null) { - throw new EdcException(format("%s not set in policy context", RequestScope.Builder.class.getName())); - } - - scopes.scope(CX_SUMMARY_CREDENTIAL); - return true; - } -} diff --git a/edc-extensions/cx-policy-legacy/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension b/edc-extensions/cx-policy-legacy/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension deleted file mode 100644 index 3b058563d..000000000 --- a/edc-extensions/cx-policy-legacy/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension +++ /dev/null @@ -1,21 +0,0 @@ -################################################################################# -# Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) -# -# See the NOTICE file(s) distributed with this work for additional -# information regarding copyright ownership. -# -# This program and the accompanying materials are made available under the -# terms of the Apache License, Version 2.0 which is available at -# https://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. -# -# SPDX-License-Identifier: Apache-2.0 -################################################################################# - -org.eclipse.tractusx.edc.policy.cx.CxPolicyExtension - diff --git a/edc-extensions/cx-policy-legacy/src/test/java/org/eclipse/tractusx/edc/policy/cx/CredentialFunctions.java b/edc-extensions/cx-policy-legacy/src/test/java/org/eclipse/tractusx/edc/policy/cx/CredentialFunctions.java deleted file mode 100644 index d562863d5..000000000 --- a/edc-extensions/cx-policy-legacy/src/test/java/org/eclipse/tractusx/edc/policy/cx/CredentialFunctions.java +++ /dev/null @@ -1,90 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.policy.cx; - -import org.eclipse.edc.identitytrust.model.CredentialSubject; -import org.eclipse.edc.identitytrust.model.Issuer; -import org.eclipse.edc.identitytrust.model.VerifiableCredential; - -import java.time.Instant; -import java.time.temporal.ChronoUnit; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.UUID; - -import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.CX_CREDENTIAL_NS; - -public class CredentialFunctions { - - public static VerifiableCredential.Builder createCredential(String type, String version) { - return VerifiableCredential.Builder.newInstance() - .types(List.of(CX_CREDENTIAL_NS + "VerifiableCredential", CX_CREDENTIAL_NS + type)) - .id(UUID.randomUUID().toString()) - .issuer(new Issuer(UUID.randomUUID().toString(), Map.of("prop1", "val1"))) - .expirationDate(Instant.now().plus(365, ChronoUnit.DAYS)) - .issuanceDate(Instant.now()) - .credentialSubject(CredentialSubject.Builder.newInstance() - .id("subject-id") - .claim(CX_CREDENTIAL_NS + "holderIdentifier", "did:web:holder") - .claim(CX_CREDENTIAL_NS + "contractVersion", version) - .claim(CX_CREDENTIAL_NS + "contractTemplate", "https://public.catena-x.org/contracts/pcf.v1.pdf") - .build()); - } - - public static VerifiableCredential.Builder createPcfCredential() { - return createCredential("PcfCredential", "1.0.0"); - } - - public static VerifiableCredential.Builder createDismantlerCredential(String... brands) { - return createDismantlerCredential(Arrays.asList(brands), "vehicleDismantle"); - } - - public static VerifiableCredential.Builder createDismantlerCredential(Collection brands, String... activityType) { - var at = activityType.length == 1 ? activityType[0] : List.of(activityType); - return VerifiableCredential.Builder.newInstance() - .types(List.of("VerifiableCredential", CX_CREDENTIAL_NS + "DismantlerCredential")) - .id(UUID.randomUUID().toString()) - .issuer(new Issuer(UUID.randomUUID().toString(), Map.of("prop1", "val1"))) - .expirationDate(Instant.now().plus(365, ChronoUnit.DAYS)) - .issuanceDate(Instant.now()) - .credentialSubject(CredentialSubject.Builder.newInstance() - .id("subject-id") - .claim(CX_CREDENTIAL_NS + "holderIdentifier", "did:web:holder") - .claim(CX_CREDENTIAL_NS + "allowedVehicleBrands", brands) - .claim(CX_CREDENTIAL_NS + "activityType", at) - .build()); - } - - public static VerifiableCredential.Builder createMembershipCredential() { - return VerifiableCredential.Builder.newInstance() - .types(List.of(CX_CREDENTIAL_NS + "VerifiableCredential", CX_CREDENTIAL_NS + "MembershipCredential")) - .id(UUID.randomUUID().toString()) - .issuer(new Issuer(UUID.randomUUID().toString(), Map.of("prop1", "val1"))) - .expirationDate(Instant.now().plus(365, ChronoUnit.DAYS)) - .issuanceDate(Instant.now()) - .credentialSubject(CredentialSubject.Builder.newInstance() - .id("subject-id") - .claim(CX_CREDENTIAL_NS + "holderIdentifier", "did:web:holder") - .build()); - } - -} diff --git a/edc-extensions/cx-policy-legacy/src/test/java/org/eclipse/tractusx/edc/policy/cx/common/AbstractVpConstraintFunctionTest.java b/edc-extensions/cx-policy-legacy/src/test/java/org/eclipse/tractusx/edc/policy/cx/common/AbstractVpConstraintFunctionTest.java deleted file mode 100644 index 8a978121e..000000000 --- a/edc-extensions/cx-policy-legacy/src/test/java/org/eclipse/tractusx/edc/policy/cx/common/AbstractVpConstraintFunctionTest.java +++ /dev/null @@ -1,114 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.policy.cx.common; - -import com.fasterxml.jackson.core.JsonProcessingException; -import jakarta.json.Json; -import jakarta.json.JsonObject; -import jakarta.json.JsonString; -import org.eclipse.edc.policy.engine.spi.PolicyContext; -import org.eclipse.edc.policy.model.Operator; -import org.eclipse.edc.policy.model.Permission; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import java.util.Map; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.eclipse.tractusx.edc.iam.ssi.spi.jsonld.JsonLdTextFixtures.createObjectMapper; -import static org.eclipse.tractusx.edc.iam.ssi.spi.jsonld.JsonLdTextFixtures.expand; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; - -class AbstractVpConstraintFunctionTest { - private static final String FOO_CREDENTIAL = """ - { - "@context": [ - "https://www.w3.org/2018/credentials/v1" - ], - "id": "urn:uuid:12345678-1234-1234-1234-123456789abc", - "type": [ - "VerifiableCredential", - "FooCredential" - ], - "issuer": "did:web:test", - "credentialSubject": { - "id": "did:web:test" - } - } - """; - private static final String PRESENTATION = """ - { - "@context": [ - "https://www.w3.org/2018/credentials/v1" - ], - "type": "VerifiablePresentation" - } - """; - private AbstractVpConstraintFunction function; - private PolicyContext context; - - @Test - void verify_operators() { - assertThat(function.validateOperator(Operator.EQ, context, Operator.EQ)).isEqualTo(true); - } - - @Test - void verify_invalid_operators() { - assertThat(function.validateOperator(Operator.NEQ, context, Operator.EQ)).isEqualTo(false); - verify(context).reportProblem(anyString()); - } - - @Test - void verify_presentation() throws JsonProcessingException { - var vp = expand(createObjectMapper().readValue(PRESENTATION, JsonObject.class), Map.of()); - - assertThat(function.validatePresentation(vp, context)).isTrue(); - - assertThat(function.validatePresentation(null, context)).isFalse(); - - assertThat(function.validatePresentation("invalid", context)).isFalse(); - - var array = Json.createArrayBuilder().build(); - assertThat(function.validatePresentation(array, context)).isFalse(); - } - - @Test - void verify_extract_credential_subject() throws JsonProcessingException { - var credential = expand(createObjectMapper().readValue(FOO_CREDENTIAL, JsonObject.class), Map.of()); - - var subject = function.extractCredentialSubject(credential, context); - - assertThat(subject).isNotNull(); - assertThat(((JsonString) subject.get("@id")).getString()).isEqualTo("did:web:test"); - } - - @BeforeEach - void setUp() { - context = mock(PolicyContext.class); - function = new AbstractVpConstraintFunction("FooCredential") { - @Override - public boolean evaluate(Operator operator, Object rightValue, Permission rule, PolicyContext context) { - throw new UnsupportedOperationException(); - } - }; - } -} diff --git a/edc-extensions/cx-policy-legacy/src/test/java/org/eclipse/tractusx/edc/policy/cx/summary/SummaryConstraintFunctionTest.java b/edc-extensions/cx-policy-legacy/src/test/java/org/eclipse/tractusx/edc/policy/cx/summary/SummaryConstraintFunctionTest.java deleted file mode 100644 index 5fe674e0b..000000000 --- a/edc-extensions/cx-policy-legacy/src/test/java/org/eclipse/tractusx/edc/policy/cx/summary/SummaryConstraintFunctionTest.java +++ /dev/null @@ -1,71 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.policy.cx.summary; - -import com.fasterxml.jackson.core.JsonProcessingException; -import jakarta.json.JsonObject; -import org.eclipse.edc.policy.engine.spi.PolicyContext; -import org.eclipse.edc.policy.model.Permission; -import org.eclipse.edc.spi.agent.ParticipantAgent; -import org.eclipse.tractusx.edc.iam.ssi.spi.jsonld.SummaryContext; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import java.util.Map; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.eclipse.edc.policy.model.Operator.EQ; -import static org.eclipse.tractusx.edc.iam.ssi.spi.jsonld.CredentialsNamespaces.CX_SUMMARY_NS_V1; -import static org.eclipse.tractusx.edc.iam.ssi.spi.jsonld.CredentialsNamespaces.VP_PROPERTY; -import static org.eclipse.tractusx.edc.iam.ssi.spi.jsonld.JsonLdTextFixtures.createObjectMapper; -import static org.eclipse.tractusx.edc.iam.ssi.spi.jsonld.JsonLdTextFixtures.expand; -import static org.eclipse.tractusx.edc.iam.ssi.spi.jsonld.SummaryCredential.SUMMARY_VP; -import static org.mockito.Mockito.atLeastOnce; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -public class SummaryConstraintFunctionTest { - public static final String CX_QUALITY = "QualityCredential"; - private static final Map CONTEXT_CACHE = Map.of(CX_SUMMARY_NS_V1, SummaryContext.SUMMARY_CONTEXT); - private Permission permission; - private PolicyContext context; - - @Test - void verify_constraint_success() throws JsonProcessingException { - var vp = expand(createObjectMapper().readValue(SUMMARY_VP, JsonObject.class), CONTEXT_CACHE); - - var function = new SummaryConstraintFunction(CX_QUALITY); - - when(context.getContextData(ParticipantAgent.class)).thenReturn(new ParticipantAgent(Map.of(VP_PROPERTY, vp), Map.of())); - - var result = function.evaluate(EQ, "active", permission, context); - - assertThat(result).isTrue(); - - verify(context, atLeastOnce()).getContextData(ParticipantAgent.class); - } - - @BeforeEach - void setUp() { - permission = Permission.Builder.newInstance().build(); - context = mock(PolicyContext.class); - } -} diff --git a/edc-extensions/cx-policy-legacy/src/test/java/org/eclipse/tractusx/edc/policy/cx/summary/SummaryConstraintFunctionsProviderTest.java b/edc-extensions/cx-policy-legacy/src/test/java/org/eclipse/tractusx/edc/policy/cx/summary/SummaryConstraintFunctionsProviderTest.java deleted file mode 100644 index 4603dec70..000000000 --- a/edc-extensions/cx-policy-legacy/src/test/java/org/eclipse/tractusx/edc/policy/cx/summary/SummaryConstraintFunctionsProviderTest.java +++ /dev/null @@ -1,96 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.policy.cx.summary; - -import org.eclipse.edc.policy.engine.spi.PolicyEngine; -import org.eclipse.edc.policy.engine.spi.RuleBindingRegistry; -import org.eclipse.edc.policy.model.Permission; -import org.junit.jupiter.api.Test; - -import static org.eclipse.tractusx.edc.policy.cx.common.PolicyScopes.CATALOG_REQUEST_SCOPE; -import static org.eclipse.tractusx.edc.policy.cx.common.PolicyScopes.CATALOG_SCOPE; -import static org.eclipse.tractusx.edc.policy.cx.common.PolicyScopes.NEGOTIATION_REQUEST_SCOPE; -import static org.eclipse.tractusx.edc.policy.cx.common.PolicyScopes.NEGOTIATION_SCOPE; -import static org.eclipse.tractusx.edc.policy.cx.common.PolicyScopes.TRANSFER_PROCESS_REQUEST_SCOPE; -import static org.eclipse.tractusx.edc.policy.cx.common.PolicyScopes.TRANSFER_PROCESS_SCOPE; -import static org.eclipse.tractusx.edc.policy.cx.summary.SummaryConstraintFunctionsProvider.registerBindings; -import static org.eclipse.tractusx.edc.policy.cx.summary.SummaryConstraintFunctionsProvider.registerFunctions; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; - -class SummaryConstraintFunctionsProviderTest { - - @Test - void verify_function_registrations() { - var policyEngine = mock(PolicyEngine.class); - - registerFunctions(policyEngine); - - assertTokenFunctionsRegistered(CATALOG_REQUEST_SCOPE, policyEngine); - assertTokenFunctionsRegistered(NEGOTIATION_REQUEST_SCOPE, policyEngine); - assertTokenFunctionsRegistered(TRANSFER_PROCESS_REQUEST_SCOPE, policyEngine); - - SummaryConstraintFunctionsProvider.CREDENTIAL_MAPPINGS.forEach((credentialName, summaryType) -> { - assertSummaryFunctionsRegistered(CATALOG_SCOPE, policyEngine, credentialName); - assertSummaryFunctionsRegistered(NEGOTIATION_SCOPE, policyEngine, credentialName); - assertSummaryFunctionsRegistered(TRANSFER_PROCESS_SCOPE, policyEngine, credentialName); - }); - } - - @Test - void verify_binding_registrations() { - var bindingRegistry = mock(RuleBindingRegistry.class); - - registerBindings(bindingRegistry); - - assertRuleTypeRegistered("Membership", bindingRegistry); - assertRuleTypeRegistered("Dismantler", bindingRegistry); - assertRuleTypeRegistered("FrameworkAgreement.pcf", bindingRegistry); - assertRuleTypeRegistered("FrameworkAgreement.sustainability", bindingRegistry); - assertRuleTypeRegistered("FrameworkAgreement.quality", bindingRegistry); - assertRuleTypeRegistered("FrameworkAgreement.traceability", bindingRegistry); - assertRuleTypeRegistered("FrameworkAgreement.behavioraltwin", bindingRegistry); - } - - private void assertTokenFunctionsRegistered(String scope, PolicyEngine policyEngine) { - verify(policyEngine, times(1)).registerPreValidator(eq(scope), any()); - } - - private void assertSummaryFunctionsRegistered(String scope, PolicyEngine policyEngine, String credentialName) { - verify(policyEngine, times(1)).registerFunction( - eq(scope), - eq(Permission.class), - eq(credentialName), - any(SummaryConstraintFunction.class)); - } - - private void assertRuleTypeRegistered(String ruleType, RuleBindingRegistry bindingRegistry) { - verify(bindingRegistry, times(1)).bind(ruleType, CATALOG_REQUEST_SCOPE); - verify(bindingRegistry, times(1)).bind(ruleType, CATALOG_SCOPE); - verify(bindingRegistry, times(1)).bind(ruleType, NEGOTIATION_REQUEST_SCOPE); - verify(bindingRegistry, times(1)).bind(ruleType, NEGOTIATION_SCOPE); - verify(bindingRegistry, times(1)).bind(ruleType, TRANSFER_PROCESS_REQUEST_SCOPE); - verify(bindingRegistry, times(1)).bind(ruleType, TRANSFER_PROCESS_SCOPE); - } - -} diff --git a/edc-extensions/cx-policy-legacy/src/test/java/org/eclipse/tractusx/edc/policy/cx/summary/SummaryTokenPolicyFunctionTest.java b/edc-extensions/cx-policy-legacy/src/test/java/org/eclipse/tractusx/edc/policy/cx/summary/SummaryTokenPolicyFunctionTest.java deleted file mode 100644 index 82e4f175e..000000000 --- a/edc-extensions/cx-policy-legacy/src/test/java/org/eclipse/tractusx/edc/policy/cx/summary/SummaryTokenPolicyFunctionTest.java +++ /dev/null @@ -1,49 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.policy.cx.summary; - -import org.eclipse.edc.policy.engine.spi.PolicyContext; -import org.eclipse.edc.policy.model.Policy; -import org.eclipse.edc.spi.iam.RequestScope; -import org.junit.jupiter.api.Test; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.eclipse.tractusx.edc.iam.ssi.spi.jsonld.CredentialsNamespaces.CX_SUMMARY_CREDENTIAL; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -class SummaryTokenPolicyFunctionTest { - - @Test - void verify_add_credential() { - var function = new SummaryTokenPolicyFunction(); - - var context = mock(PolicyContext.class); - var builder = RequestScope.Builder.newInstance(); - when(context.getContextData(eq(RequestScope.Builder.class))).thenReturn(builder); - - var policy = Policy.Builder.newInstance().build(); - - function.apply(policy, context); - - assertThat(builder.build().getScopes().contains(CX_SUMMARY_CREDENTIAL)).isTrue(); - } -} diff --git a/edc-extensions/cx-policy/build.gradle.kts b/edc-extensions/cx-policy/build.gradle.kts index 9f0e6c79c..15a293e37 100644 --- a/edc-extensions/cx-policy/build.gradle.kts +++ b/edc-extensions/cx-policy/build.gradle.kts @@ -23,12 +23,10 @@ plugins { dependencies { implementation(project(":spi:core-spi")) - implementation(project(":spi:ssi-spi")) implementation(project(":core:core-utils")) implementation(libs.edc.spi.policyengine) implementation(libs.jakartaJson) implementation(libs.edc.spi.identitytrust) testImplementation(libs.jacksonJsonP) testImplementation(libs.titaniumJsonLd) - testImplementation(testFixtures(project(":spi:ssi-spi"))) } diff --git a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-api/build.gradle.kts b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-api/build.gradle.kts index 0439436fa..d86e9ec4d 100644 --- a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-api/build.gradle.kts +++ b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-api/build.gradle.kts @@ -28,6 +28,8 @@ dependencies { implementation(libs.edc.spi.core) implementation(libs.edc.spi.web) implementation(libs.jakarta.rsApi) + implementation(libs.edc.util) + testImplementation(libs.edc.junit) testImplementation(libs.restAssured) diff --git a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-api/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/api/v1/TokenRefreshApi.java b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-api/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/api/v1/TokenRefreshApi.java index abaf84e3a..6d506b719 100644 --- a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-api/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/api/v1/TokenRefreshApi.java +++ b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-api/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/api/v1/TokenRefreshApi.java @@ -34,7 +34,7 @@ import org.eclipse.tractusx.edc.spi.tokenrefresh.dataplane.model.TokenResponse; @SecurityScheme(name = "Authentication", - description = "Self-Issued ID token containing an access_token", + description = "Self-Issued ID token containing a token", type = SecuritySchemeType.HTTP, scheme = "bearer", bearerFormat = "JWT") diff --git a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-api/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/api/v1/TokenRefreshApiController.java b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-api/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/api/v1/TokenRefreshApiController.java index 4757fcae5..ce0c468d2 100644 --- a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-api/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/api/v1/TokenRefreshApiController.java +++ b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-api/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/api/v1/TokenRefreshApiController.java @@ -26,6 +26,7 @@ import jakarta.ws.rs.Produces; import jakarta.ws.rs.QueryParam; import jakarta.ws.rs.core.MediaType; +import org.eclipse.edc.util.string.StringUtils; import org.eclipse.edc.web.spi.exception.AuthenticationFailedException; import org.eclipse.edc.web.spi.exception.InvalidRequestException; import org.eclipse.tractusx.edc.spi.tokenrefresh.dataplane.DataPlaneTokenRefreshService; @@ -52,6 +53,12 @@ public TokenResponse refreshToken(@QueryParam("grant_type") String grantType, if (!REFRESH_TOKEN_GRANT.equals(grantType)) { throw new InvalidRequestException("Grant type MUST be '%s' but was '%s'".formatted(REFRESH_TOKEN_GRANT, grantType)); } + if (StringUtils.isNullOrBlank(refreshToken)) { + throw new InvalidRequestException("Parameter 'refresh_token' cannot be null"); + } + if (StringUtils.isNullOrBlank(bearerToken)) { + throw new AuthenticationFailedException("Authorization header missing"); + } return tokenRefreshService.refreshToken(refreshToken, bearerToken) .orElseThrow(f -> new AuthenticationFailedException(f.getFailureDetail())); diff --git a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImpl.java b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImpl.java index 9a179e945..3a81c74cd 100644 --- a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImpl.java +++ b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImpl.java @@ -136,7 +136,7 @@ public DataPlaneTokenRefreshServiceImpl(Clock clock, *

  • resolve the public key material in the DID Document identified by the {@code kid} header
  • *
  • verify the token's signature
  • *
  • assert {@code iss} and {@code sub} claims are identical
  • - *
  • assert the the token contains an {@code access_token} claim, and that the value is identical to the access token we have on record
  • + *
  • assert the the token contains an {@code token} claim, and that the value is identical to the access token we have on record
  • *
  • assert that the {@code refreshToken} parameter is identical to the refresh token we have on record
  • * * diff --git a/edc-extensions/iatp/tx-iatp-sts-dim/build.gradle.kts b/edc-extensions/iatp/tx-iatp-sts-dim/build.gradle.kts index 4c4b90b45..d225a5f05 100644 --- a/edc-extensions/iatp/tx-iatp-sts-dim/build.gradle.kts +++ b/edc-extensions/iatp/tx-iatp-sts-dim/build.gradle.kts @@ -23,7 +23,7 @@ plugins { } dependencies { - implementation(libs.edc.identity.trust.spi) + implementation(libs.edc.spi.identitytrust) implementation(libs.edc.auth.oauth2.client) implementation(project(":spi:core-spi")) implementation(project(":core:core-utils")) diff --git a/edc-extensions/iatp/tx-iatp-sts-dim/src/main/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/DimSecureTokenService.java b/edc-extensions/iatp/tx-iatp-sts-dim/src/main/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/DimSecureTokenService.java index 6eeef5b4a..aef7c5a5e 100644 --- a/edc-extensions/iatp/tx-iatp-sts-dim/src/main/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/DimSecureTokenService.java +++ b/edc-extensions/iatp/tx-iatp-sts-dim/src/main/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/DimSecureTokenService.java @@ -58,7 +58,7 @@ * SI Token: *
      *
    • grantAccess: request the SI token to DIM by providing the credential types required
    • - *
    • signToken: request the SI token to DIM by providing the extracted `access_token` from the received SI token
    • + *
    • signToken: request the SI token to DIM by providing the extracted `token` from the received SI token
    • *
    */ public class DimSecureTokenService implements SecureTokenService { diff --git a/edc-extensions/iatp/tx-iatp/build.gradle.kts b/edc-extensions/iatp/tx-iatp/build.gradle.kts index 3205d9b55..c4c359f34 100644 --- a/edc-extensions/iatp/tx-iatp/build.gradle.kts +++ b/edc-extensions/iatp/tx-iatp/build.gradle.kts @@ -25,7 +25,7 @@ plugins { dependencies { implementation(libs.edc.spi.core) implementation(libs.edc.spi.policyengine) - implementation(libs.edc.identity.trust.spi) + implementation(libs.edc.spi.identitytrust) implementation(project(":spi:core-spi")) implementation(project(":core:core-utils")) diff --git a/edc-extensions/ssi/ssi-identity-core/README.md b/edc-extensions/ssi/ssi-identity-core/README.md deleted file mode 100644 index 59cc63bfe..000000000 --- a/edc-extensions/ssi/ssi-identity-core/README.md +++ /dev/null @@ -1,25 +0,0 @@ -# SSI Core Identity Service Module - -This module contains an implementation of the EDC identity service for SSI. -The SsiIdentityService contains a `SsiTokenValidationService` for validating the `JWT` token, -that uses an implementation of `SsiCredentialClient` for validating the JWT token and then check custom rules registered in the `SsiValidationRuleRegistry` - -For obtaining the `JWT` token, the identity service also delegate to the `SsiCredentialClient` . - -The default implementation according to the first milestone [here](https://github.com/eclipse-tractusx/ssi-docu/tree/main/docs/architecture/cx-3-2) -will rely on an MIW and the implementations in available in the module `:edc-extensions:ssi:ssi-miw-credential-client`. - -The implementation also provide a rule registry `SsiValidationRuleRegistry` where custom rule can be registered for validating the `ClaimToken` extracted from the `JWT` token. - -Custom rule could be like: - -- Audience validation -- VP/VC validation -- Expiration -- ..etc - -## Configuration - -| Key | Required | Example | Description | -|-----------------------------------------|----------|----------------|---------------------------------------| -| tx.ssi.endpoint.audience | X | | Endpoint URL for audience check (DSP) | diff --git a/edc-extensions/ssi/ssi-identity-core/build.gradle.kts b/edc-extensions/ssi/ssi-identity-core/build.gradle.kts deleted file mode 100644 index 3b9a4bda9..000000000 --- a/edc-extensions/ssi/ssi-identity-core/build.gradle.kts +++ /dev/null @@ -1,33 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -plugins { - `java-library` - `maven-publish` -} - -dependencies { - implementation(project(":spi:ssi-spi")) - implementation(libs.edc.spi.core) - implementation(libs.edc.spi.jwt) - implementation(libs.edc.spi.token) - implementation(libs.edc.token.core) - implementation(libs.nimbus.jwt) - testImplementation(testFixtures(libs.edc.junit)) -} diff --git a/edc-extensions/ssi/ssi-identity-core/src/main/java/org/eclipse/tractusx/edc/iam/ssi/identity/SsiIdentityService.java b/edc-extensions/ssi/ssi-identity-core/src/main/java/org/eclipse/tractusx/edc/iam/ssi/identity/SsiIdentityService.java deleted file mode 100644 index fd3c5fde9..000000000 --- a/edc-extensions/ssi/ssi-identity-core/src/main/java/org/eclipse/tractusx/edc/iam/ssi/identity/SsiIdentityService.java +++ /dev/null @@ -1,58 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.iam.ssi.identity; - -import org.eclipse.edc.spi.iam.ClaimToken; -import org.eclipse.edc.spi.iam.IdentityService; -import org.eclipse.edc.spi.iam.TokenParameters; -import org.eclipse.edc.spi.iam.TokenRepresentation; -import org.eclipse.edc.spi.iam.VerificationContext; -import org.eclipse.edc.spi.result.Result; -import org.eclipse.edc.token.spi.TokenValidationRulesRegistry; -import org.eclipse.tractusx.edc.iam.ssi.spi.SsiCredentialClient; -import org.eclipse.tractusx.edc.iam.ssi.spi.SsiTokenValidationService; - -import static org.eclipse.tractusx.edc.iam.ssi.spi.SsiConstants.SSI_TOKEN_CONTEXT; - -public class SsiIdentityService implements IdentityService { - - private final SsiTokenValidationService tokenValidationService; - - private final TokenValidationRulesRegistry rulesRegistry; - - private final SsiCredentialClient client; - - public SsiIdentityService(SsiTokenValidationService tokenValidationService, TokenValidationRulesRegistry rulesRegistry, - SsiCredentialClient client) { - this.tokenValidationService = tokenValidationService; - this.rulesRegistry = rulesRegistry; - this.client = client; - } - - @Override - public Result obtainClientCredentials(TokenParameters parameters) { - return client.obtainClientCredentials(parameters); - } - - @Override - public Result verifyJwtToken(TokenRepresentation tokenRepresentation, VerificationContext verificationContext) { - return tokenValidationService.validate(tokenRepresentation, rulesRegistry.getRules(SSI_TOKEN_CONTEXT)); - } -} diff --git a/edc-extensions/ssi/ssi-identity-core/src/main/java/org/eclipse/tractusx/edc/iam/ssi/identity/SsiIdentityServiceExtension.java b/edc-extensions/ssi/ssi-identity-core/src/main/java/org/eclipse/tractusx/edc/iam/ssi/identity/SsiIdentityServiceExtension.java deleted file mode 100644 index 762e0ac33..000000000 --- a/edc-extensions/ssi/ssi-identity-core/src/main/java/org/eclipse/tractusx/edc/iam/ssi/identity/SsiIdentityServiceExtension.java +++ /dev/null @@ -1,75 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.iam.ssi.identity; - -import org.eclipse.edc.runtime.metamodel.annotation.Extension; -import org.eclipse.edc.runtime.metamodel.annotation.Inject; -import org.eclipse.edc.runtime.metamodel.annotation.Provides; -import org.eclipse.edc.runtime.metamodel.annotation.Setting; -import org.eclipse.edc.spi.iam.AudienceResolver; -import org.eclipse.edc.spi.iam.IdentityService; -import org.eclipse.edc.spi.system.ServiceExtension; -import org.eclipse.edc.spi.system.ServiceExtensionContext; -import org.eclipse.edc.spi.types.domain.message.RemoteMessage; -import org.eclipse.edc.token.spi.TokenValidationRulesRegistry; -import org.eclipse.tractusx.edc.iam.ssi.identity.rule.SsiAudienceValidationRule; -import org.eclipse.tractusx.edc.iam.ssi.spi.SsiCredentialClient; -import org.eclipse.tractusx.edc.iam.ssi.spi.SsiTokenValidationService; - -import static org.eclipse.tractusx.edc.iam.ssi.spi.SsiConstants.SSI_TOKEN_CONTEXT; - -@Provides({ IdentityService.class, SsiTokenValidationService.class, AudienceResolver.class }) -@Extension(SsiIdentityServiceExtension.EXTENSION_NAME) -public class SsiIdentityServiceExtension implements ServiceExtension { - - public static final String EXTENSION_NAME = "SSI Identity Service"; - - @Setting(value = "SSI Endpoint audience of this connector") - public static final String ENDPOINT_AUDIENCE = "tx.ssi.endpoint.audience"; - - @Inject - private SsiCredentialClient credentialClient; - - @Inject - private TokenValidationRulesRegistry rulesRegistry; - - @Override - public String name() { - return EXTENSION_NAME; - } - - @Override - public void initialize(ServiceExtensionContext context) { - - var tokenValidationService = new SsiTokenValidationServiceImpl(credentialClient); - configureRules(context, rulesRegistry); - - var identityService = new SsiIdentityService(tokenValidationService, rulesRegistry, credentialClient); - - context.registerService(IdentityService.class, identityService); - context.registerService(SsiTokenValidationService.class, tokenValidationService); - context.registerService(AudienceResolver.class, RemoteMessage::getCounterPartyAddress); - } - - private void configureRules(ServiceExtensionContext context, TokenValidationRulesRegistry registry) { - var endpointAudience = context.getConfig().getString(ENDPOINT_AUDIENCE); - registry.addRule(SSI_TOKEN_CONTEXT, new SsiAudienceValidationRule(endpointAudience)); - } -} diff --git a/edc-extensions/ssi/ssi-identity-core/src/main/java/org/eclipse/tractusx/edc/iam/ssi/identity/SsiTokenValidationServiceImpl.java b/edc-extensions/ssi/ssi-identity-core/src/main/java/org/eclipse/tractusx/edc/iam/ssi/identity/SsiTokenValidationServiceImpl.java deleted file mode 100644 index 1c1304dd2..000000000 --- a/edc-extensions/ssi/ssi-identity-core/src/main/java/org/eclipse/tractusx/edc/iam/ssi/identity/SsiTokenValidationServiceImpl.java +++ /dev/null @@ -1,62 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.iam.ssi.identity; - -import org.eclipse.edc.spi.iam.ClaimToken; -import org.eclipse.edc.spi.iam.TokenRepresentation; -import org.eclipse.edc.spi.result.Result; -import org.eclipse.edc.token.spi.TokenValidationRule; -import org.eclipse.tractusx.edc.iam.ssi.spi.SsiCredentialClient; -import org.eclipse.tractusx.edc.iam.ssi.spi.SsiTokenValidationService; -import org.jetbrains.annotations.Nullable; - -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -public class SsiTokenValidationServiceImpl implements SsiTokenValidationService { - - private final SsiCredentialClient credentialClient; - - public SsiTokenValidationServiceImpl(SsiCredentialClient credentialClient) { - this.credentialClient = credentialClient; - } - - @Override - public Result validate(TokenRepresentation tokenRepresentation, List rules) { - return credentialClient.validate(tokenRepresentation) - .compose(claimToken -> checkRules(claimToken, tokenRepresentation.getAdditional(), rules)); - } - - private Result checkRules(ClaimToken claimToken, @Nullable Map additional, List rules) { - var errors = rules.stream() - .map(r -> r.checkRule(claimToken, additional)) - .filter(Result::failed) - .map(Result::getFailureMessages) - .flatMap(Collection::stream) - .collect(Collectors.toList()); - - if (!errors.isEmpty()) { - return Result.failure(errors); - } - return Result.success(claimToken); - } -} diff --git a/edc-extensions/ssi/ssi-identity-core/src/main/java/org/eclipse/tractusx/edc/iam/ssi/identity/rule/SsiAudienceValidationRule.java b/edc-extensions/ssi/ssi-identity-core/src/main/java/org/eclipse/tractusx/edc/iam/ssi/identity/rule/SsiAudienceValidationRule.java deleted file mode 100644 index b9f15e5e1..000000000 --- a/edc-extensions/ssi/ssi-identity-core/src/main/java/org/eclipse/tractusx/edc/iam/ssi/identity/rule/SsiAudienceValidationRule.java +++ /dev/null @@ -1,50 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.iam.ssi.identity.rule; - -import org.eclipse.edc.spi.iam.ClaimToken; -import org.eclipse.edc.spi.result.Result; -import org.eclipse.edc.token.spi.TokenValidationRule; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.Map; - -import static org.eclipse.edc.jwt.spi.JwtRegisteredClaimNames.AUDIENCE; - -public class SsiAudienceValidationRule implements TokenValidationRule { - - private final String endpointAudience; - - public SsiAudienceValidationRule(String endpointAudience) { - this.endpointAudience = endpointAudience; - } - - @Override - public Result checkRule(@NotNull ClaimToken toVerify, @Nullable Map additional) { - var audiences = toVerify.getListClaim(AUDIENCE); - if (audiences.isEmpty()) { - return Result.failure("Required audience (aud) claim is missing in token"); - } else if (!audiences.contains(endpointAudience)) { - return Result.failure("Token audience (aud) claim did not contain audience: " + endpointAudience); - } - return Result.success(); - } -} diff --git a/edc-extensions/ssi/ssi-identity-core/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension b/edc-extensions/ssi/ssi-identity-core/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension deleted file mode 100644 index 858acb7ef..000000000 --- a/edc-extensions/ssi/ssi-identity-core/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension +++ /dev/null @@ -1,20 +0,0 @@ -################################################################################# -# Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) -# -# See the NOTICE file(s) distributed with this work for additional -# information regarding copyright ownership. -# -# This program and the accompanying materials are made available under the -# terms of the Apache License, Version 2.0 which is available at -# https://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. -# -# SPDX-License-Identifier: Apache-2.0 -################################################################################# - -org.eclipse.tractusx.edc.iam.ssi.identity.SsiIdentityServiceExtension diff --git a/edc-extensions/ssi/ssi-identity-core/src/test/java/org/eclipse/tractusx/edc/iam/ssi/identity/SsiIdentityServiceExtensionTest.java b/edc-extensions/ssi/ssi-identity-core/src/test/java/org/eclipse/tractusx/edc/iam/ssi/identity/SsiIdentityServiceExtensionTest.java deleted file mode 100644 index 6b9a73a1a..000000000 --- a/edc-extensions/ssi/ssi-identity-core/src/test/java/org/eclipse/tractusx/edc/iam/ssi/identity/SsiIdentityServiceExtensionTest.java +++ /dev/null @@ -1,60 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.iam.ssi.identity; - -import org.eclipse.edc.junit.extensions.DependencyInjectionExtension; -import org.eclipse.edc.spi.iam.IdentityService; -import org.eclipse.edc.spi.system.ServiceExtensionContext; -import org.eclipse.edc.spi.system.configuration.Config; -import org.eclipse.tractusx.edc.iam.ssi.spi.SsiCredentialClient; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.eclipse.tractusx.edc.iam.ssi.identity.SsiIdentityServiceExtension.ENDPOINT_AUDIENCE; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -@ExtendWith(DependencyInjectionExtension.class) -public class SsiIdentityServiceExtensionTest { - - SsiIdentityServiceExtension extension; - - @BeforeEach - void setup(ServiceExtensionContext context) { - context.registerService(SsiCredentialClient.class, mock(SsiCredentialClient.class)); - } - - @Test - void initialize(ServiceExtensionContext context, SsiIdentityServiceExtension extension) { - var cfg = mock(Config.class); - when(context.getConfig()).thenReturn(cfg); - when(cfg.getString(ENDPOINT_AUDIENCE)).thenReturn("test"); - - extension.initialize(context); - - assertThat(context.getService(IdentityService.class)).isNotNull().isInstanceOf(SsiIdentityService.class); - - verify(cfg).getString(ENDPOINT_AUDIENCE); - - } -} diff --git a/edc-extensions/ssi/ssi-identity-core/src/test/java/org/eclipse/tractusx/edc/iam/ssi/identity/SsiIdentityServiceTest.java b/edc-extensions/ssi/ssi-identity-core/src/test/java/org/eclipse/tractusx/edc/iam/ssi/identity/SsiIdentityServiceTest.java deleted file mode 100644 index 059c77283..000000000 --- a/edc-extensions/ssi/ssi-identity-core/src/test/java/org/eclipse/tractusx/edc/iam/ssi/identity/SsiIdentityServiceTest.java +++ /dev/null @@ -1,99 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.iam.ssi.identity; - -import org.eclipse.edc.spi.iam.ClaimToken; -import org.eclipse.edc.spi.iam.TokenParameters; -import org.eclipse.edc.spi.iam.TokenRepresentation; -import org.eclipse.edc.spi.result.Result; -import org.eclipse.edc.token.spi.TokenValidationRulesRegistry; -import org.eclipse.tractusx.edc.iam.ssi.spi.SsiCredentialClient; -import org.eclipse.tractusx.edc.iam.ssi.spi.SsiTokenValidationService; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import java.util.List; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.eclipse.edc.jwt.spi.JwtRegisteredClaimNames.AUDIENCE; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -public class SsiIdentityServiceTest { - - SsiCredentialClient credentialClient = mock(SsiCredentialClient.class); - SsiTokenValidationService tokenValidationService = mock(SsiTokenValidationService.class); - TokenValidationRulesRegistry rulesRegistry = mock(TokenValidationRulesRegistry.class); - - SsiIdentityService identityService; - - @BeforeEach - void setup() { - identityService = new SsiIdentityService(tokenValidationService, rulesRegistry, credentialClient); - } - - @Test - void verifyJwtToken_success() { - var token = TokenRepresentation.Builder.newInstance().token("test").build(); - var claim = ClaimToken.Builder.newInstance().build(); - - when(tokenValidationService.validate(eq(token), eq(List.of()))).thenReturn(Result.success(claim)); - - var result = identityService.verifyJwtToken(token, mock()); - - assertThat(result).isNotNull().extracting(Result::getContent).isEqualTo(claim); - } - - @Test - void verifyJwtToken_failed() { - var token = TokenRepresentation.Builder.newInstance().token("test").build(); - - when(tokenValidationService.validate(eq(token), eq(List.of()))).thenReturn(Result.failure("fail")); - - var result = identityService.verifyJwtToken(token, mock()); - - assertThat(result).isNotNull().matches(Result::failed); - } - - - @Test - void obtainClientCredentials_success() { - var tokenParameters = TokenParameters.Builder.newInstance().claims(AUDIENCE, "audience").build(); - var tokenRepresentation = TokenRepresentation.Builder.newInstance().token("test").build(); - - when(credentialClient.obtainClientCredentials(tokenParameters)).thenReturn(Result.success(tokenRepresentation)); - - var result = identityService.obtainClientCredentials(tokenParameters); - - assertThat(result).isNotNull().extracting(Result::getContent).isEqualTo(tokenRepresentation); - } - - @Test - void obtainClientCredentials_fail() { - var tokenParameters = TokenParameters.Builder.newInstance().claims(AUDIENCE, "audience").build(); - - when(credentialClient.obtainClientCredentials(tokenParameters)).thenReturn(Result.failure("fail")); - - var result = identityService.obtainClientCredentials(tokenParameters); - - assertThat(result).isNotNull().matches(Result::failed); - } -} diff --git a/edc-extensions/ssi/ssi-identity-core/src/test/java/org/eclipse/tractusx/edc/iam/ssi/identity/SsiTokenValidationServiceImplTest.java b/edc-extensions/ssi/ssi-identity-core/src/test/java/org/eclipse/tractusx/edc/iam/ssi/identity/SsiTokenValidationServiceImplTest.java deleted file mode 100644 index ba42dff2c..000000000 --- a/edc-extensions/ssi/ssi-identity-core/src/test/java/org/eclipse/tractusx/edc/iam/ssi/identity/SsiTokenValidationServiceImplTest.java +++ /dev/null @@ -1,102 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.iam.ssi.identity; - -import org.eclipse.edc.spi.iam.ClaimToken; -import org.eclipse.edc.spi.iam.TokenRepresentation; -import org.eclipse.edc.spi.result.Result; -import org.eclipse.edc.token.spi.TokenValidationRule; -import org.eclipse.tractusx.edc.iam.ssi.spi.SsiCredentialClient; -import org.eclipse.tractusx.edc.iam.ssi.spi.SsiTokenValidationService; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import java.util.List; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoInteractions; -import static org.mockito.Mockito.when; - -public class SsiTokenValidationServiceImplTest { - - SsiCredentialClient credentialClient = mock(SsiCredentialClient.class); - - SsiTokenValidationService validationService; - - @BeforeEach - void setup() { - validationService = new SsiTokenValidationServiceImpl(credentialClient); - } - - @Test - void validate_success() { - var token = TokenRepresentation.Builder.newInstance().token("test").build(); - var rule = mock(TokenValidationRule.class); - var claim = ClaimToken.Builder.newInstance().build(); - - when(credentialClient.validate(token)).thenReturn(Result.success(claim)); - when(rule.checkRule(any(), any())).thenReturn(Result.success()); - - var result = validationService.validate(token, List.of(rule)); - - assertThat(result).isNotNull().extracting(Result::getContent).isEqualTo(claim); - - verify(credentialClient).validate(token); - verify(rule).checkRule(eq(claim), any()); - } - - @Test - void validate_fail_whenClientFails() { - var token = TokenRepresentation.Builder.newInstance().token("test").build(); - var rule = mock(TokenValidationRule.class); - - when(credentialClient.validate(token)).thenReturn(Result.failure("failure")); - when(rule.checkRule(any(), any())).thenReturn(Result.success()); - - var result = validationService.validate(token, List.of(rule)); - - assertThat(result).isNotNull().matches(Result::failed); - - verify(credentialClient).validate(token); - verifyNoInteractions(rule); - } - - @Test - void validate_fail_whenRuleFails() { - var token = TokenRepresentation.Builder.newInstance().token("test").build(); - var rule = mock(TokenValidationRule.class); - var claim = ClaimToken.Builder.newInstance().build(); - - - when(credentialClient.validate(token)).thenReturn(Result.success(claim)); - when(rule.checkRule(any(), any())).thenReturn(Result.failure("failure")); - - var result = validationService.validate(token, List.of(rule)); - - assertThat(result).isNotNull().matches(Result::failed); - - verify(credentialClient).validate(token); - verify(rule).checkRule(eq(claim), any()); - } -} diff --git a/edc-extensions/ssi/ssi-identity-core/src/test/java/org/eclipse/tractusx/edc/iam/ssi/identity/rule/SsiAudienceValidationRuleTest.java b/edc-extensions/ssi/ssi-identity-core/src/test/java/org/eclipse/tractusx/edc/iam/ssi/identity/rule/SsiAudienceValidationRuleTest.java deleted file mode 100644 index 8eea66edf..000000000 --- a/edc-extensions/ssi/ssi-identity-core/src/test/java/org/eclipse/tractusx/edc/iam/ssi/identity/rule/SsiAudienceValidationRuleTest.java +++ /dev/null @@ -1,72 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.iam.ssi.identity.rule; - -import org.eclipse.edc.spi.iam.ClaimToken; -import org.eclipse.edc.token.spi.TokenValidationRule; -import org.junit.jupiter.api.Test; - -import java.util.List; - -import static java.util.Collections.emptyMap; -import static org.assertj.core.api.Assertions.assertThat; -import static org.eclipse.edc.jwt.spi.JwtRegisteredClaimNames.AUDIENCE; - -public class SsiAudienceValidationRuleTest { - - private final String endpointAudience = "test-audience"; - private final TokenValidationRule rule = new SsiAudienceValidationRule(endpointAudience); - - @Test - void validAudience() { - var token = ClaimToken.Builder.newInstance() - .claim(AUDIENCE, List.of(endpointAudience)) - .build(); - - var result = rule.checkRule(token, emptyMap()); - - assertThat(result.succeeded()).isTrue(); - } - - @Test - void validationKoBecauseAudienceNotRespected() { - var token = ClaimToken.Builder.newInstance() - .claim(AUDIENCE, List.of("fake-audience")) - .build(); - - var result = rule.checkRule(token, emptyMap()); - - assertThat(result.succeeded()).isFalse(); - assertThat(result.getFailureMessages()).hasSize(1) - .contains("Token audience (aud) claim did not contain audience: test-audience"); - } - - @Test - void validationKoBecauseAudienceNotProvided() { - var token = ClaimToken.Builder.newInstance() - .build(); - - var result = rule.checkRule(token, emptyMap()); - - assertThat(result.succeeded()).isFalse(); - assertThat(result.getFailureMessages()).hasSize(1) - .contains("Required audience (aud) claim is missing in token"); - } -} diff --git a/edc-extensions/ssi/ssi-identity-extractor/build.gradle.kts b/edc-extensions/ssi/ssi-identity-extractor/build.gradle.kts deleted file mode 100644 index f5049009d..000000000 --- a/edc-extensions/ssi/ssi-identity-extractor/build.gradle.kts +++ /dev/null @@ -1,31 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -plugins { - `java-library` - `maven-publish` -} - -dependencies { - implementation(project(":spi:ssi-spi")) - implementation(libs.edc.spi.core) - implementation(libs.jakartaJson) - testImplementation(testFixtures(libs.edc.junit)) - testImplementation(testFixtures(project(":spi:ssi-spi"))) -} diff --git a/edc-extensions/ssi/ssi-identity-extractor/src/main/java/org/eclipse/tractusx/edc/iam/ssi/identity/extractor/CredentialIdentityExtractor.java b/edc-extensions/ssi/ssi-identity-extractor/src/main/java/org/eclipse/tractusx/edc/iam/ssi/identity/extractor/CredentialIdentityExtractor.java deleted file mode 100644 index 26cc9ae60..000000000 --- a/edc-extensions/ssi/ssi-identity-extractor/src/main/java/org/eclipse/tractusx/edc/iam/ssi/identity/extractor/CredentialIdentityExtractor.java +++ /dev/null @@ -1,87 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.iam.ssi.identity.extractor; - -import jakarta.json.JsonObject; -import org.eclipse.edc.spi.EdcException; -import org.eclipse.edc.spi.agent.ParticipantAgentServiceExtension; -import org.eclipse.edc.spi.iam.ClaimToken; -import org.eclipse.edc.spi.result.Result; -import org.eclipse.tractusx.edc.iam.ssi.spi.jsonld.JsonLdFieldExtractor; -import org.jetbrains.annotations.NotNull; - -import java.util.Map; -import java.util.Optional; -import java.util.stream.Stream; - -import static org.eclipse.edc.spi.agent.ParticipantAgent.PARTICIPANT_IDENTITY; -import static org.eclipse.tractusx.edc.iam.ssi.spi.jsonld.CredentialsNamespaces.CREDENTIAL_SUBJECT; -import static org.eclipse.tractusx.edc.iam.ssi.spi.jsonld.CredentialsNamespaces.HOLDER_IDENTIFIER; -import static org.eclipse.tractusx.edc.iam.ssi.spi.jsonld.CredentialsNamespaces.SUMMARY_CREDENTIAL_TYPE; -import static org.eclipse.tractusx.edc.iam.ssi.spi.jsonld.CredentialsNamespaces.VP_PROPERTY; -import static org.eclipse.tractusx.edc.iam.ssi.spi.jsonld.JsonLdTypeFunctions.extractObjectsOfType; -import static org.eclipse.tractusx.edc.iam.ssi.spi.jsonld.JsonLdValueFunctions.extractStringValue; - -public class CredentialIdentityExtractor implements ParticipantAgentServiceExtension { - - private static final String IDENTITY_EXTRACTOR_PREFIX = "Identity extractor:"; - - private final JsonLdFieldExtractor holderIdentifierExtractor = JsonLdFieldExtractor.Builder.newInstance() - .field(HOLDER_IDENTIFIER) - .fieldAlias("holderIdentifier") - .errorPrefix(IDENTITY_EXTRACTOR_PREFIX) - .build(); - private final JsonLdFieldExtractor credentialSubjectExtractor = JsonLdFieldExtractor.Builder.newInstance() - .field(CREDENTIAL_SUBJECT) - .fieldAlias("credentialSubject") - .errorPrefix(IDENTITY_EXTRACTOR_PREFIX) - .build(); - - @Override - public @NotNull Map attributesFor(ClaimToken token) { - var vp = (JsonObject) token.getClaim(VP_PROPERTY); - - var extractionResult = Optional.ofNullable(vp) - .map(v -> extractObjectsOfType(SUMMARY_CREDENTIAL_TYPE, v)) - .orElse(Stream.empty()) - .map(this::extractHolderIdentifier) - .findFirst() - .orElseThrow(() -> new EdcException("Failed to extract identity from the membership credential")); - - var bpn = extractionResult.orElseThrow((failure) -> new EdcException(failure.getFailureDetail())); - return Map.of(PARTICIPANT_IDENTITY, bpn); - - } - - private Result extractHolderIdentifier(JsonObject credential) { - return this.credentialSubjectExtractor.extract(credential) - .compose(holderIdentifierExtractor::extract) - .compose(this::extractHolderIdentifierValue); - } - - private Result extractHolderIdentifierValue(JsonObject identifier) { - var bpn = extractStringValue(identifier); - if (bpn == null) { - return Result.failure("Failed to find the holder identifier"); - } else { - return Result.success(bpn); - } - } -} diff --git a/edc-extensions/ssi/ssi-identity-extractor/src/main/java/org/eclipse/tractusx/edc/iam/ssi/identity/extractor/SsiIdentityExtractorExtension.java b/edc-extensions/ssi/ssi-identity-extractor/src/main/java/org/eclipse/tractusx/edc/iam/ssi/identity/extractor/SsiIdentityExtractorExtension.java deleted file mode 100644 index a4e309a81..000000000 --- a/edc-extensions/ssi/ssi-identity-extractor/src/main/java/org/eclipse/tractusx/edc/iam/ssi/identity/extractor/SsiIdentityExtractorExtension.java +++ /dev/null @@ -1,45 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.iam.ssi.identity.extractor; - -import org.eclipse.edc.runtime.metamodel.annotation.Extension; -import org.eclipse.edc.runtime.metamodel.annotation.Inject; -import org.eclipse.edc.spi.agent.ParticipantAgentService; -import org.eclipse.edc.spi.system.ServiceExtension; -import org.eclipse.edc.spi.system.ServiceExtensionContext; - -@Extension(SsiIdentityExtractorExtension.EXTENSION_NAME) -public class SsiIdentityExtractorExtension implements ServiceExtension { - - public static final String EXTENSION_NAME = "SSI Identity extractor"; - - @Inject - private ParticipantAgentService participantAgentService; - - @Override - public String name() { - return EXTENSION_NAME; - } - - @Override - public void initialize(ServiceExtensionContext context) { - participantAgentService.register(new CredentialIdentityExtractor()); - } -} diff --git a/edc-extensions/ssi/ssi-identity-extractor/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension b/edc-extensions/ssi/ssi-identity-extractor/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension deleted file mode 100644 index da0c5e345..000000000 --- a/edc-extensions/ssi/ssi-identity-extractor/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension +++ /dev/null @@ -1,20 +0,0 @@ -################################################################################# -# Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) -# -# See the NOTICE file(s) distributed with this work for additional -# information regarding copyright ownership. -# -# This program and the accompanying materials are made available under the -# terms of the Apache License, Version 2.0 which is available at -# https://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. -# -# SPDX-License-Identifier: Apache-2.0 -################################################################################# - -org.eclipse.tractusx.edc.iam.ssi.identity.extractor.SsiIdentityExtractorExtension diff --git a/edc-extensions/ssi/ssi-identity-extractor/src/test/java/org/eclipse/tractusx/edc/iam/ssi/identity/extractor/CredentialIdentityExtractorTest.java b/edc-extensions/ssi/ssi-identity-extractor/src/test/java/org/eclipse/tractusx/edc/iam/ssi/identity/extractor/CredentialIdentityExtractorTest.java deleted file mode 100644 index 4caee164d..000000000 --- a/edc-extensions/ssi/ssi-identity-extractor/src/test/java/org/eclipse/tractusx/edc/iam/ssi/identity/extractor/CredentialIdentityExtractorTest.java +++ /dev/null @@ -1,87 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.iam.ssi.identity.extractor; - -import com.fasterxml.jackson.core.JsonProcessingException; -import jakarta.json.JsonObject; -import org.eclipse.edc.spi.EdcException; -import org.eclipse.edc.spi.iam.ClaimToken; -import org.eclipse.tractusx.edc.iam.ssi.spi.jsonld.SummaryContext; -import org.junit.jupiter.api.Test; - -import java.util.Map; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.eclipse.edc.spi.agent.ParticipantAgent.PARTICIPANT_IDENTITY; -import static org.eclipse.tractusx.edc.iam.ssi.spi.jsonld.CredentialsNamespaces.CX_SUMMARY_NS_V1; -import static org.eclipse.tractusx.edc.iam.ssi.spi.jsonld.CredentialsNamespaces.VP_PROPERTY; -import static org.eclipse.tractusx.edc.iam.ssi.spi.jsonld.JsonLdTextFixtures.createObjectMapper; -import static org.eclipse.tractusx.edc.iam.ssi.spi.jsonld.JsonLdTextFixtures.expand; -import static org.eclipse.tractusx.edc.iam.ssi.spi.jsonld.SummaryCredential.SIMPLE_VP; -import static org.eclipse.tractusx.edc.iam.ssi.spi.jsonld.SummaryCredential.SUMMARY_VP; -import static org.eclipse.tractusx.edc.iam.ssi.spi.jsonld.SummaryCredential.SUMMARY_VP_NO_HOLDER; -import static org.eclipse.tractusx.edc.iam.ssi.spi.jsonld.SummaryCredential.SUMMARY_VP_NO_SUBJECT; - -public class CredentialIdentityExtractorTest { - - static final Map CONTEXT_CACHE = Map.of(CX_SUMMARY_NS_V1, SummaryContext.SUMMARY_CONTEXT); - - CredentialIdentityExtractor extractor = new CredentialIdentityExtractor(); - - @Test - void attributeFor() throws JsonProcessingException { - var vp = expand(createObjectMapper().readValue(SUMMARY_VP, JsonObject.class), CONTEXT_CACHE); - var attributes = extractor.attributesFor(ClaimToken.Builder.newInstance().claim(VP_PROPERTY, vp).build()); - - assertThat(attributes).contains(Map.entry(PARTICIPANT_IDENTITY, "BPN of holder")); - } - - @Test - void attributeFor_exception_whenVpNotPresent() { - assertThatThrownBy(() -> extractor.attributesFor(ClaimToken.Builder.newInstance().build())) - .isInstanceOf(EdcException.class) - .hasMessage("Failed to extract identity from the membership credential"); - } - - @Test - void attributeFor_exception_whenCredentialTypeNotMatch() throws JsonProcessingException { - var vp = expand(createObjectMapper().readValue(SIMPLE_VP, JsonObject.class), CONTEXT_CACHE); - assertThatThrownBy(() -> extractor.attributesFor(ClaimToken.Builder.newInstance().claim(VP_PROPERTY, vp).build())) - .isInstanceOf(EdcException.class) - .hasMessage("Failed to extract identity from the membership credential"); - } - - @Test - void attributeFor_exception_whenHolderIdentifierNotFound() throws JsonProcessingException { - var vp = expand(createObjectMapper().readValue(SUMMARY_VP_NO_HOLDER, JsonObject.class), CONTEXT_CACHE); - assertThatThrownBy(() -> extractor.attributesFor(ClaimToken.Builder.newInstance().claim(VP_PROPERTY, vp).build())) - .isInstanceOf(EdcException.class) - .hasMessage("Identity extractor: no holderIdentifier found"); - } - - @Test - void attributeFor_exception_whenCredentialSubjectNotFound() throws JsonProcessingException { - var vp = expand(createObjectMapper().readValue(SUMMARY_VP_NO_SUBJECT, JsonObject.class), CONTEXT_CACHE); - assertThatThrownBy(() -> extractor.attributesFor(ClaimToken.Builder.newInstance().claim(VP_PROPERTY, vp).build())) - .isInstanceOf(EdcException.class) - .hasMessage("Identity extractor: no credentialSubject found"); - } -} diff --git a/edc-extensions/ssi/ssi-identity-extractor/src/test/java/org/eclipse/tractusx/edc/iam/ssi/identity/extractor/SsiIdentityExtractorExtensionTest.java b/edc-extensions/ssi/ssi-identity-extractor/src/test/java/org/eclipse/tractusx/edc/iam/ssi/identity/extractor/SsiIdentityExtractorExtensionTest.java deleted file mode 100644 index de3799312..000000000 --- a/edc-extensions/ssi/ssi-identity-extractor/src/test/java/org/eclipse/tractusx/edc/iam/ssi/identity/extractor/SsiIdentityExtractorExtensionTest.java +++ /dev/null @@ -1,48 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.iam.ssi.identity.extractor; - -import org.eclipse.edc.junit.extensions.DependencyInjectionExtension; -import org.eclipse.edc.spi.agent.ParticipantAgentService; -import org.eclipse.edc.spi.system.ServiceExtensionContext; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; - -import static org.mockito.ArgumentMatchers.isA; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; - -@ExtendWith(DependencyInjectionExtension.class) -public class SsiIdentityExtractorExtensionTest { - - ParticipantAgentService participantAgentService = mock(ParticipantAgentService.class); - - @BeforeEach - void setup(ServiceExtensionContext context) { - context.registerService(ParticipantAgentService.class, participantAgentService); - } - - @Test - void initialize(ServiceExtensionContext context, SsiIdentityExtractorExtension extension) { - extension.initialize(context); - verify(participantAgentService).register(isA(CredentialIdentityExtractor.class)); - } -} diff --git a/edc-extensions/ssi/ssi-miw-credential-client/README.md b/edc-extensions/ssi/ssi-miw-credential-client/README.md deleted file mode 100644 index 883165147..000000000 --- a/edc-extensions/ssi/ssi-miw-credential-client/README.md +++ /dev/null @@ -1,34 +0,0 @@ -# MIW Client Credential Module - -This module contains an implementation of the `SsiCredentialClient` interface for SSI. -It basically narrows down to two operations: - -- obtaining a token for protocol communication -- validating the token - -For validating the token accordingly to the first milestone [here](https://github.com/eclipse-tractusx/ssi-docu/tree/main/docs/architecture/cx-3-2), the implemetation -just call the MIW for checking that the token and the VP claim inside are correct. Then extract the `JWT` claims into the `ClaimToken` for further checks. - -For obtaining a `JWT` token also it reaches the MIW, that will create a token with the `VP` claim inside. - -This module also contains two additional validation rules of VP/VC on the provider side. - -- `SsiCredentialIssuerValidationRule` checks if the issuer of the Verifiable Credential matches `tx.ssi.miw.authority.issuer` -- `SsiCredentialSubjectIdValidationRule` checks if the issuer of the JWT/VP matches the credential subject id in the Verifiable Credential - -## Configuration - -| Key | Required | Example | Description | -|----------------------------------|----------|----------------|-----------------------------------| -| tx.ssi.miw.url | X | | MIW URL | -| tx.ssi.miw.authority.id | X | | BPN number of the authority | -| tx.ssi.miw.authority.issuer | | | The id of the issuer (DID) | -| tx.ssi.oauth.token.url | X | | Token URL (Keycloak) | -| tx.ssi.oauth.client.id | X | | Client id | -| tx.ssi.oauth.client.secret.alias | X | | Vault alias for the client secret | - -By default, the `tx.ssi.miw.authority.issuer` is composed with `did:web::` - -Another mandatory settings is `tx.ssi.endpoint.audience` which is described [here](../ssi-identity-core/README.md) - -> Note: the `edc.participant.id` should match the BPN number contained in the OAuth2/Keycloak token and the one assigned by the portal to the user's organization. diff --git a/edc-extensions/ssi/ssi-miw-credential-client/build.gradle.kts b/edc-extensions/ssi/ssi-miw-credential-client/build.gradle.kts deleted file mode 100644 index 9f03fb974..000000000 --- a/edc-extensions/ssi/ssi-miw-credential-client/build.gradle.kts +++ /dev/null @@ -1,40 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -plugins { - `java-library` - `maven-publish` -} - -dependencies { - implementation(project(":spi:ssi-spi")) - implementation(project(":core:core-utils")) - implementation(libs.edc.spi.core) - implementation(libs.edc.spi.http) - implementation(libs.edc.spi.jsonld) - implementation(libs.edc.auth.oauth2.client) - implementation(libs.edc.spi.jwt) - implementation(libs.edc.spi.token) - implementation(libs.jakartaJson) - implementation(libs.nimbus.jwt) - - testImplementation(testFixtures(project(":spi:ssi-spi"))) - testImplementation(testFixtures(libs.edc.junit)) - testImplementation(testFixtures(libs.edc.lib.http)) -} diff --git a/edc-extensions/ssi/ssi-miw-credential-client/src/main/java/org/eclipse/tractusx/edc/iam/ssi/miw/SsiMiwApiClientExtension.java b/edc-extensions/ssi/ssi-miw-credential-client/src/main/java/org/eclipse/tractusx/edc/iam/ssi/miw/SsiMiwApiClientExtension.java deleted file mode 100644 index c78354ff0..000000000 --- a/edc-extensions/ssi/ssi-miw-credential-client/src/main/java/org/eclipse/tractusx/edc/iam/ssi/miw/SsiMiwApiClientExtension.java +++ /dev/null @@ -1,66 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.iam.ssi.miw; - -import org.eclipse.edc.runtime.metamodel.annotation.Extension; -import org.eclipse.edc.runtime.metamodel.annotation.Inject; -import org.eclipse.edc.runtime.metamodel.annotation.Provider; -import org.eclipse.edc.spi.http.EdcHttpClient; -import org.eclipse.edc.spi.monitor.Monitor; -import org.eclipse.edc.spi.system.ServiceExtension; -import org.eclipse.edc.spi.system.ServiceExtensionContext; -import org.eclipse.edc.spi.types.TypeManager; -import org.eclipse.tractusx.edc.iam.ssi.miw.api.MiwApiClient; -import org.eclipse.tractusx.edc.iam.ssi.miw.api.MiwApiClientImpl; -import org.eclipse.tractusx.edc.iam.ssi.miw.config.SsiMiwConfiguration; -import org.eclipse.tractusx.edc.iam.ssi.miw.oauth2.MiwOauth2Client; - - -@Extension(SsiMiwApiClientExtension.EXTENSION_NAME) -public class SsiMiwApiClientExtension implements ServiceExtension { - - public static final String EXTENSION_NAME = "SSI MIW Api Client"; - - @Inject - private MiwOauth2Client oauth2Client; - - @Inject - private EdcHttpClient httpClient; - - @Inject - private TypeManager typeManager; - - @Inject - private Monitor monitor; - - @Inject - private SsiMiwConfiguration miwConfiguration; - - @Override - public String name() { - return EXTENSION_NAME; - } - - @Provider - public MiwApiClient apiClient(ServiceExtensionContext context) { - return new MiwApiClientImpl(httpClient, miwConfiguration.getUrl(), oauth2Client, context.getParticipantId(), miwConfiguration.getAuthorityId(), typeManager.getMapper(), monitor); - } - -} diff --git a/edc-extensions/ssi/ssi-miw-credential-client/src/main/java/org/eclipse/tractusx/edc/iam/ssi/miw/SsiMiwConfigurationExtension.java b/edc-extensions/ssi/ssi-miw-credential-client/src/main/java/org/eclipse/tractusx/edc/iam/ssi/miw/SsiMiwConfigurationExtension.java deleted file mode 100644 index 22febc5b1..000000000 --- a/edc-extensions/ssi/ssi-miw-credential-client/src/main/java/org/eclipse/tractusx/edc/iam/ssi/miw/SsiMiwConfigurationExtension.java +++ /dev/null @@ -1,69 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.iam.ssi.miw; - -import org.eclipse.edc.runtime.metamodel.annotation.Extension; -import org.eclipse.edc.runtime.metamodel.annotation.Provider; -import org.eclipse.edc.runtime.metamodel.annotation.Setting; -import org.eclipse.edc.spi.system.ServiceExtension; -import org.eclipse.edc.spi.system.ServiceExtensionContext; -import org.eclipse.tractusx.edc.iam.ssi.miw.config.SsiMiwConfiguration; - -import java.net.URI; -import java.net.URLEncoder; -import java.nio.charset.StandardCharsets; - -import static java.lang.String.format; -import static org.eclipse.tractusx.edc.core.utils.PathUtils.removeTrailingSlash; - - -@Extension(SsiMiwConfigurationExtension.EXTENSION_NAME) -public class SsiMiwConfigurationExtension implements ServiceExtension { - - - @Setting(value = "MIW API base url") - public static final String MIW_BASE_URL = "tx.ssi.miw.url"; - @Setting(value = "MIW Authority ID") - public static final String MIW_AUTHORITY_ID = "tx.ssi.miw.authority.id"; - @Setting(value = "MIW Authority Issuer") - public static final String MIW_AUTHORITY_ISSUER = "tx.ssi.miw.authority.issuer"; - public static final String AUTHORITY_ID_TEMPLATE = "did:web:%s:%s"; - protected static final String EXTENSION_NAME = "SSI Miw configuration extension"; - - @Provider - public SsiMiwConfiguration miwConfiguration(ServiceExtensionContext context) { - var baseUrl = removeTrailingSlash(context.getConfig().getString(MIW_BASE_URL)); - var authorityId = context.getConfig().getString(MIW_AUTHORITY_ID); - var authorityIssuer = authorityIssuer(context, baseUrl, authorityId); - - return SsiMiwConfiguration.Builder.newInstance() - .url(baseUrl) - .authorityId(authorityId) - .authorityIssuer(authorityIssuer) - .build(); - } - - - private String authorityIssuer(ServiceExtensionContext context, String baseUrl, String authorityId) { - var uri = URI.create(baseUrl); - var defaultAuthorityIssuer = format(AUTHORITY_ID_TEMPLATE, URLEncoder.encode(uri.getAuthority(), StandardCharsets.UTF_8), authorityId); - return context.getConfig().getString(MIW_AUTHORITY_ISSUER, defaultAuthorityIssuer); - } -} diff --git a/edc-extensions/ssi/ssi-miw-credential-client/src/main/java/org/eclipse/tractusx/edc/iam/ssi/miw/SsiMiwCredentialClientExtension.java b/edc-extensions/ssi/ssi-miw-credential-client/src/main/java/org/eclipse/tractusx/edc/iam/ssi/miw/SsiMiwCredentialClientExtension.java deleted file mode 100644 index c20317621..000000000 --- a/edc-extensions/ssi/ssi-miw-credential-client/src/main/java/org/eclipse/tractusx/edc/iam/ssi/miw/SsiMiwCredentialClientExtension.java +++ /dev/null @@ -1,58 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.iam.ssi.miw; - -import org.eclipse.edc.jsonld.spi.JsonLd; -import org.eclipse.edc.runtime.metamodel.annotation.Extension; -import org.eclipse.edc.runtime.metamodel.annotation.Inject; -import org.eclipse.edc.runtime.metamodel.annotation.Provider; -import org.eclipse.edc.spi.monitor.Monitor; -import org.eclipse.edc.spi.system.ServiceExtension; -import org.eclipse.tractusx.edc.iam.ssi.miw.api.MiwApiClient; -import org.eclipse.tractusx.edc.iam.ssi.miw.credentials.SsiMiwCredentialClient; -import org.eclipse.tractusx.edc.iam.ssi.spi.SsiCredentialClient; - -@Extension(SsiMiwCredentialClientExtension.EXTENSION_NAME) -public class SsiMiwCredentialClientExtension implements ServiceExtension { - - public static final String EXTENSION_NAME = "SSI MIW Credential Client"; - - @Inject - private MiwApiClient apiClient; - - @Inject - private JsonLd jsonLdService; - - @Inject - private Monitor monitor; - - @Override - public String name() { - return EXTENSION_NAME; - } - - - @Provider - public SsiCredentialClient credentialVerifier() { - return new SsiMiwCredentialClient(apiClient, jsonLdService, monitor); - } - - -} diff --git a/edc-extensions/ssi/ssi-miw-credential-client/src/main/java/org/eclipse/tractusx/edc/iam/ssi/miw/SsiMiwOauth2ClientExtension.java b/edc-extensions/ssi/ssi-miw-credential-client/src/main/java/org/eclipse/tractusx/edc/iam/ssi/miw/SsiMiwOauth2ClientExtension.java deleted file mode 100644 index ae52fb374..000000000 --- a/edc-extensions/ssi/ssi-miw-credential-client/src/main/java/org/eclipse/tractusx/edc/iam/ssi/miw/SsiMiwOauth2ClientExtension.java +++ /dev/null @@ -1,83 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.iam.ssi.miw; - -import org.eclipse.edc.iam.oauth2.spi.client.Oauth2Client; -import org.eclipse.edc.runtime.metamodel.annotation.Extension; -import org.eclipse.edc.runtime.metamodel.annotation.Inject; -import org.eclipse.edc.runtime.metamodel.annotation.Provider; -import org.eclipse.edc.runtime.metamodel.annotation.Setting; -import org.eclipse.edc.spi.security.Vault; -import org.eclipse.edc.spi.system.ServiceExtension; -import org.eclipse.edc.spi.system.ServiceExtensionContext; -import org.eclipse.tractusx.edc.iam.ssi.miw.oauth2.MiwOauth2Client; -import org.eclipse.tractusx.edc.iam.ssi.miw.oauth2.MiwOauth2ClientConfiguration; -import org.eclipse.tractusx.edc.iam.ssi.miw.oauth2.MiwOauth2ClientImpl; - -import java.util.Objects; - -import static org.eclipse.tractusx.edc.core.utils.PathUtils.removeTrailingSlash; - - -@Extension(SsiMiwOauth2ClientExtension.EXTENSION_NAME) -public class SsiMiwOauth2ClientExtension implements ServiceExtension { - - public static final String EXTENSION_NAME = "SSI MIW OAuth2 Client"; - - @Setting(value = "OAuth2 endpoint for requesting a token") - public static final String TOKEN_URL = "tx.ssi.oauth.token.url"; - - - @Setting(value = "OAuth2 client id") - public static final String CLIENT_ID = "tx.ssi.oauth.client.id"; - - @Setting(value = "Vault alias of OAuth2 client secret") - public static final String CLIENT_SECRET_ALIAS = "tx.ssi.oauth.client.secret.alias"; - - @Inject - private Oauth2Client oauth2Client; - - @Inject - private Vault vault; - - @Override - public String name() { - return EXTENSION_NAME; - } - - @Provider - public MiwOauth2Client oauth2Client(ServiceExtensionContext context) { - return new MiwOauth2ClientImpl(oauth2Client, createConfiguration(context)); - } - - private MiwOauth2ClientConfiguration createConfiguration(ServiceExtensionContext context) { - var tokenUrl = removeTrailingSlash(context.getConfig().getString(TOKEN_URL)); - var clientId = context.getConfig().getString(CLIENT_ID); - var clientSecretAlias = context.getConfig().getString(CLIENT_SECRET_ALIAS); - var clientSecret = vault.resolveSecret(clientSecretAlias); - Objects.requireNonNull(clientSecret, "Client secret could not be retrieved"); - - return MiwOauth2ClientConfiguration.Builder.newInstance() - .tokenUrl(tokenUrl) - .clientId(clientId) - .clientSecret(clientSecret) - .build(); - } -} diff --git a/edc-extensions/ssi/ssi-miw-credential-client/src/main/java/org/eclipse/tractusx/edc/iam/ssi/miw/SsiMiwValidationRuleExtension.java b/edc-extensions/ssi/ssi-miw-credential-client/src/main/java/org/eclipse/tractusx/edc/iam/ssi/miw/SsiMiwValidationRuleExtension.java deleted file mode 100644 index 469df860e..000000000 --- a/edc-extensions/ssi/ssi-miw-credential-client/src/main/java/org/eclipse/tractusx/edc/iam/ssi/miw/SsiMiwValidationRuleExtension.java +++ /dev/null @@ -1,57 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.iam.ssi.miw; - -import org.eclipse.edc.runtime.metamodel.annotation.Extension; -import org.eclipse.edc.runtime.metamodel.annotation.Inject; -import org.eclipse.edc.spi.monitor.Monitor; -import org.eclipse.edc.spi.system.ServiceExtension; -import org.eclipse.edc.spi.system.ServiceExtensionContext; -import org.eclipse.edc.token.spi.TokenValidationRulesRegistry; -import org.eclipse.tractusx.edc.iam.ssi.miw.config.SsiMiwConfiguration; -import org.eclipse.tractusx.edc.iam.ssi.miw.rule.SsiCredentialIssuerValidationRule; -import org.eclipse.tractusx.edc.iam.ssi.miw.rule.SsiCredentialSubjectIdValidationRule; - -import static org.eclipse.tractusx.edc.iam.ssi.spi.SsiConstants.SSI_TOKEN_CONTEXT; - -@Extension(SsiMiwValidationRuleExtension.EXTENSION_NAME) -public class SsiMiwValidationRuleExtension implements ServiceExtension { - - protected static final String EXTENSION_NAME = "SSI MIW validation rules extension"; - @Inject - private TokenValidationRulesRegistry registry; - - @Inject - private Monitor monitor; - - @Inject - private SsiMiwConfiguration miwConfiguration; - - @Override - public String name() { - return EXTENSION_NAME; - } - - @Override - public void initialize(ServiceExtensionContext context) { - registry.addRule(SSI_TOKEN_CONTEXT, new SsiCredentialSubjectIdValidationRule(monitor)); - registry.addRule(SSI_TOKEN_CONTEXT, new SsiCredentialIssuerValidationRule(miwConfiguration.getAuthorityIssuer(), monitor)); - } -} diff --git a/edc-extensions/ssi/ssi-miw-credential-client/src/main/java/org/eclipse/tractusx/edc/iam/ssi/miw/api/MiwApiClient.java b/edc-extensions/ssi/ssi-miw-credential-client/src/main/java/org/eclipse/tractusx/edc/iam/ssi/miw/api/MiwApiClient.java deleted file mode 100644 index cc90325f0..000000000 --- a/edc-extensions/ssi/ssi-miw-credential-client/src/main/java/org/eclipse/tractusx/edc/iam/ssi/miw/api/MiwApiClient.java +++ /dev/null @@ -1,39 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.iam.ssi.miw.api; - -import org.eclipse.edc.runtime.metamodel.annotation.ExtensionPoint; -import org.eclipse.edc.spi.result.Result; - -import java.util.List; -import java.util.Map; -import java.util.Set; - -@ExtensionPoint -public interface MiwApiClient { - String VP = "vp"; - - Result>> getCredentials(Set types); - - Result> createPresentation(List> credentials, String audience); - - Result verifyPresentation(String jwtPresentation, String audience); - -} diff --git a/edc-extensions/ssi/ssi-miw-credential-client/src/main/java/org/eclipse/tractusx/edc/iam/ssi/miw/api/MiwApiClientImpl.java b/edc-extensions/ssi/ssi-miw-credential-client/src/main/java/org/eclipse/tractusx/edc/iam/ssi/miw/api/MiwApiClientImpl.java deleted file mode 100644 index aa0410acc..000000000 --- a/edc-extensions/ssi/ssi-miw-credential-client/src/main/java/org/eclipse/tractusx/edc/iam/ssi/miw/api/MiwApiClientImpl.java +++ /dev/null @@ -1,208 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.iam.ssi.miw.api; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.ObjectMapper; -import okhttp3.MediaType; -import okhttp3.Request; -import okhttp3.RequestBody; -import okhttp3.Response; -import org.eclipse.edc.spi.http.EdcHttpClient; -import org.eclipse.edc.spi.iam.TokenRepresentation; -import org.eclipse.edc.spi.monitor.Monitor; -import org.eclipse.edc.spi.result.Result; -import org.eclipse.tractusx.edc.iam.ssi.miw.oauth2.MiwOauth2Client; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Optional; -import java.util.Set; - -import static java.lang.String.format; -import static org.eclipse.tractusx.edc.iam.ssi.miw.api.MiwFallbackFactories.retryWhenStatusIsNotIn; - -public class MiwApiClientImpl implements MiwApiClient { - - public static final MediaType TYPE_JSON = MediaType.parse("application/json"); - public static final String CREDENTIAL_PATH = "/api/credentials"; - public static final String PRESENTATIONS_PATH = "/api/presentations"; - public static final String PRESENTATIONS_VALIDATION_PATH = "/api/presentations/validation"; - public static final String HOLDER_IDENTIFIER = "holderIdentifier"; - - public static final String ISSUER_IDENTIFIER = "issuerIdentifier"; - public static final String VERIFIABLE_CREDENTIALS = "verifiableCredentials"; - public static final String VP_FIELD = "vp"; - public static final String CONTENT_FIELD = "content"; - private static final String PRESENTATIONS_QUERY_PARAMS = "?asJwt=true&audience=%s"; - private final EdcHttpClient httpClient; - private final String baseUrl; - private final MiwOauth2Client oauth2Client; - private final ObjectMapper mapper; - private final Monitor monitor; - - private final String authorityId; - - private final String participantId; - - public MiwApiClientImpl(EdcHttpClient httpClient, String baseUrl, MiwOauth2Client oauth2Client, String participantId, String authorityId, ObjectMapper mapper, Monitor monitor) { - this.httpClient = httpClient; - this.baseUrl = baseUrl; - this.oauth2Client = oauth2Client; - this.participantId = participantId; - this.authorityId = authorityId; - this.mapper = mapper; - this.monitor = monitor; - } - - @Override - public Result>> getCredentials(Set types) { - - var params = new ArrayList(); - params.add(format("%s=%s", ISSUER_IDENTIFIER, authorityId)); - - if (!types.isEmpty()) { - params.add(format("type=%s", String.join(",", types))); - } - - var queryParams = "?" + String.join("&", params); - var url = baseUrl + CREDENTIAL_PATH + queryParams; - - return baseRequestWithToken().map(builder -> builder.get().url(url).build()) - .compose(request -> executeRequest(request, new TypeReference>() { - })) - .compose(this::handleGetCredentialResponse); - } - - @Override - public Result> createPresentation(List> credentials, String audience) { - try { - var body = Map.of(HOLDER_IDENTIFIER, participantId, VERIFIABLE_CREDENTIALS, credentials); - var url = baseUrl + PRESENTATIONS_PATH + format(PRESENTATIONS_QUERY_PARAMS, audience); - var requestBody = RequestBody.create(mapper.writeValueAsString(body), TYPE_JSON); - - return baseRequestWithToken().map(builder -> builder.post(requestBody).url(url).build()) - .compose(request -> executeRequest(request, new TypeReference<>() { - })); - } catch (JsonProcessingException e) { - return Result.failure(e.getMessage()); - } - } - - @Override - public Result verifyPresentation(String jwtPresentation, String audience) { - try { - var body = Map.of(VP_FIELD, jwtPresentation); - var url = baseUrl + PRESENTATIONS_VALIDATION_PATH + format(PRESENTATIONS_QUERY_PARAMS, audience); - var requestBody = RequestBody.create(mapper.writeValueAsString(body), TYPE_JSON); - - return baseRequestWithToken().map(builder -> builder.post(requestBody).url(url).build()) - .compose(request -> executeRequest(request, new TypeReference>() { - })) - .compose(this::handleVerifyResult); - } catch (JsonProcessingException e) { - return Result.failure(e.getMessage()); - } - } - - private Result>> handleGetCredentialResponse(Map response) { - var content = response.get(CONTENT_FIELD); - - if (content == null) { - return Result.failure("Missing content field in the credentials response"); - } - return Result.success((List>) content); - } - - private Result handleVerifyResult(Map response) { - var valid = Optional.ofNullable(response.get("valid")) - .map(Boolean.TRUE::equals) - .orElse(false); - - if (valid) { - return Result.success(); - } else { - var msg = "MIW verification failed"; - monitor.severe(msg); - return Result.failure(msg); - } - } - - private Result executeRequest(Request request, TypeReference typeReference) { - try (var response = httpClient.execute(request, List.of(retryWhenStatusIsNotIn(200, 201)))) { - return handleResponse(response, typeReference); - } catch (MiwClientException e) { - if (e.getResponse() != null) { - return handleError(e.getResponse()); - } else { - return Result.failure(e.getMessage()); - } - } catch (IOException e) { - return Result.failure(e.getMessage()); - } - } - - private Result handleResponse(Response response, TypeReference tr) { - if (response.isSuccessful()) { - return handleSuccess(response, tr); - } else { - return handleError(response); - } - } - - private Result handleSuccess(Response response, TypeReference tr) { - try { - var body = Objects.requireNonNull(response.body()).string(); - return Result.success(mapper.readValue(body, tr)); - } catch (IOException e) { - monitor.severe("Failed to parse response from MIW"); - return Result.failure(e.getMessage()); - } - } - - private Result handleError(Response response) { - var body = ""; - if (response.body() != null) { - try { - body = response.body().string(); - } catch (IOException e) { - monitor.severe("Failed to read response from MIW"); - return Result.failure(e.getMessage()); - } - } - var code = response.code(); - monitor.severe(format("MIW API returned %s with body: %s", code, body)); - return Result.failure(format("MIW API returned %s", code)); - } - - private Result baseRequestWithToken() { - return oauth2Client.obtainRequestToken() - .map(this::baseRequestWithToken); - } - - private Request.Builder baseRequestWithToken(TokenRepresentation tokenRepresentation) { - return new Request.Builder() - .addHeader("Authorization", format("Bearer %s", tokenRepresentation.getToken())); - } -} diff --git a/edc-extensions/ssi/ssi-miw-credential-client/src/main/java/org/eclipse/tractusx/edc/iam/ssi/miw/api/MiwClientException.java b/edc-extensions/ssi/ssi-miw-credential-client/src/main/java/org/eclipse/tractusx/edc/iam/ssi/miw/api/MiwClientException.java deleted file mode 100644 index 65bf7a6af..000000000 --- a/edc-extensions/ssi/ssi-miw-credential-client/src/main/java/org/eclipse/tractusx/edc/iam/ssi/miw/api/MiwClientException.java +++ /dev/null @@ -1,43 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.iam.ssi.miw.api; - -import okhttp3.Response; -import org.eclipse.edc.spi.http.EdcHttpClientException; - -/** - * Custom client exception for handling failure and retries when fetching data from MIW. - */ -public class MiwClientException extends EdcHttpClientException { - private final Response response; - - public MiwClientException(String message) { - this(message, null); - } - - public MiwClientException(String message, Response response) { - super(message); - this.response = response; - } - - public Response getResponse() { - return response; - } -} diff --git a/edc-extensions/ssi/ssi-miw-credential-client/src/main/java/org/eclipse/tractusx/edc/iam/ssi/miw/api/MiwFallbackFactories.java b/edc-extensions/ssi/ssi-miw-credential-client/src/main/java/org/eclipse/tractusx/edc/iam/ssi/miw/api/MiwFallbackFactories.java deleted file mode 100644 index a4638b2f9..000000000 --- a/edc-extensions/ssi/ssi-miw-credential-client/src/main/java/org/eclipse/tractusx/edc/iam/ssi/miw/api/MiwFallbackFactories.java +++ /dev/null @@ -1,60 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.iam.ssi.miw.api; - -import dev.failsafe.Fallback; -import dev.failsafe.event.ExecutionAttemptedEvent; -import dev.failsafe.function.CheckedFunction; -import okhttp3.Response; -import org.eclipse.edc.spi.http.FallbackFactory; - -import java.util.Arrays; -import java.util.stream.Collectors; - -import static java.lang.String.format; - -public interface MiwFallbackFactories { - - static FallbackFactory retryWhenStatusIsNot(int status) { - return retryWhenStatusIsNotIn(status); - } - - /** - * Verifies that the response has a specific statuses, otherwise it should be retried - * - * @return the {@link FallbackFactory} - */ - static FallbackFactory retryWhenStatusIsNotIn(int... status) { - var codes = Arrays.stream(status).boxed().collect(Collectors.toSet()); - return request -> { - CheckedFunction, Exception> exceptionSupplier = event -> { - var response = event.getLastResult(); - if (response == null) { - return new MiwClientException(event.getLastException().getMessage()); - } else { - return new MiwClientException(format("Server response to %s was not one of %s but was %s", request, Arrays.toString(status), response.code()), response); - } - }; - return Fallback.builderOfException(exceptionSupplier) - .handleResultIf(r -> !codes.contains(r.code())) - .build(); - }; - } -} diff --git a/edc-extensions/ssi/ssi-miw-credential-client/src/main/java/org/eclipse/tractusx/edc/iam/ssi/miw/config/SsiMiwConfiguration.java b/edc-extensions/ssi/ssi-miw-credential-client/src/main/java/org/eclipse/tractusx/edc/iam/ssi/miw/config/SsiMiwConfiguration.java deleted file mode 100644 index 028f11a8b..000000000 --- a/edc-extensions/ssi/ssi-miw-credential-client/src/main/java/org/eclipse/tractusx/edc/iam/ssi/miw/config/SsiMiwConfiguration.java +++ /dev/null @@ -1,75 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.iam.ssi.miw.config; - -import java.util.Objects; - -public class SsiMiwConfiguration { - - protected String url; - protected String authorityId; - protected String authorityIssuer; - - public String getAuthorityId() { - return authorityId; - } - - public String getUrl() { - return url; - } - - public String getAuthorityIssuer() { - return authorityIssuer; - } - - public static class Builder { - private final SsiMiwConfiguration config; - - private Builder() { - config = new SsiMiwConfiguration(); - } - - public static Builder newInstance() { - return new Builder(); - } - - public Builder url(String url) { - config.url = url; - return this; - } - - public Builder authorityId(String authorityId) { - config.authorityId = authorityId; - return this; - } - - public Builder authorityIssuer(String authorityIssuer) { - config.authorityIssuer = authorityIssuer; - return this; - } - - public SsiMiwConfiguration build() { - Objects.requireNonNull(config.url); - Objects.requireNonNull(config.authorityIssuer); - Objects.requireNonNull(config.authorityId); - return config; - } - } -} diff --git a/edc-extensions/ssi/ssi-miw-credential-client/src/main/java/org/eclipse/tractusx/edc/iam/ssi/miw/credentials/SsiMiwCredentialClient.java b/edc-extensions/ssi/ssi-miw-credential-client/src/main/java/org/eclipse/tractusx/edc/iam/ssi/miw/credentials/SsiMiwCredentialClient.java deleted file mode 100644 index 2011cbd8f..000000000 --- a/edc-extensions/ssi/ssi-miw-credential-client/src/main/java/org/eclipse/tractusx/edc/iam/ssi/miw/credentials/SsiMiwCredentialClient.java +++ /dev/null @@ -1,130 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.iam.ssi.miw.credentials; - -import com.nimbusds.jwt.SignedJWT; -import jakarta.json.Json; -import org.eclipse.edc.jsonld.spi.JsonLd; -import org.eclipse.edc.spi.iam.ClaimToken; -import org.eclipse.edc.spi.iam.TokenParameters; -import org.eclipse.edc.spi.iam.TokenRepresentation; -import org.eclipse.edc.spi.monitor.Monitor; -import org.eclipse.edc.spi.result.Result; -import org.eclipse.tractusx.edc.iam.ssi.miw.api.MiwApiClient; -import org.eclipse.tractusx.edc.iam.ssi.spi.SsiCredentialClient; - -import java.text.ParseException; -import java.util.Arrays; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -import static org.eclipse.edc.jwt.spi.JwtRegisteredClaimNames.AUDIENCE; -import static org.eclipse.edc.jwt.spi.JwtRegisteredClaimNames.SCOPE; -import static org.eclipse.tractusx.edc.iam.ssi.miw.api.MiwApiClient.VP; - -public class SsiMiwCredentialClient implements SsiCredentialClient { - - private final MiwApiClient apiClient; - - private final JsonLd jsonLdService; - private final Monitor monitor; - - public SsiMiwCredentialClient(MiwApiClient apiClient, JsonLd jsonLdService, Monitor monitor) { - this.apiClient = apiClient; - this.jsonLdService = jsonLdService; - this.monitor = monitor; - } - - @Override - public Result obtainClientCredentials(TokenParameters parameters) { - var scopes = Arrays.stream(parameters.getStringClaim(SCOPE).split(" ")) - .map(String::trim) - .filter((s) -> !s.isEmpty()) - .collect(Collectors.toSet()); - - return apiClient.getCredentials(scopes) - .compose(credentials -> createPresentation(credentials, parameters)) - .compose(this::createToken); - } - - @Override - public Result validate(TokenRepresentation tokenRepresentation) { - return extractClaims(tokenRepresentation) - .compose(claimToken -> validatePresentation(claimToken, tokenRepresentation)); - } - - private Result createToken(Map presentationResponse) { - var vp = presentationResponse.get(VP); - if (vp instanceof String) { - return Result.success(TokenRepresentation.Builder.newInstance().token((String) vp).build()); - } else { - return Result.failure("Missing or invalid format for Verifiable Presentation"); - } - } - - private Result> createPresentation(List> credentials, TokenParameters tokenParameters) { - if (!credentials.isEmpty()) { - return apiClient.createPresentation(credentials, tokenParameters.getStringClaim(AUDIENCE)); - } else { - return Result.failure("Cannot create a presentation from an empty credentials list"); - } - } - - private Result validatePresentation(ClaimToken claimToken, TokenRepresentation tokenRepresentation) { - return claimToken.getListClaim(AUDIENCE).stream().map(String.class::cast).findFirst() - .map(audience -> apiClient.verifyPresentation(tokenRepresentation.getToken(), audience) - .compose(v -> Result.success(claimToken))) - .orElseGet(() -> Result.failure("Required audience (aud) claim is missing in token")); - } - - private Result extractClaims(TokenRepresentation tokenRepresentation) { - try { - var jwt = SignedJWT.parse(tokenRepresentation.getToken()); - - var tokenBuilder = ClaimToken.Builder.newInstance(); - jwt.getJWTClaimsSet().getClaims().entrySet().stream() - .filter(entry -> entry.getValue() != null) - .map(this::mapClaim) - .peek(this::logIfError) - .filter(Result::succeeded) - .map(Result::getContent) - .forEach(entry -> tokenBuilder.claim(entry.getKey(), entry.getValue())); - - return Result.success(tokenBuilder.build()); - } catch (ParseException e) { - return Result.failure(e.getMessage()); - } - } - - private Result> mapClaim(Map.Entry entry) { - if (entry.getKey().equals(VP)) { - var json = Json.createObjectBuilder((Map) entry.getValue()).build(); - return jsonLdService.expand(json) - .map((expanded) -> Map.entry(entry.getKey(), expanded)); - } else { - return Result.success(entry); - } - } - - private void logIfError(Result result) { - result.onFailure(f -> monitor.warning(f.getFailureDetail())); - } -} diff --git a/edc-extensions/ssi/ssi-miw-credential-client/src/main/java/org/eclipse/tractusx/edc/iam/ssi/miw/oauth2/MiwOauth2Client.java b/edc-extensions/ssi/ssi-miw-credential-client/src/main/java/org/eclipse/tractusx/edc/iam/ssi/miw/oauth2/MiwOauth2Client.java deleted file mode 100644 index 20a8451f7..000000000 --- a/edc-extensions/ssi/ssi-miw-credential-client/src/main/java/org/eclipse/tractusx/edc/iam/ssi/miw/oauth2/MiwOauth2Client.java +++ /dev/null @@ -1,32 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.iam.ssi.miw.oauth2; - -import org.eclipse.edc.runtime.metamodel.annotation.ExtensionPoint; -import org.eclipse.edc.spi.iam.TokenRepresentation; -import org.eclipse.edc.spi.result.Result; - -/** - * OAuth2 client for fetching an access token to be added when using the MIW APIs - */ -@ExtensionPoint -public interface MiwOauth2Client { - Result obtainRequestToken(); -} diff --git a/edc-extensions/ssi/ssi-miw-credential-client/src/main/java/org/eclipse/tractusx/edc/iam/ssi/miw/oauth2/MiwOauth2ClientConfiguration.java b/edc-extensions/ssi/ssi-miw-credential-client/src/main/java/org/eclipse/tractusx/edc/iam/ssi/miw/oauth2/MiwOauth2ClientConfiguration.java deleted file mode 100644 index c17f2dfae..000000000 --- a/edc-extensions/ssi/ssi-miw-credential-client/src/main/java/org/eclipse/tractusx/edc/iam/ssi/miw/oauth2/MiwOauth2ClientConfiguration.java +++ /dev/null @@ -1,82 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.iam.ssi.miw.oauth2; - -/** - * Configuration of the OAuth2 client - */ -public class MiwOauth2ClientConfiguration { - private String tokenUrl; - private String clientId; - - private String clientSecret; - private String scope; - - public String getScope() { - return scope; - } - - public String getClientId() { - return clientId; - } - - public String getClientSecret() { - return clientSecret; - } - - public String getTokenUrl() { - return tokenUrl; - } - - public static class Builder { - private final MiwOauth2ClientConfiguration configuration = new MiwOauth2ClientConfiguration(); - - private Builder() { - } - - public static Builder newInstance() { - return new Builder(); - } - - public Builder tokenUrl(String url) { - configuration.tokenUrl = url; - return this; - } - - public Builder clientId(String clientId) { - configuration.clientId = clientId; - return this; - } - - public Builder scope(String scope) { - configuration.scope = scope; - return this; - } - - public Builder clientSecret(String clientSecret) { - configuration.clientSecret = clientSecret; - return this; - } - - public MiwOauth2ClientConfiguration build() { - return configuration; - } - } -} diff --git a/edc-extensions/ssi/ssi-miw-credential-client/src/main/java/org/eclipse/tractusx/edc/iam/ssi/miw/oauth2/MiwOauth2ClientImpl.java b/edc-extensions/ssi/ssi-miw-credential-client/src/main/java/org/eclipse/tractusx/edc/iam/ssi/miw/oauth2/MiwOauth2ClientImpl.java deleted file mode 100644 index 1d18bbbe0..000000000 --- a/edc-extensions/ssi/ssi-miw-credential-client/src/main/java/org/eclipse/tractusx/edc/iam/ssi/miw/oauth2/MiwOauth2ClientImpl.java +++ /dev/null @@ -1,63 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.iam.ssi.miw.oauth2; - -import org.eclipse.edc.iam.oauth2.spi.client.Oauth2Client; -import org.eclipse.edc.iam.oauth2.spi.client.Oauth2CredentialsRequest; -import org.eclipse.edc.iam.oauth2.spi.client.SharedSecretOauth2CredentialsRequest; -import org.eclipse.edc.spi.iam.TokenRepresentation; -import org.eclipse.edc.spi.result.Result; -import org.jetbrains.annotations.NotNull; - -public class MiwOauth2ClientImpl implements MiwOauth2Client { - - private static final String GRANT_TYPE = "client_credentials"; - private final Oauth2Client oauth2Client; - - private final MiwOauth2ClientConfiguration configuration; - - public MiwOauth2ClientImpl(Oauth2Client oauth2Client, MiwOauth2ClientConfiguration configuration) { - this.oauth2Client = oauth2Client; - this.configuration = configuration; - } - - @Override - public Result obtainRequestToken() { - return oauth2Client.requestToken(createRequest()); - } - - public MiwOauth2ClientConfiguration getConfiguration() { - return configuration; - } - - @NotNull - private Oauth2CredentialsRequest createRequest() { - var builder = SharedSecretOauth2CredentialsRequest.Builder.newInstance() - .url(configuration.getTokenUrl()) - .clientId(configuration.getClientId()) - .clientSecret(configuration.getClientSecret()) - .grantType(GRANT_TYPE); - - if (configuration.getScope() != null) { - builder.scope(configuration.getScope()); - } - return builder.build(); - } -} diff --git a/edc-extensions/ssi/ssi-miw-credential-client/src/main/java/org/eclipse/tractusx/edc/iam/ssi/miw/rule/SsiCredentialIssuerValidationRule.java b/edc-extensions/ssi/ssi-miw-credential-client/src/main/java/org/eclipse/tractusx/edc/iam/ssi/miw/rule/SsiCredentialIssuerValidationRule.java deleted file mode 100644 index 412ad9ada..000000000 --- a/edc-extensions/ssi/ssi-miw-credential-client/src/main/java/org/eclipse/tractusx/edc/iam/ssi/miw/rule/SsiCredentialIssuerValidationRule.java +++ /dev/null @@ -1,104 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.iam.ssi.miw.rule; - -import jakarta.json.JsonObject; -import org.eclipse.edc.spi.iam.ClaimToken; -import org.eclipse.edc.spi.monitor.Monitor; -import org.eclipse.edc.spi.result.Result; -import org.eclipse.edc.token.spi.TokenValidationRule; -import org.eclipse.tractusx.edc.iam.ssi.spi.jsonld.JsonLdFieldExtractor; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.Map; -import java.util.Optional; -import java.util.stream.Stream; - -import static java.lang.String.format; -import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.ID; -import static org.eclipse.tractusx.edc.iam.ssi.spi.jsonld.CredentialsNamespaces.CREDENTIAL_ISSUER; -import static org.eclipse.tractusx.edc.iam.ssi.spi.jsonld.CredentialsNamespaces.SUMMARY_CREDENTIAL_TYPE; -import static org.eclipse.tractusx.edc.iam.ssi.spi.jsonld.CredentialsNamespaces.VP_PROPERTY; -import static org.eclipse.tractusx.edc.iam.ssi.spi.jsonld.JsonLdTypeFunctions.extractObjectsOfType; - -/** - * {@link TokenValidationRule} that compares the issuer in the Verifiable Credential (Summary) with the one provided - * by configuration. - */ -public class SsiCredentialIssuerValidationRule implements TokenValidationRule { - - private static final String SUBJECT_ISSUER_EXTRACTOR_PREFIX = "Credential issuer extractor:"; - - private static final String SUBJECT_ISSUER_FIELD_ALIAS = "issuer"; - - private final String credentialIssuer; - - private final Monitor monitor; - - private final JsonLdFieldExtractor credentialIssuerExtractor = JsonLdFieldExtractor.Builder.newInstance() - .field(CREDENTIAL_ISSUER) - .fieldAlias(SUBJECT_ISSUER_FIELD_ALIAS) - .errorPrefix(SUBJECT_ISSUER_EXTRACTOR_PREFIX) - .build(); - - public SsiCredentialIssuerValidationRule(String credentialIssuer, Monitor monitor) { - this.credentialIssuer = credentialIssuer; - this.monitor = monitor; - } - - @Override - public Result checkRule(@NotNull ClaimToken toVerify, @Nullable Map additional) { - - var vp = (JsonObject) toVerify.getClaim(VP_PROPERTY); - - return Optional.ofNullable(vp) - .map(v -> extractObjectsOfType(SUMMARY_CREDENTIAL_TYPE, v)) - .orElse(Stream.empty()) - .map(this::extractIssuer) - .findFirst() - .orElseGet(() -> Result.failure("Failed to extract credential subject from the membership credential")) - .compose(this::validateCredentialIssuer) - .onFailure(failure -> monitor.severe(failure.getFailureDetail())); - - } - - private Result validateCredentialIssuer(String extractedCredentialIssuer) { - if (credentialIssuer.equals(extractedCredentialIssuer)) { - return Result.success(); - } else { - return Result.failure(format("Invalid credential issuer: expected %s, found %s", credentialIssuer, extractedCredentialIssuer)); - } - } - - private Result extractIssuer(JsonObject credential) { - return this.credentialIssuerExtractor.extract(credential) - .compose(this::extractIssuerValue); - } - - private Result extractIssuerValue(JsonObject issuer) { - var issuerValue = issuer.getString(ID); - if (issuerValue == null) { - return Result.failure("Failed to find the issuer"); - } else { - return Result.success(issuerValue); - } - } -} diff --git a/edc-extensions/ssi/ssi-miw-credential-client/src/main/java/org/eclipse/tractusx/edc/iam/ssi/miw/rule/SsiCredentialSubjectIdValidationRule.java b/edc-extensions/ssi/ssi-miw-credential-client/src/main/java/org/eclipse/tractusx/edc/iam/ssi/miw/rule/SsiCredentialSubjectIdValidationRule.java deleted file mode 100644 index 1c2e80315..000000000 --- a/edc-extensions/ssi/ssi-miw-credential-client/src/main/java/org/eclipse/tractusx/edc/iam/ssi/miw/rule/SsiCredentialSubjectIdValidationRule.java +++ /dev/null @@ -1,105 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.iam.ssi.miw.rule; - -import jakarta.json.JsonObject; -import org.eclipse.edc.spi.iam.ClaimToken; -import org.eclipse.edc.spi.monitor.Monitor; -import org.eclipse.edc.spi.result.Result; -import org.eclipse.edc.token.spi.TokenValidationRule; -import org.eclipse.tractusx.edc.iam.ssi.spi.jsonld.JsonLdFieldExtractor; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.Map; -import java.util.Optional; -import java.util.stream.Stream; - -import static java.lang.String.format; -import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.ID; -import static org.eclipse.edc.jwt.spi.JwtRegisteredClaimNames.ISSUER; -import static org.eclipse.tractusx.edc.iam.ssi.spi.jsonld.CredentialsNamespaces.CREDENTIAL_SUBJECT; -import static org.eclipse.tractusx.edc.iam.ssi.spi.jsonld.CredentialsNamespaces.SUMMARY_CREDENTIAL_TYPE; -import static org.eclipse.tractusx.edc.iam.ssi.spi.jsonld.CredentialsNamespaces.VP_PROPERTY; -import static org.eclipse.tractusx.edc.iam.ssi.spi.jsonld.JsonLdTypeFunctions.extractObjectsOfType; - -/** - * {@link TokenValidationRule} that compares the issuer of the VP (JWT format) with the credential subject id of - * the Verifiable Credential (Summary) - */ -public class SsiCredentialSubjectIdValidationRule implements TokenValidationRule { - - private static final String CREDENTIAL_SUBJECT_EXTRACTOR_PREFIX = "Credential subject extractor:"; - private static final String CREDENTIAL_SUBJECT_FIELD_ALIAS = "credentialSubject"; - - private final Monitor monitor; - - private final JsonLdFieldExtractor credentialSubjectExtractor = JsonLdFieldExtractor.Builder.newInstance() - .field(CREDENTIAL_SUBJECT) - .fieldAlias(CREDENTIAL_SUBJECT_FIELD_ALIAS) - .errorPrefix(CREDENTIAL_SUBJECT_EXTRACTOR_PREFIX) - .build(); - - public SsiCredentialSubjectIdValidationRule(Monitor monitor) { - this.monitor = monitor; - } - - @Override - public Result checkRule(@NotNull ClaimToken toVerify, @Nullable Map additional) { - var issuer = toVerify.getStringClaim(ISSUER); - - if (issuer == null) { - return Result.failure("Required issuer (iss) claim is missing in token"); - } - var vp = (JsonObject) toVerify.getClaim(VP_PROPERTY); - - return Optional.ofNullable(vp) - .map(v -> extractObjectsOfType(SUMMARY_CREDENTIAL_TYPE, v)) - .orElse(Stream.empty()) - .map(this::extractSubjectId) - .findFirst() - .orElseGet(() -> Result.failure("Failed to extract credential subject from the membership credential")) - .compose(credentialSubjectId -> validateCredentialSubjectId(credentialSubjectId, issuer)) - .onFailure((failure -> monitor.severe(failure.getFailureDetail()))); - - } - - private Result validateCredentialSubjectId(String credentialSubjectId, String issuer) { - if (issuer.equals(credentialSubjectId)) { - return Result.success(); - } else { - return Result.failure(format("Issuer %s and credential subject id %s don't match", issuer, credentialSubjectId)); - } - } - - private Result extractSubjectId(JsonObject credential) { - return this.credentialSubjectExtractor.extract(credential) - .compose(this::extractId); - } - - private Result extractId(JsonObject credentialSubject) { - var id = credentialSubject.getString(ID); - if (id == null) { - return Result.failure("Failed to find the id in credential subject"); - } else { - return Result.success(id); - } - } -} diff --git a/edc-extensions/ssi/ssi-miw-credential-client/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension b/edc-extensions/ssi/ssi-miw-credential-client/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension deleted file mode 100644 index 6919e95a8..000000000 --- a/edc-extensions/ssi/ssi-miw-credential-client/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension +++ /dev/null @@ -1,24 +0,0 @@ -################################################################################# -# Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) -# -# See the NOTICE file(s) distributed with this work for additional -# information regarding copyright ownership. -# -# This program and the accompanying materials are made available under the -# terms of the Apache License, Version 2.0 which is available at -# https://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. -# -# SPDX-License-Identifier: Apache-2.0 -################################################################################# - -org.eclipse.tractusx.edc.iam.ssi.miw.SsiMiwCredentialClientExtension -org.eclipse.tractusx.edc.iam.ssi.miw.SsiMiwApiClientExtension -org.eclipse.tractusx.edc.iam.ssi.miw.SsiMiwOauth2ClientExtension -org.eclipse.tractusx.edc.iam.ssi.miw.SsiMiwValidationRuleExtension -org.eclipse.tractusx.edc.iam.ssi.miw.SsiMiwConfigurationExtension diff --git a/edc-extensions/ssi/ssi-miw-credential-client/src/test/java/org/eclipse/tractusx/edc/iam/ssi/miw/SsiMiwApiClientExtensionTest.java b/edc-extensions/ssi/ssi-miw-credential-client/src/test/java/org/eclipse/tractusx/edc/iam/ssi/miw/SsiMiwApiClientExtensionTest.java deleted file mode 100644 index 9c2cbf9da..000000000 --- a/edc-extensions/ssi/ssi-miw-credential-client/src/test/java/org/eclipse/tractusx/edc/iam/ssi/miw/SsiMiwApiClientExtensionTest.java +++ /dev/null @@ -1,60 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.iam.ssi.miw; - -import org.eclipse.edc.junit.extensions.DependencyInjectionExtension; -import org.eclipse.edc.spi.system.ServiceExtensionContext; -import org.eclipse.edc.spi.types.TypeManager; -import org.eclipse.tractusx.edc.iam.ssi.miw.api.MiwApiClient; -import org.eclipse.tractusx.edc.iam.ssi.miw.api.MiwApiClientImpl; -import org.eclipse.tractusx.edc.iam.ssi.miw.config.SsiMiwConfiguration; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -@ExtendWith(DependencyInjectionExtension.class) -public class SsiMiwApiClientExtensionTest { - - private final SsiMiwConfiguration cfg = mock(SsiMiwConfiguration.class); - - @BeforeEach - void setup(ServiceExtensionContext context) { - context.registerService(SsiMiwConfiguration.class, cfg); - context.registerService(MiwApiClient.class, mock(MiwApiClient.class)); - context.registerService(TypeManager.class, new TypeManager()); - } - - @Test - void initialize(ServiceExtensionContext context, SsiMiwApiClientExtension extension) { - when(cfg.getUrl()).thenReturn("http://localhost"); - when(cfg.getAuthorityId()).thenReturn("id"); - - assertThat(extension.apiClient(context)).isInstanceOf(MiwApiClientImpl.class); - - verify(cfg).getUrl(); - verify(cfg).getAuthorityId(); - - } -} diff --git a/edc-extensions/ssi/ssi-miw-credential-client/src/test/java/org/eclipse/tractusx/edc/iam/ssi/miw/SsiMiwConfigurationExtensionTest.java b/edc-extensions/ssi/ssi-miw-credential-client/src/test/java/org/eclipse/tractusx/edc/iam/ssi/miw/SsiMiwConfigurationExtensionTest.java deleted file mode 100644 index c3333468e..000000000 --- a/edc-extensions/ssi/ssi-miw-credential-client/src/test/java/org/eclipse/tractusx/edc/iam/ssi/miw/SsiMiwConfigurationExtensionTest.java +++ /dev/null @@ -1,116 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.iam.ssi.miw; - -import org.eclipse.edc.junit.extensions.DependencyInjectionExtension; -import org.eclipse.edc.spi.system.ServiceExtensionContext; -import org.eclipse.edc.spi.system.configuration.Config; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; - -import static java.lang.String.format; -import static org.assertj.core.api.Assertions.assertThat; -import static org.eclipse.tractusx.edc.iam.ssi.miw.SsiMiwConfigurationExtension.AUTHORITY_ID_TEMPLATE; -import static org.eclipse.tractusx.edc.iam.ssi.miw.SsiMiwConfigurationExtension.MIW_AUTHORITY_ID; -import static org.eclipse.tractusx.edc.iam.ssi.miw.SsiMiwConfigurationExtension.MIW_AUTHORITY_ISSUER; -import static org.eclipse.tractusx.edc.iam.ssi.miw.SsiMiwConfigurationExtension.MIW_BASE_URL; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -@ExtendWith(DependencyInjectionExtension.class) -public class SsiMiwConfigurationExtensionTest { - - @Test - void initialize(ServiceExtensionContext context, SsiMiwConfigurationExtension extension) { - var url = "http://localhost:8080"; - var authorityId = "id"; - var authorityIssuer = "issuer"; - - var cfg = mock(Config.class); - when(context.getConfig()).thenReturn(cfg); - - when(cfg.getString(MIW_BASE_URL)).thenReturn(url); - when(cfg.getString(MIW_AUTHORITY_ID)).thenReturn(authorityId); - when(cfg.getString(eq(MIW_AUTHORITY_ISSUER), anyString())).thenReturn(authorityIssuer); - - var miwConfig = extension.miwConfiguration(context); - - verify(cfg).getString(MIW_BASE_URL); - verify(cfg).getString(MIW_AUTHORITY_ID); - verify(cfg).getString(eq(MIW_AUTHORITY_ISSUER), anyString()); - - assertThat(miwConfig.getUrl()).isEqualTo(url); - assertThat(miwConfig.getAuthorityId()).isEqualTo(authorityId); - assertThat(miwConfig.getAuthorityIssuer()).isEqualTo(authorityIssuer); - - } - - @Test - void initialize_withDefaultIssuer(ServiceExtensionContext context, SsiMiwConfigurationExtension extension) { - var url = "http://localhost:8080"; - var authorityId = "id"; - - var cfg = mock(Config.class); - when(context.getConfig()).thenReturn(cfg); - - when(cfg.getString(MIW_BASE_URL)).thenReturn(url); - when(cfg.getString(MIW_AUTHORITY_ID)).thenReturn(authorityId); - when(cfg.getString(eq(MIW_AUTHORITY_ISSUER), anyString())).thenAnswer(answer -> answer.getArgument(1)); - - var miwConfig = extension.miwConfiguration(context); - - verify(cfg).getString(MIW_BASE_URL); - verify(cfg).getString(MIW_AUTHORITY_ID); - verify(cfg).getString(eq(MIW_AUTHORITY_ISSUER), anyString()); - - assertThat(miwConfig.getUrl()).isEqualTo(url); - assertThat(miwConfig.getAuthorityId()).isEqualTo(authorityId); - assertThat(miwConfig.getAuthorityIssuer()).isEqualTo(format(AUTHORITY_ID_TEMPLATE, "localhost%3A8080", authorityId)); - - } - - @Test - void initialize_withTrailingUrl(ServiceExtensionContext context, SsiMiwConfigurationExtension extension) { - var url = "http://localhost:8080/"; - var authorityId = "id"; - - var cfg = mock(Config.class); - when(context.getConfig()).thenReturn(cfg); - - when(cfg.getString(MIW_BASE_URL)).thenReturn(url); - when(cfg.getString(MIW_AUTHORITY_ID)).thenReturn(authorityId); - when(cfg.getString(eq(MIW_AUTHORITY_ISSUER), anyString())).thenAnswer(answer -> answer.getArgument(1)); - - var miwConfig = extension.miwConfiguration(context); - - verify(cfg).getString(MIW_BASE_URL); - verify(cfg).getString(MIW_AUTHORITY_ID); - verify(cfg).getString(eq(MIW_AUTHORITY_ISSUER), anyString()); - - assertThat(miwConfig.getUrl()).isEqualTo("http://localhost:8080"); - assertThat(miwConfig.getAuthorityId()).isEqualTo(authorityId); - assertThat(miwConfig.getAuthorityIssuer()).isEqualTo(format(AUTHORITY_ID_TEMPLATE, "localhost%3A8080", authorityId)); - - } - -} diff --git a/edc-extensions/ssi/ssi-miw-credential-client/src/test/java/org/eclipse/tractusx/edc/iam/ssi/miw/SsiMiwCredentialClientExtensionTest.java b/edc-extensions/ssi/ssi-miw-credential-client/src/test/java/org/eclipse/tractusx/edc/iam/ssi/miw/SsiMiwCredentialClientExtensionTest.java deleted file mode 100644 index 45f6fda9d..000000000 --- a/edc-extensions/ssi/ssi-miw-credential-client/src/test/java/org/eclipse/tractusx/edc/iam/ssi/miw/SsiMiwCredentialClientExtensionTest.java +++ /dev/null @@ -1,48 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.iam.ssi.miw; - -import org.eclipse.edc.junit.extensions.DependencyInjectionExtension; -import org.eclipse.edc.spi.system.ServiceExtensionContext; -import org.eclipse.tractusx.edc.iam.ssi.miw.api.MiwApiClient; -import org.eclipse.tractusx.edc.iam.ssi.miw.credentials.SsiMiwCredentialClient; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.mock; - -@ExtendWith(DependencyInjectionExtension.class) -public class SsiMiwCredentialClientExtensionTest { - - SsiMiwCredentialClientExtension extension; - - @BeforeEach - void setup(ServiceExtensionContext context) { - context.registerService(MiwApiClient.class, mock(MiwApiClient.class)); - } - - @Test - void initialize(SsiMiwCredentialClientExtension extension) { - assertThat(extension.credentialVerifier()).isInstanceOf(SsiMiwCredentialClient.class); - } - -} diff --git a/edc-extensions/ssi/ssi-miw-credential-client/src/test/java/org/eclipse/tractusx/edc/iam/ssi/miw/SsiMiwOauth2ClientExtensionTest.java b/edc-extensions/ssi/ssi-miw-credential-client/src/test/java/org/eclipse/tractusx/edc/iam/ssi/miw/SsiMiwOauth2ClientExtensionTest.java deleted file mode 100644 index e35d733ff..000000000 --- a/edc-extensions/ssi/ssi-miw-credential-client/src/test/java/org/eclipse/tractusx/edc/iam/ssi/miw/SsiMiwOauth2ClientExtensionTest.java +++ /dev/null @@ -1,93 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.iam.ssi.miw; - -import org.assertj.core.api.InstanceOfAssertFactories; -import org.eclipse.edc.junit.extensions.DependencyInjectionExtension; -import org.eclipse.edc.spi.security.Vault; -import org.eclipse.edc.spi.system.ServiceExtensionContext; -import org.eclipse.edc.spi.system.configuration.Config; -import org.eclipse.edc.spi.types.TypeManager; -import org.eclipse.tractusx.edc.iam.ssi.miw.api.MiwApiClient; -import org.eclipse.tractusx.edc.iam.ssi.miw.oauth2.MiwOauth2ClientConfiguration; -import org.eclipse.tractusx.edc.iam.ssi.miw.oauth2.MiwOauth2ClientImpl; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.eclipse.tractusx.edc.iam.ssi.miw.SsiMiwOauth2ClientExtension.CLIENT_ID; -import static org.eclipse.tractusx.edc.iam.ssi.miw.SsiMiwOauth2ClientExtension.CLIENT_SECRET_ALIAS; -import static org.eclipse.tractusx.edc.iam.ssi.miw.SsiMiwOauth2ClientExtension.TOKEN_URL; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -@ExtendWith(DependencyInjectionExtension.class) -public class SsiMiwOauth2ClientExtensionTest { - - Vault vault = mock(Vault.class); - - @BeforeEach - void setup(ServiceExtensionContext context) { - context.registerService(MiwApiClient.class, mock(MiwApiClient.class)); - context.registerService(TypeManager.class, new TypeManager()); - context.registerService(Vault.class, vault); - } - - @Test - void initialize(ServiceExtensionContext context, SsiMiwOauth2ClientExtension extension) { - var config = mock(Config.class); - when(context.getConfig()).thenReturn(config); - when(config.getString(TOKEN_URL)).thenReturn("url"); - when(config.getString(CLIENT_ID)).thenReturn("clientId"); - when(config.getString(CLIENT_SECRET_ALIAS)).thenReturn("clientSecretAlias"); - when(vault.resolveSecret("clientSecretAlias")).thenReturn("clientSecret"); - - assertThat(extension.oauth2Client(context)).isInstanceOf(MiwOauth2ClientImpl.class); - verify(config).getString(TOKEN_URL); - verify(config).getString(CLIENT_ID); - verify(config).getString(CLIENT_SECRET_ALIAS); - verify(vault).resolveSecret("clientSecretAlias"); - } - - @Test - void initialize_withTrailingUrl(ServiceExtensionContext context, SsiMiwOauth2ClientExtension extension) { - var config = mock(Config.class); - when(context.getConfig()).thenReturn(config); - when(config.getString(TOKEN_URL)).thenReturn("http://localhost:8080/"); - when(config.getString(CLIENT_ID)).thenReturn("clientId"); - when(config.getString(CLIENT_SECRET_ALIAS)).thenReturn("clientSecretAlias"); - when(vault.resolveSecret("clientSecretAlias")).thenReturn("clientSecret"); - - assertThat(extension.oauth2Client(context)) - .asInstanceOf(InstanceOfAssertFactories.type(MiwOauth2ClientImpl.class)) - .extracting(MiwOauth2ClientImpl::getConfiguration) - .extracting(MiwOauth2ClientConfiguration::getTokenUrl) - .isEqualTo("http://localhost:8080"); - - verify(config).getString(TOKEN_URL); - verify(config).getString(CLIENT_ID); - verify(config).getString(CLIENT_SECRET_ALIAS); - verify(vault).resolveSecret("clientSecretAlias"); - } - - -} diff --git a/edc-extensions/ssi/ssi-miw-credential-client/src/test/java/org/eclipse/tractusx/edc/iam/ssi/miw/SsiMiwValidationRuleExtensionTest.java b/edc-extensions/ssi/ssi-miw-credential-client/src/test/java/org/eclipse/tractusx/edc/iam/ssi/miw/SsiMiwValidationRuleExtensionTest.java deleted file mode 100644 index 2273cb466..000000000 --- a/edc-extensions/ssi/ssi-miw-credential-client/src/test/java/org/eclipse/tractusx/edc/iam/ssi/miw/SsiMiwValidationRuleExtensionTest.java +++ /dev/null @@ -1,62 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.iam.ssi.miw; - -import org.eclipse.edc.junit.extensions.DependencyInjectionExtension; -import org.eclipse.edc.spi.system.ServiceExtensionContext; -import org.eclipse.edc.token.spi.TokenValidationRulesRegistry; -import org.eclipse.tractusx.edc.iam.ssi.miw.config.SsiMiwConfiguration; -import org.eclipse.tractusx.edc.iam.ssi.miw.rule.SsiCredentialIssuerValidationRule; -import org.eclipse.tractusx.edc.iam.ssi.miw.rule.SsiCredentialSubjectIdValidationRule; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; - -import static org.eclipse.tractusx.edc.iam.ssi.spi.SsiConstants.SSI_TOKEN_CONTEXT; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.ArgumentMatchers.isA; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -@ExtendWith(DependencyInjectionExtension.class) -public class SsiMiwValidationRuleExtensionTest { - - private final TokenValidationRulesRegistry registry = mock(TokenValidationRulesRegistry.class); - private final SsiMiwConfiguration cfg = mock(SsiMiwConfiguration.class); - - @BeforeEach - void setup(ServiceExtensionContext context) { - context.registerService(SsiMiwConfiguration.class, cfg); - context.registerService(TokenValidationRulesRegistry.class, registry); - } - - @Test - void initialize(ServiceExtensionContext context, SsiMiwValidationRuleExtension extension) { - when(cfg.getAuthorityIssuer()).thenReturn("issuer"); - - extension.initialize(context); - verify(registry).addRule(eq(SSI_TOKEN_CONTEXT), isA(SsiCredentialSubjectIdValidationRule.class)); - verify(registry).addRule(eq(SSI_TOKEN_CONTEXT), isA(SsiCredentialIssuerValidationRule.class)); - - verify(cfg).getAuthorityIssuer(); - } - -} diff --git a/edc-extensions/ssi/ssi-miw-credential-client/src/test/java/org/eclipse/tractusx/edc/iam/ssi/miw/api/MiwApiClientImplTest.java b/edc-extensions/ssi/ssi-miw-credential-client/src/test/java/org/eclipse/tractusx/edc/iam/ssi/miw/api/MiwApiClientImplTest.java deleted file mode 100644 index 71b747e56..000000000 --- a/edc-extensions/ssi/ssi-miw-credential-client/src/test/java/org/eclipse/tractusx/edc/iam/ssi/miw/api/MiwApiClientImplTest.java +++ /dev/null @@ -1,301 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.iam.ssi.miw.api; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.ObjectMapper; -import okhttp3.Interceptor; -import okhttp3.MediaType; -import okhttp3.Protocol; -import okhttp3.Request; -import okhttp3.Response; -import okhttp3.ResponseBody; -import okio.Buffer; -import org.eclipse.edc.spi.iam.TokenRepresentation; -import org.eclipse.edc.spi.monitor.Monitor; -import org.eclipse.edc.spi.result.Result; -import org.eclipse.tractusx.edc.iam.ssi.miw.oauth2.MiwOauth2Client; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.mockito.invocation.InvocationOnMock; - -import java.io.IOException; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Optional; -import java.util.Set; -import java.util.function.Consumer; - -import static java.lang.String.format; -import static org.assertj.core.api.Assertions.assertThat; -import static org.eclipse.http.client.testfixtures.HttpTestUtils.testHttpClient; -import static org.eclipse.tractusx.edc.iam.ssi.miw.api.MiwApiClientImpl.CREDENTIAL_PATH; -import static org.eclipse.tractusx.edc.iam.ssi.miw.api.MiwApiClientImpl.HOLDER_IDENTIFIER; -import static org.eclipse.tractusx.edc.iam.ssi.miw.api.MiwApiClientImpl.PRESENTATIONS_PATH; -import static org.eclipse.tractusx.edc.iam.ssi.miw.api.MiwApiClientImpl.PRESENTATIONS_VALIDATION_PATH; -import static org.eclipse.tractusx.edc.iam.ssi.miw.api.MiwApiClientImpl.VERIFIABLE_CREDENTIALS; -import static org.eclipse.tractusx.edc.iam.ssi.miw.api.MiwApiClientImpl.VP_FIELD; -import static org.mockito.ArgumentMatchers.contains; -import static org.mockito.ArgumentMatchers.isA; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -public class MiwApiClientImplTest { - - static final String BASE_URL = "http://localhost:8080"; - private final Consumer emptyAcceptor = (r) -> { - }; - Interceptor interceptor = mock(Interceptor.class); - MiwApiClientImpl client; - Monitor monitor = mock(Monitor.class); - MiwOauth2Client oauth2Client = mock(MiwOauth2Client.class); - ObjectMapper mapper = new ObjectMapper(); - String participantId = "participantId"; - String authorityId = "authorityId"; - - @BeforeEach - void setup() { - client = new MiwApiClientImpl(testHttpClient(interceptor), BASE_URL, oauth2Client, participantId, authorityId, mapper, monitor); - } - - @Test - void getCredentials() throws IOException { - - var credentialType = "test"; - - var response = Map.of("content", List.of(Map.of("id", "test"))); - var expectedUrl = format(BASE_URL + CREDENTIAL_PATH + "?issuerIdentifier=%s&type=%s", authorityId, credentialType); - - Consumer requestAcceptor = (request) -> { - assertThat(request.url().url().toString()).isEqualTo(expectedUrl); - }; - - when(interceptor.intercept(isA(Interceptor.Chain.class))) - .thenAnswer(invocation -> createResponse(200, invocation, requestAcceptor, response)); - - when(oauth2Client.obtainRequestToken()).thenReturn(Result.success(TokenRepresentation.Builder.newInstance().token("testToken").build())); - - var result = client.getCredentials(Set.of("test")); - - assertThat(result).isNotNull().matches(Result::succeeded) - .extracting(Result::getContent) - .asList().hasSize(1); - } - - @Test - void getCredentials_fails_whenMiwFails() throws IOException { - - when(interceptor.intercept(isA(Interceptor.Chain.class))) - .thenAnswer(invocation -> createResponse(500, invocation)); - - when(oauth2Client.obtainRequestToken()).thenReturn(Result.success(TokenRepresentation.Builder.newInstance().token("testToken").build())); - - var result = client.getCredentials(Set.of("test")); - - assertThat(result).isNotNull().matches(Result::failed); - } - - @Test - void getCredentials_fails_whenTokenRequestFails() { - - when(oauth2Client.obtainRequestToken()).thenReturn(Result.failure("Token fetch failure")); - - var result = client.getCredentials(Set.of("test")); - - assertThat(result).isNotNull().matches(Result::failed); - } - - @Test - void createPresentation() throws IOException { - var audience = "audience"; - var response = Map.of("vp", Map.of()); - var expectedUrl = format(BASE_URL + PRESENTATIONS_PATH + "?asJwt=true&audience=%s", audience); - - Consumer requestAcceptor = (request) -> { - var expectedBody = Map.of(HOLDER_IDENTIFIER, participantId, VERIFIABLE_CREDENTIALS, List.of()); - var body = getBody(request, new TypeReference>() { - }); - - assertThat(body).containsAllEntriesOf(expectedBody); - - assertThat(request.url().url().toString()).isEqualTo(expectedUrl); - }; - - when(interceptor.intercept(isA(Interceptor.Chain.class))) - .thenAnswer(invocation -> createResponse(200, invocation, requestAcceptor, response)); - - when(oauth2Client.obtainRequestToken()).thenReturn(Result.success(TokenRepresentation.Builder.newInstance().token("testToken").build())); - - var result = client.createPresentation(List.of(), audience); - - assertThat(result).isNotNull().matches(Result::succeeded); - } - - @Test - void createPresentation_fails_whenMiwFails() throws IOException { - - when(interceptor.intercept(isA(Interceptor.Chain.class))) - .thenAnswer(invocation -> createResponse(500, invocation, emptyAcceptor, "Request Failed")); - - when(oauth2Client.obtainRequestToken()).thenReturn(Result.success(TokenRepresentation.Builder.newInstance().token("testToken").build())); - - var result = client.createPresentation(List.of(), "audience"); - - assertThat(result).isNotNull().matches(Result::failed); - - verify(monitor).severe(contains("Request Failed")); - } - - @Test - void createPresentation_fails_whenTokenRequestFails() { - - when(oauth2Client.obtainRequestToken()).thenReturn(Result.failure("Token fetch failure")); - - var result = client.createPresentation(List.of(), "audience"); - - assertThat(result).isNotNull().matches(Result::failed); - } - - @Test - void verifyPresentation() throws IOException { - var jwt = "jwt"; - var verifyRequest = Map.of(VP_FIELD, jwt); - var audience = "audience"; - var expectedUrl = format(BASE_URL + PRESENTATIONS_VALIDATION_PATH + "?asJwt=true&audience=%s", audience); - - Consumer requestAcceptor = (request) -> { - - var body = getBody(request, new TypeReference>() { - }); - - assertThat(body).containsAllEntriesOf(verifyRequest); - assertThat(request.url().url().toString()).isEqualTo(expectedUrl); - }; - var verifyResponse = Map.of("valid", true); - - when(interceptor.intercept(isA(Interceptor.Chain.class))) - .thenAnswer(invocation -> createResponse(200, invocation, requestAcceptor, verifyResponse)); - - when(oauth2Client.obtainRequestToken()).thenReturn(Result.success(TokenRepresentation.Builder.newInstance().token("testToken").build())); - - var result = client.verifyPresentation(jwt, "audience"); - - assertThat(result).isNotNull().matches(Result::succeeded); - } - - @Test - void verifyPresentation_fails_whenNotVerified() throws IOException { - var jwt = "jwt"; - var verifyRequest = Map.of(VP_FIELD, jwt); - var audience = "audience"; - var expectedUrl = format(BASE_URL + PRESENTATIONS_VALIDATION_PATH + "?asJwt=true&audience=%s", audience); - - Consumer requestAcceptor = (request) -> { - - var body = getBody(request, new TypeReference>() { - }); - - assertThat(body).containsAllEntriesOf(verifyRequest); - assertThat(request.url().url().toString()).isEqualTo(expectedUrl); - }; - var verifyResponse = Map.of("valid", false); - - when(interceptor.intercept(isA(Interceptor.Chain.class))) - .thenAnswer(invocation -> createResponse(200, invocation, requestAcceptor, verifyResponse)); - - when(oauth2Client.obtainRequestToken()).thenReturn(Result.success(TokenRepresentation.Builder.newInstance().token("testToken").build())); - - var result = client.verifyPresentation(jwt, "audience"); - - assertThat(result).isNotNull().matches(Result::failed); - } - - @Test - void verifyPresentation_fails_whenMiwFails() throws IOException { - - when(interceptor.intercept(isA(Interceptor.Chain.class))) - .thenAnswer(invocation -> createResponse(500, invocation)); - - when(oauth2Client.obtainRequestToken()).thenReturn(Result.success(TokenRepresentation.Builder.newInstance().token("testToken").build())); - - var result = client.verifyPresentation("jwt", "audience"); - - assertThat(result).isNotNull().matches(Result::failed); - } - - @Test - void verifyPresentation_fails_whenTokenRequestFails() throws IOException { - - when(oauth2Client.obtainRequestToken()).thenReturn(Result.failure("Token fetch failure")); - - var result = client.verifyPresentation("jwt", "audience"); - - assertThat(result).isNotNull().matches(Result::failed); - } - - - private Response createResponse(int code, InvocationOnMock invocation) { - return createResponse(code, invocation, (req) -> { - }, null); - } - - private Response createResponse(int code, InvocationOnMock invocation, Object body) { - return createResponse(code, invocation, (req) -> { - }, body); - } - - - private Response createResponse(int code, InvocationOnMock invocation, Consumer consumer, Object body) { - var bodyString = Optional.ofNullable(body).map(this::toJson).orElse(""); - var request = getRequest(invocation); - consumer.accept(request); - return new Response.Builder() - .protocol(Protocol.HTTP_1_1) - .request(request) - .code(code) - .message("") - .body(ResponseBody.create(bodyString, MediaType.parse("application/json"))) - .build(); - } - - private String toJson(Object body) { - try { - return mapper.writeValueAsString(body); - } catch (JsonProcessingException e) { - throw new RuntimeException(e); - } - } - - private T getBody(Request request, TypeReference typeReference) { - try (var buffer = new Buffer()) { - Objects.requireNonNull(request.body()).writeTo(buffer); - return mapper.readValue(buffer.inputStream(), typeReference); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - private Request getRequest(InvocationOnMock invocation) { - return invocation.getArgument(0, Interceptor.Chain.class).request(); - } -} diff --git a/edc-extensions/ssi/ssi-miw-credential-client/src/test/java/org/eclipse/tractusx/edc/iam/ssi/miw/credentials/SsiMiwCredentialClientTest.java b/edc-extensions/ssi/ssi-miw-credential-client/src/test/java/org/eclipse/tractusx/edc/iam/ssi/miw/credentials/SsiMiwCredentialClientTest.java deleted file mode 100644 index 37725dbe3..000000000 --- a/edc-extensions/ssi/ssi-miw-credential-client/src/test/java/org/eclipse/tractusx/edc/iam/ssi/miw/credentials/SsiMiwCredentialClientTest.java +++ /dev/null @@ -1,157 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.iam.ssi.miw.credentials; - -import com.nimbusds.jose.JOSEException; -import com.nimbusds.jose.JWSAlgorithm; -import com.nimbusds.jose.JWSHeader; -import com.nimbusds.jose.crypto.RSASSASigner; -import com.nimbusds.jose.jwk.KeyUse; -import com.nimbusds.jose.jwk.RSAKey; -import com.nimbusds.jose.jwk.gen.RSAKeyGenerator; -import com.nimbusds.jwt.JWTClaimsSet; -import com.nimbusds.jwt.SignedJWT; -import jakarta.json.Json; -import org.eclipse.edc.jsonld.spi.JsonLd; -import org.eclipse.edc.spi.iam.TokenParameters; -import org.eclipse.edc.spi.iam.TokenRepresentation; -import org.eclipse.edc.spi.monitor.Monitor; -import org.eclipse.edc.spi.result.Result; -import org.eclipse.tractusx.edc.iam.ssi.miw.api.MiwApiClient; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import java.security.PrivateKey; -import java.time.Instant; -import java.util.Date; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.UUID; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.eclipse.edc.jwt.spi.JwtRegisteredClaimNames.AUDIENCE; -import static org.eclipse.edc.jwt.spi.JwtRegisteredClaimNames.SCOPE; -import static org.eclipse.tractusx.edc.iam.ssi.miw.api.MiwApiClient.VP; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoInteractions; -import static org.mockito.Mockito.when; - -public class SsiMiwCredentialClientTest { - - private final String audience = "audience"; - SsiMiwCredentialClient credentialClient; - MiwApiClient apiClient = mock(MiwApiClient.class); - JsonLd jsonLdService = mock(JsonLd.class); - - Monitor monitor = mock(Monitor.class); - private RSAKey key; - - @BeforeEach - void setup() throws JOSEException { - credentialClient = new SsiMiwCredentialClient(apiClient, jsonLdService, monitor); - key = testKey(); - } - - @Test - void validate_success() throws JOSEException { - var claims = createClaims(Instant.now()); - var jwt = createJwt(UUID.randomUUID().toString(), claims, key.toPrivateKey()); - when(apiClient.verifyPresentation(jwt, audience)).thenReturn(Result.success()); - when(jsonLdService.expand(any())).thenReturn(Result.success(Json.createObjectBuilder().build())); - - var result = credentialClient.validate(TokenRepresentation.Builder.newInstance().token(jwt).build()); - - assertThat(result).isNotNull().matches(Result::succeeded); - verify(apiClient).verifyPresentation(jwt, audience); - } - - @Test - void validate_success_whenClientFails() throws JOSEException { - var claims = createClaims(Instant.now()); - var jwt = createJwt(UUID.randomUUID().toString(), claims, key.toPrivateKey()); - when(apiClient.verifyPresentation(jwt, audience)).thenReturn(Result.failure("fail")); - when(jsonLdService.expand(any())).thenReturn(Result.success(Json.createObjectBuilder().build())); - - var result = credentialClient.validate(TokenRepresentation.Builder.newInstance().token(jwt).build()); - - assertThat(result).isNotNull().matches(Result::failed); - verify(apiClient).verifyPresentation(jwt, audience); - } - - @Test - void validate_fail_whenInvalidToken() throws JOSEException { - - var result = credentialClient.validate(TokenRepresentation.Builder.newInstance().token("invalid").build()); - - assertThat(result).isNotNull().matches(Result::failed); - verifyNoInteractions(apiClient); - } - - @Test - void obtainCredentials_success() { - - var jwt = "serialized"; - Map credential = Map.of(); - Map presentation = Map.of(VP, jwt); - - var credentials = List.of(credential); - - when(apiClient.getCredentials(Set.of())).thenReturn(Result.success(credentials)); - when(apiClient.createPresentation(credentials, audience)).thenReturn(Result.success(presentation)); - var result = credentialClient.obtainClientCredentials(TokenParameters.Builder.newInstance().claims(AUDIENCE, audience).claims(SCOPE, "").build()); - - assertThat(result).isNotNull() - .extracting(Result::getContent) - .extracting(TokenRepresentation::getToken) - .isEqualTo(jwt); - - verify(apiClient).getCredentials(Set.of()); - } - - private JWTClaimsSet createClaims(Instant exp) { - return new JWTClaimsSet.Builder() - .claim("foo", "bar") - .claim(VP, Map.of()) - .audience(audience) - .expirationTime(Date.from(exp)) - .build(); - } - - private String createJwt(String publicKeyId, JWTClaimsSet claimsSet, PrivateKey pk) { - var header = new JWSHeader.Builder(JWSAlgorithm.RS256).keyID(publicKeyId).build(); - try { - SignedJWT jwt = new SignedJWT(header, claimsSet); - jwt.sign(new RSASSASigner(pk)); - return jwt.serialize(); - } catch (JOSEException e) { - throw new AssertionError(e); - } - } - - private RSAKey testKey() throws JOSEException { - return new RSAKeyGenerator(2048) - .keyUse(KeyUse.SIGNATURE) // indicate the intended use of the key - .keyID(UUID.randomUUID().toString()) // give the key a unique ID - .generate(); - } -} diff --git a/edc-extensions/ssi/ssi-miw-credential-client/src/test/java/org/eclipse/tractusx/edc/iam/ssi/miw/oauth2/MiwOauth2ClientImplTest.java b/edc-extensions/ssi/ssi-miw-credential-client/src/test/java/org/eclipse/tractusx/edc/iam/ssi/miw/oauth2/MiwOauth2ClientImplTest.java deleted file mode 100644 index 4444edcea..000000000 --- a/edc-extensions/ssi/ssi-miw-credential-client/src/test/java/org/eclipse/tractusx/edc/iam/ssi/miw/oauth2/MiwOauth2ClientImplTest.java +++ /dev/null @@ -1,82 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.iam.ssi.miw.oauth2; - -import org.eclipse.edc.iam.oauth2.spi.client.Oauth2Client; -import org.eclipse.edc.iam.oauth2.spi.client.SharedSecretOauth2CredentialsRequest; -import org.eclipse.edc.spi.iam.TokenRepresentation; -import org.eclipse.edc.spi.result.Result; -import org.junit.jupiter.api.Test; -import org.mockito.ArgumentCaptor; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -public class MiwOauth2ClientImplTest { - - Oauth2Client oauth2Client = mock(Oauth2Client.class); - - @Test - void obtainRequestToken() { - var config = MiwOauth2ClientConfiguration.Builder.newInstance() - .tokenUrl("http://localhost:8081/token") - .clientId("client_id") - .scope("scope") - .clientSecret("client_secret") - .build(); - - var tokenRepresentation = TokenRepresentation.Builder.newInstance().token("token").build(); - when(oauth2Client.requestToken(any())).thenReturn(Result.success(tokenRepresentation)); - var client = new MiwOauth2ClientImpl(oauth2Client, config); - - var response = client.obtainRequestToken(); - assertThat(response).isNotNull().extracting(Result::getContent).isEqualTo(tokenRepresentation); - - var captor = ArgumentCaptor.forClass(SharedSecretOauth2CredentialsRequest.class); - verify(oauth2Client).requestToken(captor.capture()); - - var request = captor.getValue(); - - assertThat(request.getClientId()).isEqualTo(config.getClientId()); - assertThat(request.getClientSecret()).isEqualTo(config.getClientSecret()); - assertThat(request.getScope()).isEqualTo(config.getScope()); - assertThat(request.getUrl()).isEqualTo(config.getTokenUrl()); - - } - - @Test - void obtainRequestToken_failed() { - var config = MiwOauth2ClientConfiguration.Builder.newInstance() - .tokenUrl("http://localhost:8081/token") - .clientId("client_id") - .scope("scope") - .clientSecret("client_secret") - .build(); - - when(oauth2Client.requestToken(any())).thenReturn(Result.failure("failure")); - var client = new MiwOauth2ClientImpl(oauth2Client, config); - - var response = client.obtainRequestToken(); - assertThat(response).isNotNull().matches(Result::failed); - } -} diff --git a/edc-extensions/ssi/ssi-miw-credential-client/src/test/java/org/eclipse/tractusx/edc/iam/ssi/miw/rule/SsiCredentialIssuerValidationRuleTest.java b/edc-extensions/ssi/ssi-miw-credential-client/src/test/java/org/eclipse/tractusx/edc/iam/ssi/miw/rule/SsiCredentialIssuerValidationRuleTest.java deleted file mode 100644 index 22dbf4dcf..000000000 --- a/edc-extensions/ssi/ssi-miw-credential-client/src/test/java/org/eclipse/tractusx/edc/iam/ssi/miw/rule/SsiCredentialIssuerValidationRuleTest.java +++ /dev/null @@ -1,65 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.iam.ssi.miw.rule; - -import com.fasterxml.jackson.core.JsonProcessingException; -import jakarta.json.JsonObject; -import org.eclipse.edc.spi.iam.ClaimToken; -import org.eclipse.edc.spi.monitor.Monitor; -import org.eclipse.tractusx.edc.iam.ssi.spi.jsonld.SummaryContext; -import org.junit.jupiter.api.Test; - -import java.util.Map; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.eclipse.tractusx.edc.iam.ssi.spi.jsonld.CredentialsNamespaces.CX_SUMMARY_NS_V1; -import static org.eclipse.tractusx.edc.iam.ssi.spi.jsonld.CredentialsNamespaces.VP_PROPERTY; -import static org.eclipse.tractusx.edc.iam.ssi.spi.jsonld.JsonLdTextFixtures.createObjectMapper; -import static org.eclipse.tractusx.edc.iam.ssi.spi.jsonld.JsonLdTextFixtures.expand; -import static org.eclipse.tractusx.edc.iam.ssi.spi.jsonld.SummaryCredential.SUMMARY_VP; -import static org.mockito.Mockito.mock; - -public class SsiCredentialIssuerValidationRuleTest { - - static final Map CONTEXT_CACHE = Map.of(CX_SUMMARY_NS_V1, SummaryContext.SUMMARY_CONTEXT); - - SsiCredentialIssuerValidationRule validationRule; - - @Test - void checkRule() throws JsonProcessingException { - validationRule = new SsiCredentialIssuerValidationRule("did:web:issuer-example.com", mock(Monitor.class)); - var vp = expand(createObjectMapper().readValue(SUMMARY_VP, JsonObject.class), CONTEXT_CACHE); - var claimToken = ClaimToken.Builder.newInstance().claim(VP_PROPERTY, vp).build(); - var result = validationRule.checkRule(claimToken, Map.of()); - - assertThat(result.succeeded()).isTrue(); - } - - - @Test - void checkRule_shouldFail_whenIssuerIsWrong() throws JsonProcessingException { - validationRule = new SsiCredentialIssuerValidationRule("issuer", mock(Monitor.class)); - var vp = expand(createObjectMapper().readValue(SUMMARY_VP, JsonObject.class), CONTEXT_CACHE); - var claimToken = ClaimToken.Builder.newInstance().claim(VP_PROPERTY, vp).build(); - var result = validationRule.checkRule(claimToken, Map.of()); - - assertThat(result.succeeded()).isFalse(); - } -} diff --git a/edc-extensions/ssi/ssi-miw-credential-client/src/test/java/org/eclipse/tractusx/edc/iam/ssi/miw/rule/SsiCredentialSubjectIdValidationRuleTest.java b/edc-extensions/ssi/ssi-miw-credential-client/src/test/java/org/eclipse/tractusx/edc/iam/ssi/miw/rule/SsiCredentialSubjectIdValidationRuleTest.java deleted file mode 100644 index 19d001e02..000000000 --- a/edc-extensions/ssi/ssi-miw-credential-client/src/test/java/org/eclipse/tractusx/edc/iam/ssi/miw/rule/SsiCredentialSubjectIdValidationRuleTest.java +++ /dev/null @@ -1,82 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.iam.ssi.miw.rule; - -import com.fasterxml.jackson.core.JsonProcessingException; -import jakarta.json.JsonObject; -import org.eclipse.edc.spi.iam.ClaimToken; -import org.eclipse.edc.spi.monitor.Monitor; -import org.eclipse.tractusx.edc.iam.ssi.spi.jsonld.SummaryContext; -import org.junit.jupiter.api.Test; - -import java.util.Map; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.eclipse.edc.jwt.spi.JwtRegisteredClaimNames.ISSUER; -import static org.eclipse.tractusx.edc.iam.ssi.spi.jsonld.CredentialsNamespaces.CX_SUMMARY_NS_V1; -import static org.eclipse.tractusx.edc.iam.ssi.spi.jsonld.CredentialsNamespaces.VP_PROPERTY; -import static org.eclipse.tractusx.edc.iam.ssi.spi.jsonld.JsonLdTextFixtures.createObjectMapper; -import static org.eclipse.tractusx.edc.iam.ssi.spi.jsonld.JsonLdTextFixtures.expand; -import static org.eclipse.tractusx.edc.iam.ssi.spi.jsonld.SummaryCredential.SUMMARY_VP; -import static org.mockito.Mockito.mock; - -public class SsiCredentialSubjectIdValidationRuleTest { - - static final Map CONTEXT_CACHE = Map.of(CX_SUMMARY_NS_V1, SummaryContext.SUMMARY_CONTEXT); - - private final SsiCredentialSubjectIdValidationRule validationRule = new SsiCredentialSubjectIdValidationRule(mock(Monitor.class)); - - @Test - void checkRule() throws JsonProcessingException { - var vp = expand(createObjectMapper().readValue(SUMMARY_VP, JsonObject.class), CONTEXT_CACHE); - var claimToken = ClaimToken.Builder.newInstance() - .claim(VP_PROPERTY, vp) - .claim(ISSUER, "did:web:example.com").build(); - - var result = validationRule.checkRule(claimToken, Map.of()); - - assertThat(result.succeeded()).isTrue(); - } - - @Test - void checkRule_shouldFail_whenIssuerMissingInClaims() throws JsonProcessingException { - var vp = expand(createObjectMapper().readValue(SUMMARY_VP, JsonObject.class), CONTEXT_CACHE); - var claimToken = ClaimToken.Builder.newInstance() - .claim(VP_PROPERTY, vp) - .build(); - - var result = validationRule.checkRule(claimToken, Map.of()); - - assertThat(result.succeeded()).isFalse(); - } - - @Test - void checkRule_shouldFail_whenWrongIssuerInClaims() throws JsonProcessingException { - var vp = expand(createObjectMapper().readValue(SUMMARY_VP, JsonObject.class), CONTEXT_CACHE); - var claimToken = ClaimToken.Builder.newInstance() - .claim(VP_PROPERTY, vp) - .claim(ISSUER, "wrong").build(); - - var result = validationRule.checkRule(claimToken, Map.of()); - - assertThat(result.succeeded()).isFalse(); - } - -} diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/MiwParticipant.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/MiwParticipant.java deleted file mode 100644 index b20aa6e08..000000000 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/MiwParticipant.java +++ /dev/null @@ -1,82 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.lifecycle; - -import org.eclipse.tractusx.edc.tests.participant.TractusxParticipantBase; - -import java.util.HashMap; -import java.util.Map; -import java.util.Objects; - -/** - * Extension of {@link TractusxParticipantBase} with MIW specific configuration - */ -public class MiwParticipant extends TractusxParticipantBase { - - protected String miwUri; - protected String oauth2Uri; - - public Map getConfiguration() { - var baseConfiguration = super.getConfiguration(); - - var ssiConfiguration = new HashMap() { - { - put("tx.ssi.miw.url", miwUri); - put("tx.ssi.oauth.token.url", oauth2Uri); - put("tx.ssi.oauth.client.id", "miw_private_client"); - put("tx.ssi.oauth.client.secret.alias", "client_secret_alias"); - put("tx.ssi.miw.authority.id", "BPNL000000000000"); - put("tx.ssi.miw.authority.issuer", "did:web:localhost%3A8000:BPNL000000000000"); - put("tx.vault.seed.secrets", "client_secret_alias:miw_private_client"); - put("tx.ssi.endpoint.audience", getProtocolEndpoint().getUrl().toString()); - } - }; - ssiConfiguration.putAll(baseConfiguration); - return ssiConfiguration; - } - - public static class Builder extends TractusxParticipantBase.Builder { - - protected Builder() { - super(new MiwParticipant()); - } - - public static Builder newInstance() { - return new Builder(); - } - - public Builder miwUri(String miwUri) { - participant.miwUri = miwUri; - return self(); - } - - public Builder oauth2Uri(String oauth2Uri) { - participant.oauth2Uri = oauth2Uri; - return self(); - } - - @Override - public MiwParticipant build() { - super.build(); - Objects.requireNonNull(participant.miwUri, "MIW URI should not be null"); - return participant; - } - } -} diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tag/MiwIntegrationTest.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tag/MiwIntegrationTest.java deleted file mode 100644 index c3db731a4..000000000 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tag/MiwIntegrationTest.java +++ /dev/null @@ -1,36 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.tag; - -import org.eclipse.edc.junit.annotations.IntegrationTest; -import org.junit.jupiter.api.Tag; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -@Target({ ElementType.TYPE }) -@Retention(RetentionPolicy.RUNTIME) -@IntegrationTest -@Tag("MiwIntegrationTest") -public @interface MiwIntegrationTest { -} - diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/catalog/MiwSsiCatalogTest.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/catalog/MiwSsiCatalogTest.java deleted file mode 100644 index 01f2e7233..000000000 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/catalog/MiwSsiCatalogTest.java +++ /dev/null @@ -1,88 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.tests.catalog; - -import org.eclipse.tractusx.edc.lifecycle.MiwParticipant; -import org.eclipse.tractusx.edc.lifecycle.ParticipantRuntime; -import org.eclipse.tractusx.edc.tag.MiwIntegrationTest; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.RegisterExtension; - -import java.util.Map; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.eclipse.edc.test.system.utils.PolicyFixtures.noConstraintPolicy; -import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.TX_NAMESPACE; -import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.SOKRATES_BPN; -import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.SOKRATES_NAME; -import static org.eclipse.tractusx.edc.tests.helpers.CatalogHelperFunctions.getDatasetAssetId; -import static org.eclipse.tractusx.edc.tests.helpers.PolicyHelperFunctions.frameworkPolicy; - -@MiwIntegrationTest -public class MiwSsiCatalogTest { - - protected static final String MIW_SOKRATES_URL = "http://localhost:8000"; - protected static final String OAUTH_TOKEN_URL = "http://localhost:8080/realms/miw_test/protocol/openid-connect/token"; - protected static final MiwParticipant SOKRATES = MiwParticipant.Builder.newInstance() - .name(SOKRATES_NAME) - .id(SOKRATES_BPN) - .miwUri(MIW_SOKRATES_URL) - .oauth2Uri(OAUTH_TOKEN_URL) - .build(); - - - @RegisterExtension - protected static final ParticipantRuntime SOKRATES_RUNTIME = new ParticipantRuntime( - ":edc-tests:runtime:runtime-memory-ssi", - SOKRATES.getName(), - SOKRATES.getConfiguration() - ); - - @Test - @DisplayName("Verify that Sokrates receives only the offers he is permitted to") - void requestCatalog_fulfillsPolicy_shouldReturnOffer() { - // arrange - SOKRATES.createAsset("test-asset"); - SOKRATES.createAsset("test-asset-1"); - - var bpnAccessPolicy = frameworkPolicy(Map.of(TX_NAMESPACE + "BPN", "active")); - var dismantlerAccessPolicy = frameworkPolicy(Map.of(TX_NAMESPACE + "Dismantler", "active")); - - var bpnAccessId = SOKRATES.createPolicyDefinition(bpnAccessPolicy); - var contractPolicyId = SOKRATES.createPolicyDefinition(noConstraintPolicy()); - var dismantlerAccessPolicyId = SOKRATES.createPolicyDefinition(dismantlerAccessPolicy); - - SOKRATES.createContractDefinition("test-asset", "test-def", bpnAccessId, contractPolicyId); - SOKRATES.createContractDefinition("test-asset-1", "test-def-2", dismantlerAccessPolicyId, contractPolicyId); - - // act - var catalog = SOKRATES.getCatalogDatasets(SOKRATES); - - // assert - assertThat(catalog).isNotEmpty() - .hasSize(1) - .allSatisfy(co -> { - assertThat(getDatasetAssetId(co)).isEqualTo("test-asset"); - }); - - } - -} diff --git a/edc-tests/edc-controlplane/ssi-summarycred-tests/build.gradle.kts b/edc-tests/edc-controlplane/ssi-summarycred-tests/build.gradle.kts deleted file mode 100644 index c5d8a88f3..000000000 --- a/edc-tests/edc-controlplane/ssi-summarycred-tests/build.gradle.kts +++ /dev/null @@ -1,41 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -plugins { - `java-library` - `java-test-fixtures` -} - -dependencies { - testImplementation(testFixtures(project(":edc-tests:edc-controlplane:fixtures"))) - testImplementation(libs.edc.ih.spi) - testImplementation(libs.edc.ih.spi.store) - testImplementation(libs.edc.junit) - testImplementation(libs.edc.core.token) - // 3rd party libs - testImplementation(libs.netty.mockserver) - testImplementation(libs.restAssured) - testImplementation(libs.awaitility) - testImplementation(libs.okhttp.mockwebserver) -} - -// do not publish -edcBuild { - publish.set(false) -} diff --git a/edc-tests/edc-controlplane/ssi-summarycred-tests/src/test/java/org/eclipse/tractusx/edc/tests/KeycloakDispatcher.java b/edc-tests/edc-controlplane/ssi-summarycred-tests/src/test/java/org/eclipse/tractusx/edc/tests/KeycloakDispatcher.java deleted file mode 100644 index ded5051be..000000000 --- a/edc-tests/edc-controlplane/ssi-summarycred-tests/src/test/java/org/eclipse/tractusx/edc/tests/KeycloakDispatcher.java +++ /dev/null @@ -1,56 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.tests; - -import okhttp3.mockwebserver.Dispatcher; -import okhttp3.mockwebserver.MockResponse; -import okhttp3.mockwebserver.RecordedRequest; -import org.eclipse.edc.spi.types.TypeManager; -import org.jetbrains.annotations.NotNull; - -import java.util.Map; - -public class KeycloakDispatcher extends Dispatcher { - - private static final TypeManager MAPPER = new TypeManager(); - private final String path; - - public KeycloakDispatcher(String path) { - this.path = path; - } - - public KeycloakDispatcher() { - this("/"); - } - - @NotNull - @Override - public MockResponse dispatch(@NotNull RecordedRequest recordedRequest) { - if (recordedRequest.getPath().split("\\?")[0].equals(path)) { - return createTokenResponse(); - } - return new MockResponse().setResponseCode(404); - } - - private MockResponse createTokenResponse() { - return new MockResponse().setBody(MAPPER.writeValueAsString(Map.of("access_token", "token"))); - } - -} diff --git a/edc-tests/edc-controlplane/ssi-summarycred-tests/src/test/java/org/eclipse/tractusx/edc/tests/MiwDispatcher.java b/edc-tests/edc-controlplane/ssi-summarycred-tests/src/test/java/org/eclipse/tractusx/edc/tests/MiwDispatcher.java deleted file mode 100644 index 2371ea3e9..000000000 --- a/edc-tests/edc-controlplane/ssi-summarycred-tests/src/test/java/org/eclipse/tractusx/edc/tests/MiwDispatcher.java +++ /dev/null @@ -1,142 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.tests; - -import com.fasterxml.jackson.core.type.TypeReference; -import com.nimbusds.jose.JOSEException; -import com.nimbusds.jose.JWSAlgorithm; -import com.nimbusds.jose.JWSHeader; -import com.nimbusds.jose.crypto.RSASSASigner; -import com.nimbusds.jose.jwk.KeyUse; -import com.nimbusds.jose.jwk.RSAKey; -import com.nimbusds.jose.jwk.gen.RSAKeyGenerator; -import com.nimbusds.jwt.JWTClaimsSet; -import com.nimbusds.jwt.SignedJWT; -import okhttp3.mockwebserver.Dispatcher; -import okhttp3.mockwebserver.MockResponse; -import okhttp3.mockwebserver.RecordedRequest; -import org.eclipse.edc.spi.types.TypeManager; -import org.jetbrains.annotations.NotNull; - -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.security.PrivateKey; -import java.time.Instant; -import java.util.Date; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.UUID; - -import static java.lang.String.format; - -public class MiwDispatcher extends Dispatcher { - - private static final TypeManager MAPPER = new TypeManager(); - - private final String audience; - - private final String credentialSubjectId; - - private final Map summaryVc; - - public MiwDispatcher(String bpn, String vcFile, String credentialSubjectId, String audience) { - this.audience = audience; - this.credentialSubjectId = credentialSubjectId; - var json = format(readVcContent(vcFile), bpn); - summaryVc = MAPPER.readValue(json, new TypeReference<>() { - }); - } - - @NotNull - @Override - public MockResponse dispatch(@NotNull RecordedRequest recordedRequest) { - return switch (recordedRequest.getPath().split("\\?")[0]) { - case "/api/credentials" -> credentialResponse(); - case "/api/presentations" -> presentationResponse(); - case "/api/presentations/validation" -> presentationValidationResponse(); - default -> new MockResponse().setResponseCode(404); - }; - } - - private String readVcContent(String vcFile) { - var classloader = Thread.currentThread().getContextClassLoader(); - - try (var jsonStream = classloader.getResourceAsStream(vcFile)) { - Objects.requireNonNull(jsonStream); - return new String(jsonStream.readAllBytes(), StandardCharsets.UTF_8); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - private MockResponse credentialResponse() { - return new MockResponse().setBody(MAPPER.writeValueAsString(Map.of("content", List.of(summaryVc)))); - } - - private MockResponse presentationResponse() { - try { - var jwt = createJwt(UUID.randomUUID().toString(), createClaims(Instant.now(), createVerifiablePresentationClaim()), testKey().toPrivateKey()); - return new MockResponse().setBody(MAPPER.writeValueAsString(Map.of("vp", jwt))); - } catch (JOSEException e) { - throw new RuntimeException(e); - } - } - - private Map createVerifiablePresentationClaim() { - var ctx = List.of("https://www.w3.org/2018/credentials/v1"); - var type = List.of("VerifiablePresentation"); - return Map.of( - "@context", ctx, - "type", type, - "verifiableCredential", List.of(summaryVc)); - } - - private MockResponse presentationValidationResponse() { - return new MockResponse().setBody(MAPPER.writeValueAsString(Map.of("valid", true))); - } - - private JWTClaimsSet createClaims(Instant exp, Map presentation) { - return new JWTClaimsSet.Builder() - .issuer(credentialSubjectId) - .claim("vp", presentation) - .audience(audience) - .expirationTime(Date.from(exp)) - .build(); - } - - private String createJwt(String publicKeyId, JWTClaimsSet claimsSet, PrivateKey pk) { - var header = new JWSHeader.Builder(JWSAlgorithm.RS256).keyID(publicKeyId).build(); - try { - SignedJWT jwt = new SignedJWT(header, claimsSet); - jwt.sign(new RSASSASigner(pk)); - return jwt.serialize(); - } catch (JOSEException e) { - throw new AssertionError(e); - } - } - - private RSAKey testKey() throws JOSEException { - return new RSAKeyGenerator(2048) - .keyUse(KeyUse.SIGNATURE) // indicate the intended use of the key - .keyID(UUID.randomUUID().toString()) // give the key a unique ID - .generate(); - } -} diff --git a/edc-tests/edc-controlplane/ssi-summarycred-tests/src/test/java/org/eclipse/tractusx/edc/tests/MiwParticipant.java b/edc-tests/edc-controlplane/ssi-summarycred-tests/src/test/java/org/eclipse/tractusx/edc/tests/MiwParticipant.java deleted file mode 100644 index ebe238996..000000000 --- a/edc-tests/edc-controlplane/ssi-summarycred-tests/src/test/java/org/eclipse/tractusx/edc/tests/MiwParticipant.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -package org.eclipse.tractusx.edc.tests; - -import org.eclipse.tractusx.edc.tests.participant.TractusxParticipantBase; - -import java.net.URI; -import java.util.HashMap; -import java.util.Map; - -import static org.eclipse.edc.util.io.Ports.getFreePort; - -public class MiwParticipant extends TractusxParticipantBase { - - private final URI miwUri = URI.create("http://localhost:" + getFreePort()); - private final URI oauthTokenUri = URI.create("http://localhost:" + getFreePort()); - - /** - * Returns the SSI configuration - */ - public Map getConfiguration() { - return new HashMap<>(super.getConfiguration()) { - { - put("tx.ssi.miw.url", miwUri.toString()); - put("tx.ssi.oauth.token.url", oauthTokenUri.toString()); - put("tx.ssi.oauth.client.id", "client_id"); - put("tx.ssi.oauth.client.secret.alias", "client_secret_alias"); - put("tx.ssi.miw.authority.id", "authorityId"); - put("tx.ssi.miw.authority.issuer", "did:web:example.com"); - put("tx.vault.seed.secrets", "client_secret_alias:client_secret"); - put("tx.ssi.endpoint.audience", getProtocolEndpoint().getUrl().toString()); - } - }; - } - - /** - * Returns the MIW endpoint - */ - public URI miwEndpoint() { - return miwUri; - } - - /** - * Returns the OAuth2 token endpoint - */ - public URI authTokenEndpoint() { - return oauthTokenUri; - } - - public static class Builder extends TractusxParticipantBase.Builder { - - protected Builder() { - super(new MiwParticipant()); - } - - public static Builder newInstance() { - return new Builder(); - } - - @Override - public MiwParticipant build() { - super.build(); - return participant; - } - } -} \ No newline at end of file diff --git a/edc-tests/edc-controlplane/ssi-summarycred-tests/src/test/java/org/eclipse/tractusx/edc/tests/negotiation/AbstractContractNegotiateTest.java b/edc-tests/edc-controlplane/ssi-summarycred-tests/src/test/java/org/eclipse/tractusx/edc/tests/negotiation/AbstractContractNegotiateTest.java deleted file mode 100644 index 2ea74e8f9..000000000 --- a/edc-tests/edc-controlplane/ssi-summarycred-tests/src/test/java/org/eclipse/tractusx/edc/tests/negotiation/AbstractContractNegotiateTest.java +++ /dev/null @@ -1,90 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.tests.negotiation; - -import org.eclipse.edc.connector.contract.spi.types.negotiation.ContractNegotiationStates; -import org.eclipse.edc.policy.model.Operator; -import org.eclipse.tractusx.edc.tests.MiwParticipant; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; - -import java.util.Map; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.awaitility.Awaitility.await; -import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.TX_NAMESPACE; -import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.PLATO_BPN; -import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.PLATO_NAME; -import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.SOKRATES_BPN; -import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.SOKRATES_NAME; -import static org.eclipse.tractusx.edc.tests.helpers.PolicyHelperFunctions.bpnGroupPolicy; -import static org.eclipse.tractusx.edc.tests.helpers.PolicyHelperFunctions.frameworkPolicy; -import static org.eclipse.tractusx.edc.tests.participant.TractusxParticipantBase.ASYNC_POLL_INTERVAL; -import static org.eclipse.tractusx.edc.tests.participant.TractusxParticipantBase.ASYNC_TIMEOUT; - -public abstract class AbstractContractNegotiateTest { - - protected static final MiwParticipant SOKRATES = MiwParticipant.Builder.newInstance() - .name(SOKRATES_NAME) - .id(SOKRATES_BPN) - .build(); - - protected static final MiwParticipant PLATO = MiwParticipant.Builder.newInstance() - .name(PLATO_NAME) - .id(PLATO_BPN) - .build(); - - - @Test - @DisplayName("Verify contract negotiation fails with wrong policy") - void contractNegotiation_shouldFail_whenPolicyEvaluationFails() { - var assetId = "api-asset-1"; - var authCodeHeaderName = "test-authkey"; - var authCode = "test-authcode"; - - Map dataAddress = Map.of( - "name", "transfer-test", - "baseUrl", "http://testurl", - "type", "HttpData", - "contentType", "application/json", - "authKey", authCodeHeaderName, - "authCode", authCode - ); - - PLATO.createAsset(assetId, Map.of(), dataAddress); - - PLATO.storeBusinessPartner(SOKRATES.getBpn(), "allowed-group"); - var accessPolicyId = PLATO.createPolicyDefinition(bpnGroupPolicy(Operator.NEQ, "forbidden-group")); - var contractPolicyId = PLATO.createPolicyDefinition(frameworkPolicy(Map.of(TX_NAMESPACE + "Dismantler", "active"))); - PLATO.createContractDefinition(assetId, "def-1", accessPolicyId, contractPolicyId); - - var negotiationId = SOKRATES.initContractNegotiation(PLATO, assetId); - - // wait for the failed contract negotiation - await().pollInterval(ASYNC_POLL_INTERVAL) - .atMost(ASYNC_TIMEOUT) - .untilAsserted(() -> { - var negotiationState = SOKRATES.getContractNegotiationState(negotiationId); - assertThat(negotiationState).isEqualTo(ContractNegotiationStates.TERMINATED.toString()); - }); - } - - -} diff --git a/edc-tests/edc-controlplane/ssi-summarycred-tests/src/test/java/org/eclipse/tractusx/edc/tests/negotiation/SsiContractNegotiationInMemoryTest.java b/edc-tests/edc-controlplane/ssi-summarycred-tests/src/test/java/org/eclipse/tractusx/edc/tests/negotiation/SsiContractNegotiationInMemoryTest.java deleted file mode 100644 index baf01089d..000000000 --- a/edc-tests/edc-controlplane/ssi-summarycred-tests/src/test/java/org/eclipse/tractusx/edc/tests/negotiation/SsiContractNegotiationInMemoryTest.java +++ /dev/null @@ -1,93 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.tests.negotiation; - -import okhttp3.mockwebserver.MockWebServer; -import org.eclipse.edc.junit.annotations.EndToEndTest; -import org.eclipse.tractusx.edc.tests.KeycloakDispatcher; -import org.eclipse.tractusx.edc.tests.MiwDispatcher; -import org.eclipse.tractusx.edc.tests.runtimes.ParticipantRuntime; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.extension.RegisterExtension; - -import java.io.IOException; - -import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.PLATO_BPN; -import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.SOKRATES_BPN; - - -@EndToEndTest -public class SsiContractNegotiationInMemoryTest extends AbstractContractNegotiateTest { - public static final String SUMMARY_VC_TEMPLATE = "summary-vc-no-dismantler.json"; - - @RegisterExtension - protected static final ParticipantRuntime PLATO_RUNTIME = new ParticipantRuntime( - ":edc-tests:runtime:runtime-memory-ssi", - PLATO.getName(), - PLATO.getBpn(), - PLATO.getConfiguration() - ); - - @RegisterExtension - protected static final ParticipantRuntime SOKRATES_RUNTIME = new ParticipantRuntime( - ":edc-tests:runtime:runtime-memory-ssi", - SOKRATES.getName(), - SOKRATES.getBpn(), - SOKRATES.getConfiguration() - ); - private static MockWebServer miwSokratesServer; - private static MockWebServer miwPlatoServer; - private static MockWebServer sokratesOauthServer; - private static MockWebServer platoOauthServer; - - - @BeforeAll - static void setup() throws IOException { - miwSokratesServer = new MockWebServer(); - miwPlatoServer = new MockWebServer(); - sokratesOauthServer = new MockWebServer(); - platoOauthServer = new MockWebServer(); - - - var credentialSubjectId = "did:web:example.com"; - - miwSokratesServer.start(SOKRATES.miwEndpoint().getPort()); - miwSokratesServer.setDispatcher(new MiwDispatcher(SOKRATES_BPN, SUMMARY_VC_TEMPLATE, credentialSubjectId, PLATO.getProtocolEndpoint().getUrl().toString())); - - miwPlatoServer.start(PLATO.miwEndpoint().getPort()); - miwPlatoServer.setDispatcher(new MiwDispatcher(PLATO_BPN, SUMMARY_VC_TEMPLATE, credentialSubjectId, SOKRATES.getProtocolEndpoint().getUrl().toString())); - - sokratesOauthServer.start(SOKRATES.authTokenEndpoint().getPort()); - sokratesOauthServer.setDispatcher(new KeycloakDispatcher()); - - platoOauthServer.start(PLATO.authTokenEndpoint().getPort()); - platoOauthServer.setDispatcher(new KeycloakDispatcher()); - } - - @AfterAll - static void teardown() throws IOException { - miwSokratesServer.shutdown(); - miwPlatoServer.shutdown(); - sokratesOauthServer.shutdown(); - platoOauthServer.shutdown(); - - } -} diff --git a/edc-tests/edc-controlplane/ssi-summarycred-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/SsiHttpConsumerPullWithProxyInMemoryTest.java b/edc-tests/edc-controlplane/ssi-summarycred-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/SsiHttpConsumerPullWithProxyInMemoryTest.java deleted file mode 100644 index 4335630a2..000000000 --- a/edc-tests/edc-controlplane/ssi-summarycred-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/SsiHttpConsumerPullWithProxyInMemoryTest.java +++ /dev/null @@ -1,121 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.tests.transfer; - -import jakarta.json.JsonObject; -import okhttp3.mockwebserver.MockWebServer; -import org.eclipse.edc.junit.annotations.EndToEndTest; -import org.eclipse.tractusx.edc.tests.KeycloakDispatcher; -import org.eclipse.tractusx.edc.tests.MiwDispatcher; -import org.eclipse.tractusx.edc.tests.MiwParticipant; -import org.eclipse.tractusx.edc.tests.participant.TractusxParticipantBase; -import org.eclipse.tractusx.edc.tests.runtimes.ParticipantRuntime; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.extension.RegisterExtension; - -import java.io.IOException; -import java.util.Map; - -import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.TX_NAMESPACE; -import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.PLATO_BPN; -import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.PLATO_NAME; -import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.SOKRATES_BPN; -import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.SOKRATES_NAME; -import static org.eclipse.tractusx.edc.tests.helpers.PolicyHelperFunctions.frameworkPolicy; - - -@EndToEndTest -public class SsiHttpConsumerPullWithProxyInMemoryTest extends HttpConsumerPullBaseTest { - - public static final String SUMMARY_VC_TEMPLATE = "summary-vc.json"; - protected static final MiwParticipant SOKRATES = MiwParticipant.Builder.newInstance() - .name(SOKRATES_NAME) - .id(SOKRATES_BPN) - .build(); - protected static final MiwParticipant PLATO = MiwParticipant.Builder.newInstance() - .name(PLATO_NAME) - .id(PLATO_BPN) - .build(); - @RegisterExtension - protected static final ParticipantRuntime SOKRATES_RUNTIME = new ParticipantRuntime( - ":edc-tests:runtime:runtime-memory-ssi", - SOKRATES.getName(), - SOKRATES.getBpn(), - SOKRATES.getConfiguration() - ); - @RegisterExtension - protected static final ParticipantRuntime PLATO_RUNTIME = new ParticipantRuntime( - ":edc-tests:runtime:runtime-memory-ssi", - PLATO.getName(), - PLATO.getBpn(), - PLATO.getConfiguration() - ); - - private static MockWebServer sokratesOauthServer; - private static MockWebServer platoOauthServer; - private static MockWebServer miwPlatoServer; - private static MockWebServer miwSokratesServer; - - @BeforeAll - static void prepare() throws IOException { - miwSokratesServer = new MockWebServer(); - miwPlatoServer = new MockWebServer(); - sokratesOauthServer = new MockWebServer(); - platoOauthServer = new MockWebServer(); - - var credentialSubjectId = "did:web:example.com"; - - miwSokratesServer.start(SOKRATES.miwEndpoint().getPort()); - miwSokratesServer.setDispatcher(new MiwDispatcher(SOKRATES_BPN, SUMMARY_VC_TEMPLATE, credentialSubjectId, PLATO.getProtocolEndpoint().getUrl().toString())); - - miwPlatoServer.start(PLATO.miwEndpoint().getPort()); - miwPlatoServer.setDispatcher(new MiwDispatcher(PLATO_BPN, SUMMARY_VC_TEMPLATE, credentialSubjectId, SOKRATES.getProtocolEndpoint().getUrl().toString())); - - sokratesOauthServer.start(SOKRATES.authTokenEndpoint().getPort()); - sokratesOauthServer.setDispatcher(new KeycloakDispatcher()); - - platoOauthServer.start(PLATO.authTokenEndpoint().getPort()); - platoOauthServer.setDispatcher(new KeycloakDispatcher()); - } - - @AfterAll - static void unwind() throws IOException { - miwSokratesServer.shutdown(); - miwPlatoServer.shutdown(); - sokratesOauthServer.shutdown(); - platoOauthServer.shutdown(); - } - - @Override - public TractusxParticipantBase plato() { - return PLATO; - } - - @Override - public TractusxParticipantBase sokrates() { - return SOKRATES; - } - - @Override - protected JsonObject createAccessPolicy(String bpn) { - return frameworkPolicy(Map.of(TX_NAMESPACE + "Dismantler", "active")); - } -} diff --git a/edc-tests/edc-controlplane/ssi-summarycred-tests/src/test/resources/framework-policy.json b/edc-tests/edc-controlplane/ssi-summarycred-tests/src/test/resources/framework-policy.json deleted file mode 100644 index 321aecbe5..000000000 --- a/edc-tests/edc-controlplane/ssi-summarycred-tests/src/test/resources/framework-policy.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "@context": [ - "https://w3id.org/edc/v0.0.1", - "https://w3id.org/tractusx/edc/v0.0.1", - "http://www.w3.org/ns/odrl.jsonld" - ], - "@type": "PolicyDefinitionRequest", - "@id": "${POLICY_ID}", - "policy": { - "@type": "Set", - "permission": [ - { - "action": "use", - "constraint": [ - { - "leftOperand": "${FRAMEWORK_CREDENTIAL}", - "operator": "eq", - "rightOperand": "active" - } - ] - } - ] - } -} diff --git a/edc-tests/edc-controlplane/ssi-summarycred-tests/src/test/resources/summary-vc-no-dismantler.json b/edc-tests/edc-controlplane/ssi-summarycred-tests/src/test/resources/summary-vc-no-dismantler.json deleted file mode 100644 index 750648f04..000000000 --- a/edc-tests/edc-controlplane/ssi-summarycred-tests/src/test/resources/summary-vc-no-dismantler.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "@context": [ - "https://www.w3.org/2018/credentials/v1", - "https://w3id.org/2023/catenax/credentials/summary/v1" - ], - "id": "urn:uuid:12345678-1234-1234-1234-123456789abc", - "type": [ - "VerifiableCredential", - "SummaryCredential" - ], - "issuer": "did:web:example.com", - "issuanceDate": "2023-06-02T12:00:00Z", - "expirationDate": "2022-06-16T18:56:59Z", - "credentialSubject": { - "id": "did:web:example.com", - "holderIdentifier": "%s", - "type": "Summary-List", - "name": "CX-Credentials", - "items": [ - "MembershipCredential", - "PcfCredential", - "SustainabilityCredential", - "QualityCredential", - "TraceabilityCredential", - "BehaviorTwinCredential", - "BpnCredential" - ], - "contractTemplates": "https://public.catena-x.org/contracts/" - }, - "proof": { - "type": "Ed25519Signature2018", - "created": "2023-06-02T12:00:00Z", - "proofPurpose": "assertionMethod", - "verificationMethod": "did:web:example.com#key-1", - "jws": "xxxx" - } -} \ No newline at end of file diff --git a/edc-tests/edc-controlplane/ssi-summarycred-tests/src/test/resources/summary-vc.json b/edc-tests/edc-controlplane/ssi-summarycred-tests/src/test/resources/summary-vc.json deleted file mode 100644 index 01c640a70..000000000 --- a/edc-tests/edc-controlplane/ssi-summarycred-tests/src/test/resources/summary-vc.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "@context": [ - "https://www.w3.org/2018/credentials/v1", - "https://w3id.org/2023/catenax/credentials/summary/v1" - ], - "id": "urn:uuid:12345678-1234-1234-1234-123456789abc", - "type": [ - "VerifiableCredential", - "SummaryCredential" - ], - "issuer": "did:web:example.com", - "issuanceDate": "2023-06-02T12:00:00Z", - "expirationDate": "2022-06-16T18:56:59Z", - "credentialSubject": { - "id": "did:web:example.com", - "holderIdentifier": "%s", - "type": "Summary-List", - "name": "CX-Credentials", - "items": [ - "MembershipCredential", - "DismantlerCredential", - "PcfCredential", - "SustainabilityCredential", - "QualityCredential", - "TraceabilityCredential", - "BehaviorTwinCredential", - "BpnCredential" - ], - "contractTemplates": "https://public.catena-x.org/contracts/" - }, - "proof": { - "type": "Ed25519Signature2018", - "created": "2023-06-02T12:00:00Z", - "proofPurpose": "assertionMethod", - "verificationMethod": "did:web:example.com#key-1", - "jws": "xxxx" - } -} \ No newline at end of file diff --git a/edc-tests/edc-dataplane/edc-dataplane-tokenrefresh-tests/build.gradle.kts b/edc-tests/edc-dataplane/edc-dataplane-tokenrefresh-tests/build.gradle.kts index 2f813d5fa..cd5b341a9 100644 --- a/edc-tests/edc-dataplane/edc-dataplane-tokenrefresh-tests/build.gradle.kts +++ b/edc-tests/edc-dataplane/edc-dataplane-tokenrefresh-tests/build.gradle.kts @@ -28,6 +28,7 @@ dependencies { testImplementation(libs.edc.junit) testImplementation(libs.restAssured) + testImplementation(project(":spi:core-spi")) testImplementation(libs.edc.dpf.http) testImplementation(libs.edc.spi.identity.did) testImplementation(libs.nimbus.jwt) diff --git a/edc-tests/edc-dataplane/edc-dataplane-tokenrefresh-tests/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/e2e/DataPlaneTokenRefreshEndToEndTest.java b/edc-tests/edc-dataplane/edc-dataplane-tokenrefresh-tests/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/e2e/DataPlaneTokenRefreshEndToEndTest.java index 23f2629e4..8bb6cf0eb 100644 --- a/edc-tests/edc-dataplane/edc-dataplane-tokenrefresh-tests/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/e2e/DataPlaneTokenRefreshEndToEndTest.java +++ b/edc-tests/edc-dataplane/edc-dataplane-tokenrefresh-tests/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/e2e/DataPlaneTokenRefreshEndToEndTest.java @@ -42,6 +42,9 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.EmptySource; +import org.junit.jupiter.params.provider.NullSource; import java.net.URI; import java.text.ParseException; @@ -50,6 +53,7 @@ import static org.apache.http.HttpHeaders.AUTHORIZATION; import static org.assertj.core.api.Assertions.assertThat; import static org.eclipse.edc.spi.CoreConstants.EDC_NAMESPACE; +import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.TX_AUTH_NS; import static org.hamcrest.Matchers.containsString; @@ -64,7 +68,8 @@ public class DataPlaneTokenRefreshEndToEndTest { protected static final EdcRuntimeExtension DATAPLANE_RUNTIME = new EdcRuntimeExtension( ":edc-tests:runtime:dataplane-cloud", "Token-Refresh-Dataplane", - with(RUNTIME_CONFIG.baseConfig(), Map.of("edc.transfer.proxy.token.signer.privatekey.alias", PROVIDER_KEY_ID)) + with(RUNTIME_CONFIG.baseConfig(), Map.of("edc.transfer.proxy.token.signer.privatekey.alias", PROVIDER_KEY_ID, + "edc.transfer.proxy.token.verifier.publickey.alias", PROVIDER_KEY_ID)) ); private ECKey providerKey; private ECKey consumerKey; @@ -95,6 +100,7 @@ void setup() throws JOSEException { }); } + @DisplayName("Refresh token success") @Test void refresh_success() { @@ -105,8 +111,8 @@ void refresh_success() { var edr = authorizationService.createEndpointDataReference(createStartMessage("test-process-id", CONSUMER_DID)) .orElseThrow(f -> new AssertionError(f.getFailureDetail())); - var refreshToken = edr.getStringProperty("refreshToken"); - var accessToken = edr.getStringProperty("authorization"); + var refreshToken = edr.getStringProperty(TX_AUTH_NS + "refreshToken"); + var accessToken = edr.getStringProperty(EDC_NAMESPACE + "authorization"); var authToken = createAuthToken(accessToken, consumerKey); var tokenResponse = RUNTIME_CONFIG.getRefreshApi().baseRequest() @@ -122,6 +128,79 @@ void refresh_success() { assertThat(tokenResponse).isNotNull(); } + @DisplayName("Refresh token is null or empty (missing)") + @ParameterizedTest + @NullSource + @EmptySource + void refresh_invalidRefreshToken(String invalidRefreshToken) { + // register generator and secrets + prepareDataplaneRuntime(); + + var authorizationService = DATAPLANE_RUNTIME.getService(DataPlaneAuthorizationService.class); + var edr = authorizationService.createEndpointDataReference(createStartMessage("test-process-id", CONSUMER_DID)) + .orElseThrow(f -> new AssertionError(f.getFailureDetail())); + + var refreshToken = edr.getStringProperty(TX_AUTH_NS + "refreshToken"); + var accessToken = edr.getStringProperty(EDC_NAMESPACE + "authorization"); + var authToken = createAuthToken(accessToken, consumerKey); + + RUNTIME_CONFIG.getRefreshApi().baseRequest() + .queryParam("grant_type", "refresh_token") + .queryParam("refresh_token", invalidRefreshToken) + .header(AUTHORIZATION, "Bearer " + authToken) + .post("/token") + .then() + .log().ifError() + .statusCode(400); + } + + @DisplayName("The Authorization header is empty") + @Test + void refresh_emptyAuthHeader() { + // register generator and secrets + prepareDataplaneRuntime(); + + var authorizationService = DATAPLANE_RUNTIME.getService(DataPlaneAuthorizationService.class); + var edr = authorizationService.createEndpointDataReference(createStartMessage("test-process-id", CONSUMER_DID)) + .orElseThrow(f -> new AssertionError(f.getFailureDetail())); + + var refreshToken = edr.getStringProperty(TX_AUTH_NS + "refreshToken"); + var accessToken = edr.getStringProperty(EDC_NAMESPACE + "authorization"); + + // auth header is empty + RUNTIME_CONFIG.getRefreshApi().baseRequest() + .queryParam("grant_type", "refresh_token") + .queryParam("refresh_token", refreshToken) + .header(AUTHORIZATION, "") + .post("/token") + .then() + .log().ifError() + .statusCode(401); + } + + @DisplayName("The Authorization header is missing") + @Test + void refresh_missingAuthHeader() { + // register generator and secrets + prepareDataplaneRuntime(); + + var authorizationService = DATAPLANE_RUNTIME.getService(DataPlaneAuthorizationService.class); + var edr = authorizationService.createEndpointDataReference(createStartMessage("test-process-id", CONSUMER_DID)) + .orElseThrow(f -> new AssertionError(f.getFailureDetail())); + + var refreshToken = edr.getStringProperty(TX_AUTH_NS + "refreshToken"); + var accessToken = edr.getStringProperty(EDC_NAMESPACE + "authorization"); + + // auth header is empty + RUNTIME_CONFIG.getRefreshApi().baseRequest() + .queryParam("grant_type", "refresh_token") + .queryParam("refresh_token", refreshToken) + .post("/token") + .then() + .log().ifError() + .statusCode(401); + } + @DisplayName("The sign key of the authentication token is different from the public key from the DID") @Test void refresh_spoofedAuthToken() throws JOSEException { @@ -131,8 +210,8 @@ void refresh_spoofedAuthToken() throws JOSEException { var edr = authorizationService.createEndpointDataReference(createStartMessage("test-process-id", CONSUMER_DID)) .orElseThrow(f -> new AssertionError(f.getFailureDetail())); - var refreshToken = edr.getStringProperty("refreshToken"); - var accessToken = edr.getStringProperty("authorization"); + var refreshToken = edr.getStringProperty(TX_AUTH_NS + "refreshToken"); + var accessToken = edr.getStringProperty(EDC_NAMESPACE + "authorization"); var spoofedKey = new ECKeyGenerator(Curve.P_256).keyID(CONSUMER_KEY_ID).generate(); var authTokenWithSpoofedKey = createAuthToken(accessToken, spoofedKey); @@ -157,7 +236,7 @@ void refresh_withWrongRefreshToken() { .orElseThrow(f -> new AssertionError(f.getFailureDetail())); var refreshToken = "invalid_refresh_token"; - var accessToken = edr.getStringProperty("authorization"); + var accessToken = edr.getStringProperty(EDC_NAMESPACE + "authorization"); RUNTIME_CONFIG.getRefreshApi().baseRequest() .queryParam("grant_type", "refresh_token") @@ -171,7 +250,7 @@ void refresh_withWrongRefreshToken() { } - @DisplayName("The authentication token misses required claims: access_token") + @DisplayName("The authentication token misses required claims: token") @Test void refresh_invalidAuthenticationToken_missingAccessToken() { prepareDataplaneRuntime(); @@ -180,11 +259,11 @@ void refresh_invalidAuthenticationToken_missingAccessToken() { var edr = authorizationService.createEndpointDataReference(createStartMessage("test-process-id", CONSUMER_DID)) .orElseThrow(f -> new AssertionError(f.getFailureDetail())); - var refreshToken = edr.getStringProperty("refreshToken"); - var accessToken = edr.getStringProperty("authorization"); + var refreshToken = edr.getStringProperty(TX_AUTH_NS + "refreshToken"); + var accessToken = edr.getStringProperty(EDC_NAMESPACE + "authorization"); var claims = new JWTClaimsSet.Builder() - /* missing: .claim("access_token", accessToken)*/ + /* missing: .claim("token", accessToken)*/ .issuer(CONSUMER_DID) .subject(CONSUMER_DID) .audience("did:web:bob") @@ -200,7 +279,7 @@ void refresh_invalidAuthenticationToken_missingAccessToken() { .then() .log().ifValidationFails() .statusCode(401) - .body(containsString("Required claim 'access_token' not present on token.")); + .body(containsString("Required claim 'token' not present on token.")); } @DisplayName("The authentication token misses required claims: audience") @@ -212,11 +291,11 @@ void refresh_invalidAuthenticationToken_missingAudience() { var edr = authorizationService.createEndpointDataReference(createStartMessage("test-process-id", CONSUMER_DID)) .orElseThrow(f -> new AssertionError(f.getFailureDetail())); - var refreshToken = edr.getStringProperty("refreshToken"); - var accessToken = edr.getStringProperty("authorization"); + var refreshToken = edr.getStringProperty(TX_AUTH_NS + "refreshToken"); + var accessToken = edr.getStringProperty(EDC_NAMESPACE + "authorization"); var claims = new JWTClaimsSet.Builder() - .claim("access_token", accessToken) + .claim("token", accessToken) .issuer(CONSUMER_DID) .subject(CONSUMER_DID) /* missing: .audience("did:web:bob")*/ @@ -242,7 +321,7 @@ private void prepareDataplaneRuntime() { private String createAuthToken(String accessToken, ECKey signerKey) { var claims = new JWTClaimsSet.Builder() - .claim("access_token", accessToken) + .claim("token", accessToken) .issuer(CONSUMER_DID) .subject(CONSUMER_DID) .audience("did:web:bob") diff --git a/edc-tests/miw-tests/README.md b/edc-tests/miw-tests/README.md deleted file mode 100644 index f204147c3..000000000 --- a/edc-tests/miw-tests/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# E2E-Tests - -This module contains JUnit tests that spin up multiple runtimes in one JVM. diff --git a/edc-tests/miw-tests/build.gradle.kts b/edc-tests/miw-tests/build.gradle.kts deleted file mode 100644 index c721d0c53..000000000 --- a/edc-tests/miw-tests/build.gradle.kts +++ /dev/null @@ -1,64 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -plugins { - `java-library` -} - -dependencies { - testImplementation(project(":spi:edr-spi")) - testImplementation(project(":edc-extensions:edr:edr-api-v2")) - testImplementation(libs.okhttp.mockwebserver) - testImplementation(libs.restAssured) - testImplementation(libs.nimbus.jwt) - testImplementation(libs.postgres) - testImplementation(libs.awaitility) - testImplementation(libs.aws.s3) - testImplementation(libs.edc.spi.core) - testImplementation(libs.edc.junit) - testImplementation(libs.edc.spi.policy) - testImplementation(libs.edc.spi.contract) - testImplementation(libs.edc.core.api) - testImplementation(libs.edc.spi.catalog) - testImplementation(libs.edc.api.catalog) - testImplementation(libs.edc.api.contractnegotiation) - testImplementation(libs.edc.api.transferprocess) - testImplementation(libs.edc.spi.dataplane.selector) - testImplementation(libs.edc.ext.jsonld) - testImplementation(libs.edc.dsp) - testImplementation(libs.edc.lib.http) - testImplementation(libs.edc.lib.jsonld) - testImplementation(testFixtures(libs.edc.sql.core)) - - - testCompileOnly(project(":edc-tests:runtime:extensions")) - testCompileOnly(project(":edc-tests:runtime:runtime-memory")) - testCompileOnly(project(":edc-tests:runtime:runtime-memory-ssi")) - testCompileOnly(project(":edc-tests:runtime:runtime-postgresql")) - testImplementation(project(":edc-extensions:ssi:ssi-miw-credential-client")) - testImplementation(libs.edc.auth.oauth2.client) - - runtimeOnly(libs.tink) - -} - -// do not publish -edcBuild { - publish.set(false) -} diff --git a/edc-tests/miw-tests/src/test/java/org/eclipse/tractusx/edc/tag/MiwIntegrationTest.java b/edc-tests/miw-tests/src/test/java/org/eclipse/tractusx/edc/tag/MiwIntegrationTest.java deleted file mode 100644 index c3db731a4..000000000 --- a/edc-tests/miw-tests/src/test/java/org/eclipse/tractusx/edc/tag/MiwIntegrationTest.java +++ /dev/null @@ -1,36 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.tag; - -import org.eclipse.edc.junit.annotations.IntegrationTest; -import org.junit.jupiter.api.Tag; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -@Target({ ElementType.TYPE }) -@Retention(RetentionPolicy.RUNTIME) -@IntegrationTest -@Tag("MiwIntegrationTest") -public @interface MiwIntegrationTest { -} - diff --git a/edc-tests/miw-tests/src/test/java/org/eclipse/tractusx/edc/tests/miw/README.md b/edc-tests/miw-tests/src/test/java/org/eclipse/tractusx/edc/tests/miw/README.md deleted file mode 100644 index 339f93775..000000000 --- a/edc-tests/miw-tests/src/test/java/org/eclipse/tractusx/edc/tests/miw/README.md +++ /dev/null @@ -1,72 +0,0 @@ -# Function-testing the Managed-Identity-Wallet - -## Test setup - -As test subject we used a `docker-compose.yml` file located in `src/main/resources/`. From that directory, simply -execute `docker compose up --wait`, and then, once everything is started, -run `docker exec -i resources-postgres-1 /opt/seed.sh` to seed test data. - -## Test suite description - -### `t0001` Request and verify a VP - -### `t0002` Wrong audience - -This test asserts, that a verification request is rejected, if the wrong `audience=` query parameter is supplied. -The `audience` query parameter must match the `aud` claim inside the token. - -### `t0003` A self-signed VP token is rejected - -This test asserts, that submitting a self-generated JWT (containing the original VP claim) should be rejected. The MIW -should only accept JWTs that were signed by the requestor's private key, which is hosted in MIW. Currently, no JWT -validation is done. - -A rejected flow would be: - -- request VC from MIW -- request VP from MIW, returned in JWT format -- decode the JWT, unpack the payload -- generate a random keypair -- re-use the original claims (payload) and header -- sign with the random keypair - -### `t0004` A bogus JWT is rejected - -This test is an amendment to `t0003` in that it not only forges the JWT itself, but the JWT does not contain any of the -required claims. For example, it does not even contain a `vp` claim, so there is no VerifiablePresentation. - -### `t0005` A forged VC proof (altered JWS) is rejected - -This test asserts, that an altered (and potentially even malformed) `jws` proof is rejected. This test specifically -targets the use of JsonWebSignature2020, because there the `proof` object contains a `jws` field. - -Altering that `jws` value, here by replacing all "a" with "X" should cause the MIW to reject the verification request. - -### `t0006` A tampered VC proof (changed document) is rejected - -Similar to `t0005`, which alters the proof itself, this test alters the document, for which the proof was created. -Technically this should alter the document hash, so the proof becomes invalid, and the MIW should reject the request. - -### `t0007` Forged `iss` claim is rejected - -In this test we construct an impersonation attack, which assumes there are at least two participants in the MIW. -Participant 1 requests a VP, decodes it, replaces the `iss` claim with the ID of Participant 2 and - using again a -randomly generated keypair - signs this forged VP token. This effectively gives any participant the possibility to mount -impersonation attacks. - -> Note that Participant 2 was created in the database using the `src/test/resources/db.sh` script - -### `t0008` Invalid `iss` claim is rejected (non-existent user) - -This test attempts to have a JWT verified where the `iss` claim cannot be resolved. - -### `t0009` Invalid `iss` claim is rejected (not did:web format) - -This test asserts that a malformed `iss` claim is rejected by MIW. Specifically, the claim must be in `did:web:....` -format. - -### `t0010` An altered `aud` claim is rejected - -Similar to `t0007`, and in extension to `t0003`, this test asserts, that a verification request is rejected by MIW, if -the `aud` claim inside the JWT token was replaced. -> Note that this attack is only possible if the integrity and provenance of the JWT is not checked, see `t0003`. diff --git a/edc-tests/miw-tests/src/test/java/org/eclipse/tractusx/edc/tests/miw/WalletTest.java b/edc-tests/miw-tests/src/test/java/org/eclipse/tractusx/edc/tests/miw/WalletTest.java deleted file mode 100644 index a93595301..000000000 --- a/edc-tests/miw-tests/src/test/java/org/eclipse/tractusx/edc/tests/miw/WalletTest.java +++ /dev/null @@ -1,395 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.tests.miw; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.nimbusds.jose.JOSEException; -import com.nimbusds.jose.JOSEObjectType; -import com.nimbusds.jose.JWSAlgorithm; -import com.nimbusds.jose.JWSHeader; -import com.nimbusds.jose.JWSObject; -import com.nimbusds.jose.crypto.Ed25519Signer; -import com.nimbusds.jose.jwk.Curve; -import com.nimbusds.jose.jwk.JWK; -import com.nimbusds.jose.jwk.KeyUse; -import com.nimbusds.jose.jwk.gen.OctetKeyPairGenerator; -import com.nimbusds.jwt.JWTClaimsSet; -import com.nimbusds.jwt.SignedJWT; -import dev.failsafe.RetryPolicy; -import jakarta.json.Json; -import okhttp3.OkHttpClient; -import org.eclipse.edc.iam.oauth2.client.Oauth2ClientImpl; -import org.eclipse.edc.jsonld.util.JacksonJsonLd; -import org.eclipse.edc.spi.monitor.Monitor; -import org.eclipse.edc.spi.types.TypeManager; -import org.eclipse.http.client.EdcHttpClientImpl; -import org.eclipse.tractusx.edc.iam.ssi.miw.api.MiwApiClient; -import org.eclipse.tractusx.edc.iam.ssi.miw.api.MiwApiClientImpl; -import org.eclipse.tractusx.edc.iam.ssi.miw.oauth2.MiwOauth2ClientConfiguration; -import org.eclipse.tractusx.edc.iam.ssi.miw.oauth2.MiwOauth2ClientImpl; -import org.eclipse.tractusx.edc.tag.MiwIntegrationTest; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; - -import java.text.ParseException; -import java.util.Date; -import java.util.Map; -import java.util.Set; -import java.util.UUID; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.spy; - -@MiwIntegrationTest -public class WalletTest { - - static final String MIW_SOKRATES_URL = "http://localhost:8000"; - static final String OAUTH_TOKEN_URL = "http://localhost:8080/realms/miw_test/protocol/openid-connect/token"; - private static final ObjectMapper OBJECT_MAPPER = JacksonJsonLd.createObjectMapper(); - private static final String OTHER_PARTICIPANTS_DID = "did:web:localhost%3A8000:BPNL000000000042"; - private final TypeReference> mapRef = new TypeReference<>() { - }; - private MiwApiClient client; - - @BeforeEach - void setup() { - - var monitor = mock(Monitor.class); - var httpClient = new EdcHttpClientImpl(new OkHttpClient.Builder().build(), RetryPolicy.ofDefaults(), monitor); - var config = MiwOauth2ClientConfiguration.Builder.newInstance() - .clientId("miw_private_client") - .clientSecret("miw_private_client") - .tokenUrl(OAUTH_TOKEN_URL) - .build(); - var oauth2baseClient = new Oauth2ClientImpl(httpClient, new TypeManager()); - - var auth2client = spy(new MiwOauth2ClientImpl(oauth2baseClient, config)); - - this.client = new MiwApiClientImpl(httpClient, MIW_SOKRATES_URL, auth2client, "miw_private_client", "BPNL000000000000", OBJECT_MAPPER, monitor); - } - - @Test - @DisplayName("t0001: Request VC, create a VP and verify") - void requestAndVerifyVp() { - var credentialsResult = client.getCredentials(Set.of("SummaryCredential")); - assertThat(credentialsResult.succeeded()).withFailMessage(credentialsResult::getFailureDetail).isTrue(); - assertThat(credentialsResult.getContent()).isNotEmpty(); - - var presentationResult = client.createPresentation(credentialsResult.getContent(), "test-audience"); - assertThat(presentationResult.succeeded()).isTrue(); - - var vp = presentationResult.getContent().get("vp").toString(); - var verifyResult = client.verifyPresentation(vp, "test-audience"); - - assertThat(verifyResult.succeeded()).describedAs("Should be able to verify its own VP: " + verifyResult.getFailureDetail()).isTrue(); - } - - @Test - @DisplayName("t0002: A wrong audience (passed to API) is rejected") - void verifyVp_withWrongAudience() { - var credentialsResult = client.getCredentials(Set.of("SummaryCredential")); - - var presentationResult = client.createPresentation(credentialsResult.getContent(), "test-audience"); - - var verifyResult = client.verifyPresentation(presentationResult.getContent().get("vp").toString(), "wrong-audience"); - - assertThat(verifyResult.failed()).describedAs("Should not be able to verify against a wrong audience").isTrue(); - } - - @Test - @DisplayName("t0003: A a spoofed/self-signed VP is rejected") - void verifyVp_spoofedVp() throws ParseException, JOSEException { - // obtain VC, create VP - var credentialsResult = client.getCredentials(Set.of("SummaryCredential")); - var presentationResult = client.createPresentation(credentialsResult.getContent(), "test-audience"); - - var vpToken = presentationResult.getContent().get("vp").toString(); - - // extract content, parse into JWSobject - var jwt = JWSObject.parse(vpToken); - - // create new JWS header - var header = createHeader(); - - // sign JWS with own key - var claimsSet = new JWTClaimsSet.Builder(); - jwt.getPayload().toJSONObject().forEach(claimsSet::claim); - var jwk = createJwkKeypair(); - - var ownJwt = new SignedJWT(header, claimsSet.build()); - ownJwt.sign(new Ed25519Signer(jwk.toOctetKeyPair())); - - // this should definitely return false!! - var result = client.verifyPresentation(ownJwt.serialize(), "test-audience"); - - assertThat(result.succeeded()).isFalse(); - } - - @Test - @DisplayName("t0004: A completely bogus JWT (without even a VP inside) is rejected") - void verifyVp_bogusTokenWithoutVp() throws JOSEException { - - // extract content, parse into JWSobject - // create new JWS header - var header = createHeader(); - - // generate completely arbitrary JWT claims - var claimsSet = new JWTClaimsSet.Builder(); - claimsSet.claim("aud", "test-audience") - .claim("iss", OTHER_PARTICIPANTS_DID); - var jwk = createJwkKeypair(); - - var ownJwt = new SignedJWT(header, claimsSet.build()); - ownJwt.sign(new Ed25519Signer(jwk.toOctetKeyPair())); - - // this should definitely return false!! - var result = client.verifyPresentation(ownJwt.serialize(), "test-audience"); - - assertThat(result.succeeded()).isFalse(); - } - - @Test - @DisplayName("t0005: A forged VC proof (altered JWS) is rejected") - void verifyVp_spoofedVpAndForgedJws() throws JsonProcessingException, ParseException, JOSEException { - // obtain VC, create VP - var credentialsResult = client.getCredentials(Set.of("SummaryCredential")); - var presentationResult = client.createPresentation(credentialsResult.getContent(), "test-audience"); - - var vpToken = presentationResult.getContent().get("vp").toString(); - // extract content, parse into JWSobject - var jwt = JWSObject.parse(vpToken); - - // create new JWS header - var header = createHeader(); - - // sign JWS with own key - var claimsSet = new JWTClaimsSet.Builder(); - - - var payloadJson = jwt.getPayload().toJSONObject(); - var jo = Json.createObjectBuilder(payloadJson).build(); - - // replace JWS inside the VC's proof object - var jws = jo.getJsonObject("vp").getJsonArray("verifiableCredential").getJsonObject(0).getJsonObject("proof").getString("jws"); - var invalidJws = jws.replace("a", "X"); - var tamperedJson = jo.toString().replace(jws, invalidJws); - var tamperedJsonObject = OBJECT_MAPPER.readValue(tamperedJson, mapRef); - tamperedJsonObject.forEach(claimsSet::claim); - var jwk = createJwkKeypair(); - - var forgedJwt = new SignedJWT(header, claimsSet.build()); - forgedJwt.sign(new Ed25519Signer(jwk.toOctetKeyPair())); - - // this should definitely return false!! - var result = client.verifyPresentation(forgedJwt.serialize(), "test-audience"); - - assertThat(result.succeeded()).withFailMessage("Verifying a forged VC proof (JWS) should not be possible!").isFalse(); - } - - @Test - @DisplayName("t0006: A tampered VC proof (changed holderIdentifier) is rejected") - void verifyVp_spoofedVpAndTamperedVc() throws JsonProcessingException, ParseException, JOSEException { - // obtain VC, create VP - var credentialsResult = client.getCredentials(Set.of("SummaryCredential")); - var presentationResult = client.createPresentation(credentialsResult.getContent(), "test-audience"); - - var vpToken = presentationResult.getContent().get("vp").toString(); - - // extract content, parse into JWSobject - var jwt = JWSObject.parse(vpToken); - - // create new JWS header - var header = createHeader(); - - // sign JWS with own key - var claimsSet = new JWTClaimsSet.Builder(); - - - var payloadJson = jwt.getPayload().toString(); - var tamperedPayload = payloadJson.replace("\"holderIdentifier\":\"BPNL000000000000\"", "\"holderIdentifier\":\"wrongHolderIdentifier\""); - var tamperedJsonObject = OBJECT_MAPPER.readValue(tamperedPayload, mapRef); - tamperedJsonObject.forEach(claimsSet::claim); - - var jwk = createJwkKeypair(); - - var forgedJwt = new SignedJWT(header, claimsSet.build()); - forgedJwt.sign(new Ed25519Signer(jwk.toOctetKeyPair())); - - // this should definitely return false!! - var result = client.verifyPresentation(forgedJwt.serialize(), "test-audience"); - - assertThat(result.succeeded()).withFailMessage("Verifying a tampered holderIdentifier should not be possible!").isFalse(); - } - - @Test - @DisplayName("t0007: An invalid 'iss' claim (use existing other issuer) is rejected") - void verifyVp_invalidIssuerClaim() throws ParseException, JOSEException { - var credentialsResult = client.getCredentials(Set.of("SummaryCredential")); - var presentationResult = client.createPresentation(credentialsResult.getContent(), "test-audience"); - - var vpToken = presentationResult.getContent().get("vp").toString(); - - // extract content, parse into JWSobject - var jwt = JWSObject.parse(vpToken); - - // create new JWS header - var header = createHeader(); - - // replace payload - var claimsSet = new JWTClaimsSet.Builder(); - - var vp = jwt.getPayload().toJSONObject(); - // change the iss claim - please check the src/test/resources/db.sh script, this additional participant is added there - vp.replace("iss", OTHER_PARTICIPANTS_DID); - - // create new VP token - vp.forEach(claimsSet::claim); - - var jwk = createJwkKeypair(); - var forgedJwt = new SignedJWT(header, claimsSet.build()); - forgedJwt.sign(new Ed25519Signer(jwk.toOctetKeyPair())); - - var result = client.verifyPresentation(forgedJwt.serialize(), "test-audience"); - - assertThat(result.succeeded()).withFailMessage("Altering the 'iss' claim (impersonation) should not be possible!").isFalse(); - } - - @Test - @DisplayName("t0008: An invalid 'iss' claim (non-existing issuer) is rejected") - void verifyVp_invalidIssuerClaim_notExists() throws ParseException, JOSEException { - var credentialsResult = client.getCredentials(Set.of("SummaryCredential")); - var presentationResult = client.createPresentation(credentialsResult.getContent(), "test-audience"); - - var vpToken = presentationResult.getContent().get("vp").toString(); - - // extract content, parse into JWSobject - var jwt = JWSObject.parse(vpToken); - - // create new JWS header - var header = createHeader(); - - // replace payload - var claimsSet = new JWTClaimsSet.Builder(); - - var vp = jwt.getPayload().toJSONObject(); - // change the iss claim - please check the src/test/resources/db.sh script, this additional participant is added there - vp.replace("iss", "did:web:someotherissuer"); - - // create new VP token - vp.forEach(claimsSet::claim); - - var jwk = createJwkKeypair(); - var forgedJwt = new SignedJWT(header, claimsSet.build()); - forgedJwt.sign(new Ed25519Signer(jwk.toOctetKeyPair())); - - var result = client.verifyPresentation(forgedJwt.serialize(), "test-audience"); - - assertThat(result.succeeded()).withFailMessage("Altering the 'iss' claim (impersonation) should not be possible!").isFalse(); - } - - @Test - @DisplayName("t0009: An invalid 'iss' claim (not in DID:web format) is rejected") - void verifyVp_invalidIssuerClaim_notExists_issNotDidWeb() throws ParseException, JOSEException { - var credentialsResult = client.getCredentials(Set.of("SummaryCredential")); - var presentationResult = client.createPresentation(credentialsResult.getContent(), "test-audience"); - - var vpToken = presentationResult.getContent().get("vp").toString(); - - // extract content, parse into JWSobject - var jwt = JWSObject.parse(vpToken); - - // create new JWS header - var header = createHeader(); - - // replace payload - var claimsSet = new JWTClaimsSet.Builder(); - - var vp = jwt.getPayload().toJSONObject(); - // change the iss claim - please check the src/test/resources/db.sh script, this additional participant is added there - vp.replace("iss", "this_isnt_even_didweb"); - - // create new VP token - vp.forEach(claimsSet::claim); - - var jwk = createJwkKeypair(); - var forgedJwt = new SignedJWT(header, claimsSet.build()); - forgedJwt.sign(new Ed25519Signer(jwk.toOctetKeyPair())); - - var result = client.verifyPresentation(forgedJwt.serialize(), "test-audience"); - - assertThat(result.succeeded()).withFailMessage("Altering the 'iss' claim (impersonation) should not be possible!").isFalse(); - } - - @Test - @DisplayName("t0010: An altered 'aud' claim is rejected") - void verifyVp_modifiedAudClaim() throws ParseException, JOSEException { - var credentialsResult = client.getCredentials(Set.of("SummaryCredential")); - var presentationResult = client.createPresentation(credentialsResult.getContent(), "test-audience"); - - var vpToken = presentationResult.getContent().get("vp").toString(); - - // extract content, parse into JWSobject - var jwt = JWSObject.parse(vpToken); - - // create new JWS header - var header = createHeader(); - - // replace payload - var claimsSet = new JWTClaimsSet.Builder(); - - var vp = jwt.getPayload().toJSONObject(); - // change the iss claim - vp.replace("aud", "some-other-audience"); - - // create new VP token - vp.forEach(claimsSet::claim); - - var jwk = createJwkKeypair(); - var forgedJwt = new SignedJWT(header, claimsSet.build()); - forgedJwt.sign(new Ed25519Signer(jwk.toOctetKeyPair())); - - var result = client.verifyPresentation(forgedJwt.serialize(), "some-other-audience"); - - assertThat(result.succeeded()).withFailMessage("Altering the 'aud' claim (replay attack) should not be possible!").isFalse(); - } - - private JWSHeader createHeader() { - return new JWSHeader.Builder(JWSAlgorithm.EdDSA) - .type(JOSEObjectType.JWT) - .keyID(UUID.randomUUID().toString()) - .build(); - } - - private JWK createJwkKeypair() { - try { - return new OctetKeyPairGenerator(Curve.Ed25519) - .keyUse(KeyUse.SIGNATURE) // indicate the intended use of the key (optional) - .keyID(UUID.randomUUID().toString()) // give the key a unique ID (optional) - .issueTime(new Date()) // issued-at timestamp (optional) - .generate(); - } catch (Exception e) { - throw new RuntimeException(e); - } - } -} diff --git a/edc-tests/miw-tests/src/test/resources/docker-environment/docker-compose.yaml b/edc-tests/miw-tests/src/test/resources/docker-environment/docker-compose.yaml deleted file mode 100644 index b89dc5729..000000000 --- a/edc-tests/miw-tests/src/test/resources/docker-environment/docker-compose.yaml +++ /dev/null @@ -1,92 +0,0 @@ -################################################################################# -# Copyright (c) 2021,2023 Contributors to the Eclipse Foundation -# -# See the NOTICE file(s) distributed with this work for additional -# information regarding copyright ownership. -# -# This program and the accompanying materials are made available under the -# terms of the Apache License, Version 2.0 which is available at -# https://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. -# -# SPDX-License-Identifier: Apache-2.0 -################################################################################# - - -version: '3' - -services: - miw: - image: tractusx/managed-identity-wallet:main - platform: linux/amd64 - container_name: miw - env_file: - - ../env-files/env.docker - ports: - - "8000:8000" - - "8090:8090" - - "5005:5005" - networks: - - miw-net - entrypoint: "java -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005 -jar miw-latest.jar" - depends_on: - postgres: - condition: service_started - keycloak: - condition: service_started - - postgres: - image: postgres:15.3-alpine3.18 - volumes: - - postgres_data:/var/lib/postgresql/data - - ./postgres/db.sh:/docker-entrypoint-initdb.d/init-database.sh - - ./postgres/seed.sh:/opt/seed.sh - env_file: - - ../env-files/env.docker - ports: - - "5432:5432" - networks: - - miw-net - healthcheck: - test: [ "CMD-SHELL", "pg_isready -U postgres" ] - interval: 5s - timeout: 30s - retries: 10 - - keycloak: - image: quay.io/keycloak/keycloak:21.1 - env_file: - - ../env-files/env.docker - environment: - DB_SCHEMA: public - command: - - start-dev - - --import-realm - volumes: - - ./keycloak/miw_test_realm.json:/opt/keycloak/data/import/miw_test_realm.json - - ./keycloak/health-check.sh:/opt/keycloak/health-check.sh - ports: - - "8080:8080" - depends_on: - postgres: - condition: service_healthy - networks: - - miw-net - healthcheck: - test: "bash /opt/keycloak/health-check.sh" - interval: 10s - timeout: 10s - retries: 15 - -volumes: - postgres_data: - driver: local - -networks: - miw-net: - name: miw-net diff --git a/edc-tests/miw-tests/src/test/resources/docker-environment/keycloak/health-check.sh b/edc-tests/miw-tests/src/test/resources/docker-environment/keycloak/health-check.sh deleted file mode 100755 index 27efb3eea..000000000 --- a/edc-tests/miw-tests/src/test/resources/docker-environment/keycloak/health-check.sh +++ /dev/null @@ -1,33 +0,0 @@ -#!/bin/bash -################################################################################# -# Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) -# -# See the NOTICE file(s) distributed with this work for additional -# information regarding copyright ownership. -# -# This program and the accompanying materials are made available under the -# terms of the Apache License, Version 2.0 which is available at -# https://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. -# -# SPDX-License-Identifier: Apache-2.0 -################################################################################# - -# health check approach taken from https://stackoverflow.com/a/75693900/7079724 - -exec 3<>/dev/tcp/localhost/8080 - -echo -e "GET /health/ready HTTP/1.1\nhost: localhost:8080\n" >&3 - -timeout --preserve-status 1 cat <&3 | grep -m 1 status | grep -m 1 UP -ERROR=$? - -exec 3<&- -exec 3>&- - -exit $ERROR diff --git a/edc-tests/miw-tests/src/test/resources/docker-environment/keycloak/miw_test_realm.json b/edc-tests/miw-tests/src/test/resources/docker-environment/keycloak/miw_test_realm.json deleted file mode 100644 index d2bc89329..000000000 --- a/edc-tests/miw-tests/src/test/resources/docker-environment/keycloak/miw_test_realm.json +++ /dev/null @@ -1,2479 +0,0 @@ -{ - "id": "e980fcc5-9e29-485c-bd56-440783e32014", - "realm": "miw_test", - "notBefore": 0, - "defaultSignatureAlgorithm": "RS256", - "revokeRefreshToken": false, - "refreshTokenMaxReuse": 0, - "accessTokenLifespan": 28800, - "accessTokenLifespanForImplicitFlow": 900, - "ssoSessionIdleTimeout": 1800, - "ssoSessionMaxLifespan": 36000, - "ssoSessionIdleTimeoutRememberMe": 0, - "ssoSessionMaxLifespanRememberMe": 0, - "offlineSessionIdleTimeout": 2592000, - "offlineSessionMaxLifespanEnabled": false, - "offlineSessionMaxLifespan": 5184000, - "clientSessionIdleTimeout": 0, - "clientSessionMaxLifespan": 0, - "clientOfflineSessionIdleTimeout": 0, - "clientOfflineSessionMaxLifespan": 0, - "accessCodeLifespan": 60, - "accessCodeLifespanUserAction": 300, - "accessCodeLifespanLogin": 1800, - "actionTokenGeneratedByAdminLifespan": 43200, - "actionTokenGeneratedByUserLifespan": 28800, - "oauth2DeviceCodeLifespan": 600, - "oauth2DevicePollingInterval": 5, - "enabled": true, - "sslRequired": "external", - "registrationAllowed": false, - "registrationEmailAsUsername": false, - "rememberMe": false, - "verifyEmail": false, - "loginWithEmailAllowed": true, - "duplicateEmailsAllowed": false, - "resetPasswordAllowed": false, - "editUsernameAllowed": false, - "bruteForceProtected": false, - "permanentLockout": false, - "maxFailureWaitSeconds": 900, - "minimumQuickLoginWaitSeconds": 60, - "waitIncrementSeconds": 60, - "quickLoginCheckMilliSeconds": 1000, - "maxDeltaTimeSeconds": 43200, - "failureFactor": 30, - "roles": { - "realm": [ - { - "id": "ad36b1ad-a3cb-4594-853b-b5744b86fcdb", - "name": "uma_authorization", - "description": "${role_uma_authorization}", - "composite": false, - "clientRole": false, - "containerId": "e980fcc5-9e29-485c-bd56-440783e32014", - "attributes": {} - }, - { - "id": "3247ecc3-6884-4548-bfaa-0f47cce0cda6", - "name": "default-roles-miw_test", - "description": "${role_default-roles}", - "composite": true, - "composites": { - "realm": [ - "offline_access", - "uma_authorization" - ], - "client": { - "realm-management": [ - "manage-users" - ], - "account": [ - "view-profile", - "manage-account" - ] - } - }, - "clientRole": false, - "containerId": "e980fcc5-9e29-485c-bd56-440783e32014", - "attributes": {} - }, - { - "id": "ce1ee2c7-517c-4cf0-a96f-3adac1d200a7", - "name": "offline_access", - "description": "${role_offline-access}", - "composite": false, - "clientRole": false, - "containerId": "e980fcc5-9e29-485c-bd56-440783e32014", - "attributes": {} - } - ], - "client": { - "realm-management": [ - { - "id": "e9eb031a-9dc3-413f-be30-8a396cf9a783", - "name": "manage-authorization", - "description": "${role_manage-authorization}", - "composite": false, - "clientRole": true, - "containerId": "f2604867-9227-4947-8d36-6abc754f9883", - "attributes": {} - }, - { - "id": "b33997ba-a7cb-4f47-8272-d04c18e51416", - "name": "manage-identity-providers", - "description": "${role_manage-identity-providers}", - "composite": false, - "clientRole": true, - "containerId": "f2604867-9227-4947-8d36-6abc754f9883", - "attributes": {} - }, - { - "id": "c66b4177-f470-4164-851c-018fa4445d78", - "name": "query-users", - "description": "${role_query-users}", - "composite": false, - "clientRole": true, - "containerId": "f2604867-9227-4947-8d36-6abc754f9883", - "attributes": {} - }, - { - "id": "ac2965ec-c2f2-4e30-b8fd-e3a34afc0070", - "name": "create-client", - "description": "${role_create-client}", - "composite": false, - "clientRole": true, - "containerId": "f2604867-9227-4947-8d36-6abc754f9883", - "attributes": {} - }, - { - "id": "fc813275-05d3-408f-a0d5-6943a66ada3f", - "name": "manage-events", - "description": "${role_manage-events}", - "composite": false, - "clientRole": true, - "containerId": "f2604867-9227-4947-8d36-6abc754f9883", - "attributes": {} - }, - { - "id": "73d25c6c-ca63-414e-a908-22d2f2cb18f6", - "name": "view-realm", - "description": "${role_view-realm}", - "composite": false, - "clientRole": true, - "containerId": "f2604867-9227-4947-8d36-6abc754f9883", - "attributes": {} - }, - { - "id": "2073b2f4-c5de-491f-a34d-ea0c687cae4e", - "name": "manage-users", - "description": "${role_manage-users}", - "composite": false, - "clientRole": true, - "containerId": "f2604867-9227-4947-8d36-6abc754f9883", - "attributes": {} - }, - { - "id": "3f5e2b33-5611-4289-a36d-236b81485938", - "name": "view-identity-providers", - "description": "${role_view-identity-providers}", - "composite": false, - "clientRole": true, - "containerId": "f2604867-9227-4947-8d36-6abc754f9883", - "attributes": {} - }, - { - "id": "9e9436f9-6f9a-4a86-adaa-da935522e551", - "name": "impersonation", - "description": "${role_impersonation}", - "composite": false, - "clientRole": true, - "containerId": "f2604867-9227-4947-8d36-6abc754f9883", - "attributes": {} - }, - { - "id": "272c47ae-68d9-459a-8d8c-39b95136681b", - "name": "query-realms", - "description": "${role_query-realms}", - "composite": false, - "clientRole": true, - "containerId": "f2604867-9227-4947-8d36-6abc754f9883", - "attributes": {} - }, - { - "id": "8d3984f8-408c-4c9f-8af5-dcdbbf76118c", - "name": "view-users", - "description": "${role_view-users}", - "composite": true, - "composites": { - "client": { - "realm-management": [ - "query-users", - "query-groups" - ] - } - }, - "clientRole": true, - "containerId": "f2604867-9227-4947-8d36-6abc754f9883", - "attributes": {} - }, - { - "id": "9beee882-a768-42ed-b142-74e238928634", - "name": "realm-admin", - "description": "${role_realm-admin}", - "composite": true, - "composites": { - "client": { - "realm-management": [ - "manage-identity-providers", - "manage-authorization", - "query-users", - "create-client", - "manage-events", - "view-realm", - "manage-users", - "view-identity-providers", - "impersonation", - "query-realms", - "view-users", - "view-clients", - "view-authorization", - "query-groups", - "query-clients", - "view-events", - "manage-clients", - "manage-realm" - ] - } - }, - "clientRole": true, - "containerId": "f2604867-9227-4947-8d36-6abc754f9883", - "attributes": {} - }, - { - "id": "df03dd95-6720-4ec8-a21e-25f124b9be51", - "name": "view-authorization", - "description": "${role_view-authorization}", - "composite": false, - "clientRole": true, - "containerId": "f2604867-9227-4947-8d36-6abc754f9883", - "attributes": {} - }, - { - "id": "9f0a02be-2609-496c-82cc-c07b82d2b4cc", - "name": "view-clients", - "description": "${role_view-clients}", - "composite": true, - "composites": { - "client": { - "realm-management": [ - "query-clients" - ] - } - }, - "clientRole": true, - "containerId": "f2604867-9227-4947-8d36-6abc754f9883", - "attributes": {} - }, - { - "id": "f2d938d7-835f-414b-af54-289c97fed144", - "name": "query-groups", - "description": "${role_query-groups}", - "composite": false, - "clientRole": true, - "containerId": "f2604867-9227-4947-8d36-6abc754f9883", - "attributes": {} - }, - { - "id": "6dea15cf-8398-442a-9df6-639c45cce53b", - "name": "query-clients", - "description": "${role_query-clients}", - "composite": false, - "clientRole": true, - "containerId": "f2604867-9227-4947-8d36-6abc754f9883", - "attributes": {} - }, - { - "id": "8f0da98f-988a-46cf-be03-44e12f1c3ad6", - "name": "view-events", - "description": "${role_view-events}", - "composite": false, - "clientRole": true, - "containerId": "f2604867-9227-4947-8d36-6abc754f9883", - "attributes": {} - }, - { - "id": "3f2173cd-352d-4928-9525-1fdbaf289309", - "name": "manage-clients", - "description": "${role_manage-clients}", - "composite": false, - "clientRole": true, - "containerId": "f2604867-9227-4947-8d36-6abc754f9883", - "attributes": {} - }, - { - "id": "d0c8168f-9ac4-4ac8-a908-715fda68959c", - "name": "manage-realm", - "description": "${role_manage-realm}", - "composite": false, - "clientRole": true, - "containerId": "f2604867-9227-4947-8d36-6abc754f9883", - "attributes": {} - } - ], - "security-admin-console": [], - "miw_private_client": [ - { - "id": "232e256b-81b3-4282-8198-2a4557a2687a", - "name": "view_wallets", - "description": "view_wallets", - "composite": false, - "clientRole": true, - "containerId": "774d507f-5aa3-4d16-be24-0e461f35d66a", - "attributes": {} - }, - { - "id": "2a1f1417-4eed-4ff9-b569-7461f7ae0ead", - "name": "add_wallets", - "description": "add_wallets", - "composite": false, - "clientRole": true, - "containerId": "774d507f-5aa3-4d16-be24-0e461f35d66a", - "attributes": {} - }, - { - "id": "737ec30a-c542-419a-8533-8caa7a267b68", - "name": "update_wallet", - "description": "update_wallet", - "composite": false, - "clientRole": true, - "containerId": "774d507f-5aa3-4d16-be24-0e461f35d66a", - "attributes": {} - }, - { - "id": "b32143a1-23cc-4ea5-96b0-aec079958ca0", - "name": "view_wallet", - "description": "view_wallet", - "composite": false, - "clientRole": true, - "containerId": "774d507f-5aa3-4d16-be24-0e461f35d66a", - "attributes": {} - }, - { - "id": "8ac5652e-103e-49a2-a7d0-4a9cdc958543", - "name": "update_wallets", - "description": "update_wallets", - "composite": false, - "clientRole": true, - "containerId": "774d507f-5aa3-4d16-be24-0e461f35d66a", - "attributes": {} - } - ], - "admin-cli": [], - "account-console": [], - "broker": [ - { - "id": "bd277caa-1e1f-474a-9fb9-a0f6ec21bfa5", - "name": "read-token", - "description": "${role_read-token}", - "composite": false, - "clientRole": true, - "containerId": "f6dd02a1-9c2b-4af9-81bf-200efc0fcf22", - "attributes": {} - } - ], - "miw_public": [], - "account": [ - { - "id": "cbe6b27b-83b2-4c40-ba6b-e776b32d919c", - "name": "manage-account-links", - "description": "${role_manage-account-links}", - "composite": false, - "clientRole": true, - "containerId": "356d12b7-0894-474f-8701-c51c78182351", - "attributes": {} - }, - { - "id": "2e9938b0-51ea-47f6-91d5-93020fbbe094", - "name": "view-profile", - "description": "${role_view-profile}", - "composite": false, - "clientRole": true, - "containerId": "356d12b7-0894-474f-8701-c51c78182351", - "attributes": {} - }, - { - "id": "000f2103-4f84-4ab2-b2e9-72e006a7aa7a", - "name": "delete-account", - "description": "${role_delete-account}", - "composite": false, - "clientRole": true, - "containerId": "356d12b7-0894-474f-8701-c51c78182351", - "attributes": {} - }, - { - "id": "d0d1ec92-4928-4446-ab70-af4a5ec941f0", - "name": "manage-consent", - "description": "${role_manage-consent}", - "composite": true, - "composites": { - "client": { - "account": [ - "view-consent" - ] - } - }, - "clientRole": true, - "containerId": "356d12b7-0894-474f-8701-c51c78182351", - "attributes": {} - }, - { - "id": "be516b3c-47c9-4da9-b65a-c0269c066cd2", - "name": "view-consent", - "description": "${role_view-consent}", - "composite": false, - "clientRole": true, - "containerId": "356d12b7-0894-474f-8701-c51c78182351", - "attributes": {} - }, - { - "id": "f628b4e8-783f-4b2b-ad20-9ce7191ef39b", - "name": "manage-account", - "description": "${role_manage-account}", - "composite": true, - "composites": { - "client": { - "account": [ - "manage-account-links" - ] - } - }, - "clientRole": true, - "containerId": "356d12b7-0894-474f-8701-c51c78182351", - "attributes": {} - }, - { - "id": "465eff9a-73da-4fd3-ac96-e84db10cc263", - "name": "view-applications", - "description": "${role_view-applications}", - "composite": false, - "clientRole": true, - "containerId": "356d12b7-0894-474f-8701-c51c78182351", - "attributes": {} - }, - { - "id": "631c870f-24e9-4058-b506-993520d68d24", - "name": "view-groups", - "description": "${role_view-groups}", - "composite": false, - "clientRole": true, - "containerId": "356d12b7-0894-474f-8701-c51c78182351", - "attributes": {} - } - ] - } - }, - "groups": [], - "defaultRole": { - "id": "3247ecc3-6884-4548-bfaa-0f47cce0cda6", - "name": "default-roles-miw_test", - "description": "${role_default-roles}", - "composite": true, - "clientRole": false, - "containerId": "e980fcc5-9e29-485c-bd56-440783e32014" - }, - "requiredCredentials": [ - "password" - ], - "otpPolicyType": "totp", - "otpPolicyAlgorithm": "HmacSHA1", - "otpPolicyInitialCounter": 0, - "otpPolicyDigits": 6, - "otpPolicyLookAheadWindow": 1, - "otpPolicyPeriod": 30, - "otpPolicyCodeReusable": false, - "otpSupportedApplications": [ - "totpAppMicrosoftAuthenticatorName", - "totpAppGoogleName", - "totpAppFreeOTPName" - ], - "webAuthnPolicyRpEntityName": "keycloak", - "webAuthnPolicySignatureAlgorithms": [ - "ES256" - ], - "webAuthnPolicyRpId": "", - "webAuthnPolicyAttestationConveyancePreference": "not specified", - "webAuthnPolicyAuthenticatorAttachment": "not specified", - "webAuthnPolicyRequireResidentKey": "not specified", - "webAuthnPolicyUserVerificationRequirement": "not specified", - "webAuthnPolicyCreateTimeout": 0, - "webAuthnPolicyAvoidSameAuthenticatorRegister": false, - "webAuthnPolicyAcceptableAaguids": [], - "webAuthnPolicyPasswordlessRpEntityName": "keycloak", - "webAuthnPolicyPasswordlessSignatureAlgorithms": [ - "ES256" - ], - "webAuthnPolicyPasswordlessRpId": "", - "webAuthnPolicyPasswordlessAttestationConveyancePreference": "not specified", - "webAuthnPolicyPasswordlessAuthenticatorAttachment": "not specified", - "webAuthnPolicyPasswordlessRequireResidentKey": "not specified", - "webAuthnPolicyPasswordlessUserVerificationRequirement": "not specified", - "webAuthnPolicyPasswordlessCreateTimeout": 0, - "webAuthnPolicyPasswordlessAvoidSameAuthenticatorRegister": false, - "webAuthnPolicyPasswordlessAcceptableAaguids": [], - "users": [ - { - "id": "7e5c957b-2f20-41e0-85fb-e84656caadfe", - "createdTimestamp": 1687957169104, - "username": "service-account-miw_private_client", - "enabled": true, - "totp": false, - "emailVerified": false, - "serviceAccountClientId": "miw_private_client", - "disableableCredentialTypes": [], - "requiredActions": [], - "realmRoles": [ - "default-roles-miw_test" - ], - "clientRoles": { - "miw_private_client": [ - "view_wallets", - "update_wallet", - "add_wallets", - "view_wallet", - "update_wallets" - ] - }, - "notBefore": 0, - "groups": [] - } - ], - "scopeMappings": [ - { - "clientScope": "offline_access", - "roles": [ - "offline_access" - ] - } - ], - "clientScopeMappings": { - "account": [ - { - "client": "account-console", - "roles": [ - "manage-account", - "view-groups" - ] - } - ] - }, - "clients": [ - { - "id": "356d12b7-0894-474f-8701-c51c78182351", - "clientId": "account", - "name": "${client_account}", - "rootUrl": "${authBaseUrl}", - "baseUrl": "/realms/miw_test/account/", - "surrogateAuthRequired": false, - "enabled": true, - "alwaysDisplayInConsole": false, - "clientAuthenticatorType": "client-secret", - "redirectUris": [ - "/realms/miw_test/account/*" - ], - "webOrigins": [], - "notBefore": 0, - "bearerOnly": false, - "consentRequired": false, - "standardFlowEnabled": true, - "implicitFlowEnabled": false, - "directAccessGrantsEnabled": false, - "serviceAccountsEnabled": false, - "publicClient": true, - "frontchannelLogout": false, - "protocol": "openid-connect", - "attributes": { - "post.logout.redirect.uris": "+" - }, - "authenticationFlowBindingOverrides": {}, - "fullScopeAllowed": false, - "nodeReRegistrationTimeout": 0, - "defaultClientScopes": [ - "web-origins", - "acr", - "profile", - "roles", - "email" - ], - "optionalClientScopes": [ - "address", - "phone", - "offline_access", - "microprofile-jwt" - ] - }, - { - "id": "e33fa081-88ee-4443-955a-22b57d96bd9a", - "clientId": "account-console", - "name": "${client_account-console}", - "rootUrl": "${authBaseUrl}", - "baseUrl": "/realms/miw_test/account/", - "surrogateAuthRequired": false, - "enabled": true, - "alwaysDisplayInConsole": false, - "clientAuthenticatorType": "client-secret", - "redirectUris": [ - "/realms/miw_test/account/*" - ], - "webOrigins": [], - "notBefore": 0, - "bearerOnly": false, - "consentRequired": false, - "standardFlowEnabled": true, - "implicitFlowEnabled": false, - "directAccessGrantsEnabled": false, - "serviceAccountsEnabled": false, - "publicClient": true, - "frontchannelLogout": false, - "protocol": "openid-connect", - "attributes": { - "post.logout.redirect.uris": "+", - "pkce.code.challenge.method": "S256" - }, - "authenticationFlowBindingOverrides": {}, - "fullScopeAllowed": false, - "nodeReRegistrationTimeout": 0, - "protocolMappers": [ - { - "id": "db8af579-9b62-4a5d-8f21-9113cacce594", - "name": "audience resolve", - "protocol": "openid-connect", - "protocolMapper": "oidc-audience-resolve-mapper", - "consentRequired": false, - "config": {} - } - ], - "defaultClientScopes": [ - "web-origins", - "acr", - "profile", - "roles", - "email" - ], - "optionalClientScopes": [ - "address", - "phone", - "offline_access", - "microprofile-jwt" - ] - }, - { - "id": "e6ecff04-23e9-4828-ae48-2eaf9cf21086", - "clientId": "admin-cli", - "name": "${client_admin-cli}", - "surrogateAuthRequired": false, - "enabled": true, - "alwaysDisplayInConsole": false, - "clientAuthenticatorType": "client-secret", - "redirectUris": [], - "webOrigins": [], - "notBefore": 0, - "bearerOnly": false, - "consentRequired": false, - "standardFlowEnabled": false, - "implicitFlowEnabled": false, - "directAccessGrantsEnabled": true, - "serviceAccountsEnabled": false, - "publicClient": true, - "frontchannelLogout": false, - "protocol": "openid-connect", - "attributes": { - "post.logout.redirect.uris": "+" - }, - "authenticationFlowBindingOverrides": {}, - "fullScopeAllowed": false, - "nodeReRegistrationTimeout": 0, - "defaultClientScopes": [ - "web-origins", - "acr", - "profile", - "roles", - "email" - ], - "optionalClientScopes": [ - "address", - "phone", - "offline_access", - "microprofile-jwt" - ] - }, - { - "id": "f6dd02a1-9c2b-4af9-81bf-200efc0fcf22", - "clientId": "broker", - "name": "${client_broker}", - "surrogateAuthRequired": false, - "enabled": true, - "alwaysDisplayInConsole": false, - "clientAuthenticatorType": "client-secret", - "redirectUris": [], - "webOrigins": [], - "notBefore": 0, - "bearerOnly": true, - "consentRequired": false, - "standardFlowEnabled": true, - "implicitFlowEnabled": false, - "directAccessGrantsEnabled": false, - "serviceAccountsEnabled": false, - "publicClient": false, - "frontchannelLogout": false, - "protocol": "openid-connect", - "attributes": { - "post.logout.redirect.uris": "+" - }, - "authenticationFlowBindingOverrides": {}, - "fullScopeAllowed": false, - "nodeReRegistrationTimeout": 0, - "defaultClientScopes": [ - "web-origins", - "acr", - "profile", - "roles", - "email" - ], - "optionalClientScopes": [ - "address", - "phone", - "offline_access", - "microprofile-jwt" - ] - }, - { - "id": "774d507f-5aa3-4d16-be24-0e461f35d66a", - "clientId": "miw_private_client", - "name": "miw_private_client", - "description": "miw_private_client", - "rootUrl": "", - "adminUrl": "", - "baseUrl": "", - "surrogateAuthRequired": false, - "enabled": true, - "alwaysDisplayInConsole": false, - "clientAuthenticatorType": "client-secret", - "secret": "miw_private_client", - "redirectUris": [], - "webOrigins": [], - "notBefore": 0, - "bearerOnly": false, - "consentRequired": false, - "standardFlowEnabled": true, - "implicitFlowEnabled": false, - "directAccessGrantsEnabled": true, - "serviceAccountsEnabled": true, - "publicClient": false, - "frontchannelLogout": true, - "protocol": "openid-connect", - "attributes": { - "oidc.ciba.grant.enabled": "false", - "client.secret.creation.time": "1684923648", - "backchannel.logout.session.required": "true", - "post.logout.redirect.uris": "+", - "display.on.consent.screen": "false", - "oauth2.device.authorization.grant.enabled": "false", - "backchannel.logout.revoke.offline.tokens": "false" - }, - "authenticationFlowBindingOverrides": {}, - "fullScopeAllowed": true, - "nodeReRegistrationTimeout": -1, - "protocolMappers": [ - { - "id": "767fc59d-4812-4147-a4c0-c1d36854a111", - "name": "User Client Role", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-client-role-mapper", - "consentRequired": false, - "config": { - "id.token.claim": "true", - "access.token.claim": "true", - "usermodel.clientRoleMapping.clientId": "miw_private_client", - "multivalued": "true", - "userinfo.token.claim": "true" - } - }, - { - "id": "c46e9cc6-3057-4640-a78b-e12fc3a714df", - "name": "BPN", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-attribute-mapper", - "consentRequired": false, - "config": { - "aggregate.attrs": "false", - "userinfo.token.claim": "true", - "multivalued": "false", - "user.attribute": "BPN", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "BPN" - } - }, - { - "id": "f446598c-1637-4585-b2b6-0204d2e6e92e", - "name": "client_bpn_mapper", - "protocol": "openid-connect", - "protocolMapper": "oidc-hardcoded-claim-mapper", - "consentRequired": false, - "config": { - "claim.value": "BPNL000000000000", - "userinfo.token.claim": "true", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "BPN", - "access.tokenResponse.claim": "false" - } - }, - { - "id": "1340463e-a737-4507-8ecb-b01715a9fde4", - "name": "Client IP Address", - "protocol": "openid-connect", - "protocolMapper": "oidc-usersessionmodel-note-mapper", - "consentRequired": false, - "config": { - "user.session.note": "clientAddress", - "userinfo.token.claim": "true", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "clientAddress", - "jsonType.label": "String" - } - }, - { - "id": "9096587b-3781-4104-b1ec-458c7ca95e8d", - "name": "Client ID", - "protocol": "openid-connect", - "protocolMapper": "oidc-usersessionmodel-note-mapper", - "consentRequired": false, - "config": { - "user.session.note": "clientId", - "userinfo.token.claim": "true", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "clientId", - "jsonType.label": "String" - } - }, - { - "id": "370515a5-370a-4b68-9704-9a67407c1390", - "name": "Client Host", - "protocol": "openid-connect", - "protocolMapper": "oidc-usersessionmodel-note-mapper", - "consentRequired": false, - "config": { - "user.session.note": "clientHost", - "userinfo.token.claim": "true", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "clientHost", - "jsonType.label": "String" - } - } - ], - "defaultClientScopes": [ - "web-origins", - "acr", - "profile", - "roles", - "email" - ], - "optionalClientScopes": [ - "address", - "phone", - "offline_access", - "microprofile-jwt" - ] - }, - { - "id": "7dbe3954-6da4-43f1-a1df-cf160fee58e2", - "clientId": "miw_public", - "name": "", - "description": "", - "rootUrl": "", - "adminUrl": "", - "baseUrl": "", - "surrogateAuthRequired": false, - "enabled": true, - "alwaysDisplayInConsole": false, - "clientAuthenticatorType": "client-secret", - "redirectUris": [ - "http://localhost:8080/*", - "http://localhost/*", - "http://localhost:8087/*" - ], - "webOrigins": [ - "http://localhost:8080", - "http://localhost", - "http://localhost:8087" - ], - "notBefore": 0, - "bearerOnly": false, - "consentRequired": false, - "standardFlowEnabled": true, - "implicitFlowEnabled": false, - "directAccessGrantsEnabled": true, - "serviceAccountsEnabled": false, - "publicClient": true, - "frontchannelLogout": true, - "protocol": "openid-connect", - "attributes": { - "oidc.ciba.grant.enabled": "false", - "backchannel.logout.session.required": "true", - "post.logout.redirect.uris": "+", - "display.on.consent.screen": "false", - "oauth2.device.authorization.grant.enabled": "false", - "backchannel.logout.revoke.offline.tokens": "false" - }, - "authenticationFlowBindingOverrides": {}, - "fullScopeAllowed": true, - "nodeReRegistrationTimeout": -1, - "protocolMappers": [ - { - "id": "1312c58c-7950-4e3f-b45d-a77b827a62d7", - "name": "BPN_user_attribute", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-attribute-mapper", - "consentRequired": false, - "config": { - "aggregate.attrs": "false", - "userinfo.token.claim": "true", - "multivalued": "false", - "user.attribute": "BPN", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "BPN" - } - } - ], - "defaultClientScopes": [ - "web-origins", - "acr", - "profile", - "roles", - "email" - ], - "optionalClientScopes": [ - "address", - "phone", - "offline_access", - "microprofile-jwt" - ] - }, - { - "id": "f2604867-9227-4947-8d36-6abc754f9883", - "clientId": "realm-management", - "name": "${client_realm-management}", - "surrogateAuthRequired": false, - "enabled": true, - "alwaysDisplayInConsole": false, - "clientAuthenticatorType": "client-secret", - "redirectUris": [], - "webOrigins": [], - "notBefore": 0, - "bearerOnly": true, - "consentRequired": false, - "standardFlowEnabled": true, - "implicitFlowEnabled": false, - "directAccessGrantsEnabled": false, - "serviceAccountsEnabled": false, - "publicClient": false, - "frontchannelLogout": false, - "protocol": "openid-connect", - "attributes": { - "post.logout.redirect.uris": "+" - }, - "authenticationFlowBindingOverrides": {}, - "fullScopeAllowed": false, - "nodeReRegistrationTimeout": 0, - "defaultClientScopes": [ - "web-origins", - "acr", - "profile", - "roles", - "email" - ], - "optionalClientScopes": [ - "address", - "phone", - "offline_access", - "microprofile-jwt" - ] - }, - { - "id": "d966ce87-fa07-4c99-9ed1-899961993d88", - "clientId": "security-admin-console", - "name": "${client_security-admin-console}", - "rootUrl": "${authAdminUrl}", - "baseUrl": "/admin/miw_test/console/", - "surrogateAuthRequired": false, - "enabled": true, - "alwaysDisplayInConsole": false, - "clientAuthenticatorType": "client-secret", - "redirectUris": [ - "/admin/miw_test/console/*" - ], - "webOrigins": [ - "+" - ], - "notBefore": 0, - "bearerOnly": false, - "consentRequired": false, - "standardFlowEnabled": true, - "implicitFlowEnabled": false, - "directAccessGrantsEnabled": false, - "serviceAccountsEnabled": false, - "publicClient": true, - "frontchannelLogout": false, - "protocol": "openid-connect", - "attributes": { - "post.logout.redirect.uris": "+", - "pkce.code.challenge.method": "S256" - }, - "authenticationFlowBindingOverrides": {}, - "fullScopeAllowed": false, - "nodeReRegistrationTimeout": 0, - "protocolMappers": [ - { - "id": "088895dc-a6b7-4d7a-b8e8-70804dd7a4be", - "name": "locale", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-attribute-mapper", - "consentRequired": false, - "config": { - "userinfo.token.claim": "true", - "user.attribute": "locale", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "locale", - "jsonType.label": "String" - } - } - ], - "defaultClientScopes": [ - "web-origins", - "acr", - "profile", - "roles", - "email" - ], - "optionalClientScopes": [ - "address", - "phone", - "offline_access", - "microprofile-jwt" - ] - } - ], - "clientScopes": [ - { - "id": "e7addfcc-9187-43b2-9dd8-d883c3d7d4ce", - "name": "email", - "description": "OpenID Connect built-in scope: email", - "protocol": "openid-connect", - "attributes": { - "include.in.token.scope": "true", - "display.on.consent.screen": "true", - "consent.screen.text": "${emailScopeConsentText}" - }, - "protocolMappers": [ - { - "id": "7f56bfa8-3c9c-4ddb-ba03-bf3baee76b5e", - "name": "email verified", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-property-mapper", - "consentRequired": false, - "config": { - "userinfo.token.claim": "true", - "user.attribute": "emailVerified", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "email_verified", - "jsonType.label": "boolean" - } - }, - { - "id": "7ae07240-7a54-4e77-a3ed-1cff45e70a6f", - "name": "email", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-property-mapper", - "consentRequired": false, - "config": { - "userinfo.token.claim": "true", - "user.attribute": "email", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "email", - "jsonType.label": "String" - } - } - ] - }, - { - "id": "6447876f-32c7-42b7-864c-61b8c12f651f", - "name": "offline_access", - "description": "OpenID Connect built-in scope: offline_access", - "protocol": "openid-connect", - "attributes": { - "consent.screen.text": "${offlineAccessScopeConsentText}", - "display.on.consent.screen": "true" - } - }, - { - "id": "7b162106-cbc9-4c05-9043-6fbece4d7600", - "name": "role_list", - "description": "SAML role list", - "protocol": "saml", - "attributes": { - "consent.screen.text": "${samlRoleListScopeConsentText}", - "display.on.consent.screen": "true" - }, - "protocolMappers": [ - { - "id": "445b2b60-0bf1-4eb8-ab60-99351b616da6", - "name": "role list", - "protocol": "saml", - "protocolMapper": "saml-role-list-mapper", - "consentRequired": false, - "config": { - "single": "false", - "attribute.nameformat": "Basic", - "attribute.name": "Role" - } - } - ] - }, - { - "id": "ad308290-1c37-4d33-99f3-8d23e2f74501", - "name": "microprofile-jwt", - "description": "Microprofile - JWT built-in scope", - "protocol": "openid-connect", - "attributes": { - "include.in.token.scope": "true", - "display.on.consent.screen": "false" - }, - "protocolMappers": [ - { - "id": "7fbc621e-a6ad-48d4-b981-55be57bae980", - "name": "groups", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-realm-role-mapper", - "consentRequired": false, - "config": { - "multivalued": "true", - "userinfo.token.claim": "true", - "user.attribute": "foo", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "groups", - "jsonType.label": "String" - } - }, - { - "id": "3eacc647-eff9-48a4-a9ca-cdd8b1a02665", - "name": "upn", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-property-mapper", - "consentRequired": false, - "config": { - "userinfo.token.claim": "true", - "user.attribute": "username", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "upn", - "jsonType.label": "String" - } - } - ] - }, - { - "id": "f6d808aa-019d-4f3f-951e-dda5a77f841c", - "name": "acr", - "description": "OpenID Connect scope for add acr (authentication context class reference) to the token", - "protocol": "openid-connect", - "attributes": { - "include.in.token.scope": "false", - "display.on.consent.screen": "false" - }, - "protocolMappers": [ - { - "id": "d3204d28-9023-4cf6-b996-fd845180c8dd", - "name": "acr loa level", - "protocol": "openid-connect", - "protocolMapper": "oidc-acr-mapper", - "consentRequired": false, - "config": { - "id.token.claim": "true", - "access.token.claim": "true", - "userinfo.token.claim": "true" - } - } - ] - }, - { - "id": "fcfb1f12-dc72-4529-be32-51b16d4b7c58", - "name": "profile", - "description": "OpenID Connect built-in scope: profile", - "protocol": "openid-connect", - "attributes": { - "include.in.token.scope": "true", - "display.on.consent.screen": "true", - "consent.screen.text": "${profileScopeConsentText}" - }, - "protocolMappers": [ - { - "id": "7091a3bd-ffd1-40cf-82cf-636aa49728ce", - "name": "nickname", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-attribute-mapper", - "consentRequired": false, - "config": { - "userinfo.token.claim": "true", - "user.attribute": "nickname", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "nickname", - "jsonType.label": "String" - } - }, - { - "id": "27f9ab53-8807-4ef1-b9a0-12a8a76ab5ec", - "name": "birthdate", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-attribute-mapper", - "consentRequired": false, - "config": { - "userinfo.token.claim": "true", - "user.attribute": "birthdate", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "birthdate", - "jsonType.label": "String" - } - }, - { - "id": "29402017-bf33-48c2-8e7c-9eae2c44e929", - "name": "locale", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-attribute-mapper", - "consentRequired": false, - "config": { - "userinfo.token.claim": "true", - "user.attribute": "locale", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "locale", - "jsonType.label": "String" - } - }, - { - "id": "6e24f73b-8529-43ff-9815-2901cb1d5a91", - "name": "updated at", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-attribute-mapper", - "consentRequired": false, - "config": { - "userinfo.token.claim": "true", - "user.attribute": "updatedAt", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "updated_at", - "jsonType.label": "long" - } - }, - { - "id": "a45c35be-f77d-4627-9bf9-a3414722e484", - "name": "picture", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-attribute-mapper", - "consentRequired": false, - "config": { - "userinfo.token.claim": "true", - "user.attribute": "picture", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "picture", - "jsonType.label": "String" - } - }, - { - "id": "eba7c338-cce4-4cd6-8044-083273ddca3a", - "name": "full name", - "protocol": "openid-connect", - "protocolMapper": "oidc-full-name-mapper", - "consentRequired": false, - "config": { - "id.token.claim": "true", - "access.token.claim": "true", - "userinfo.token.claim": "true" - } - }, - { - "id": "bfb08dad-0a9f-41fd-871b-1fbfb0d43594", - "name": "profile", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-attribute-mapper", - "consentRequired": false, - "config": { - "userinfo.token.claim": "true", - "user.attribute": "profile", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "profile", - "jsonType.label": "String" - } - }, - { - "id": "b8f94365-aa92-44d7-9f96-84822aef4cad", - "name": "family name", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-property-mapper", - "consentRequired": false, - "config": { - "userinfo.token.claim": "true", - "user.attribute": "lastName", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "family_name", - "jsonType.label": "String" - } - }, - { - "id": "b8849581-e158-4daf-98f0-b23f351b7362", - "name": "given name", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-property-mapper", - "consentRequired": false, - "config": { - "userinfo.token.claim": "true", - "user.attribute": "firstName", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "given_name", - "jsonType.label": "String" - } - }, - { - "id": "7104be3f-1760-4fa7-9ad7-985959f852f2", - "name": "website", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-attribute-mapper", - "consentRequired": false, - "config": { - "userinfo.token.claim": "true", - "user.attribute": "website", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "website", - "jsonType.label": "String" - } - }, - { - "id": "c7a9ba7a-62bf-4846-9b2f-56a8c6b31901", - "name": "gender", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-attribute-mapper", - "consentRequired": false, - "config": { - "userinfo.token.claim": "true", - "user.attribute": "gender", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "gender", - "jsonType.label": "String" - } - }, - { - "id": "1e5a4e39-1fbc-4245-bced-f1271c01cf28", - "name": "middle name", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-attribute-mapper", - "consentRequired": false, - "config": { - "userinfo.token.claim": "true", - "user.attribute": "middleName", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "middle_name", - "jsonType.label": "String" - } - }, - { - "id": "20bca7ef-8879-4b77-85fc-e38dd86518da", - "name": "username", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-property-mapper", - "consentRequired": false, - "config": { - "userinfo.token.claim": "true", - "user.attribute": "username", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "preferred_username", - "jsonType.label": "String" - } - }, - { - "id": "679465a3-8205-404b-ac12-f0ce50194f71", - "name": "zoneinfo", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-attribute-mapper", - "consentRequired": false, - "config": { - "userinfo.token.claim": "true", - "user.attribute": "zoneinfo", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "zoneinfo", - "jsonType.label": "String" - } - } - ] - }, - { - "id": "fc9f5da4-557c-432f-87ec-128c07e09c79", - "name": "phone", - "description": "OpenID Connect built-in scope: phone", - "protocol": "openid-connect", - "attributes": { - "include.in.token.scope": "true", - "display.on.consent.screen": "true", - "consent.screen.text": "${phoneScopeConsentText}" - }, - "protocolMappers": [ - { - "id": "bbe96ba8-010c-4798-83e5-38fa3c7e7d66", - "name": "phone number", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-attribute-mapper", - "consentRequired": false, - "config": { - "userinfo.token.claim": "true", - "user.attribute": "phoneNumber", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "phone_number", - "jsonType.label": "String" - } - }, - { - "id": "15f0c6ce-d7a5-4165-9ae2-978e3776d4a4", - "name": "phone number verified", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-attribute-mapper", - "consentRequired": false, - "config": { - "userinfo.token.claim": "true", - "user.attribute": "phoneNumberVerified", - "id.token.claim": "true", - "access.token.claim": "true", - "claim.name": "phone_number_verified", - "jsonType.label": "boolean" - } - } - ] - }, - { - "id": "96747a05-db5f-4289-bca2-8e3ebc0b244e", - "name": "roles", - "description": "OpenID Connect scope for add user roles to the access token", - "protocol": "openid-connect", - "attributes": { - "include.in.token.scope": "false", - "display.on.consent.screen": "true", - "consent.screen.text": "${rolesScopeConsentText}" - }, - "protocolMappers": [ - { - "id": "7db29b64-30f8-43df-99f7-73f16db774b4", - "name": "audience resolve", - "protocol": "openid-connect", - "protocolMapper": "oidc-audience-resolve-mapper", - "consentRequired": false, - "config": {} - }, - { - "id": "1fa84511-e274-4ffb-8cb7-a426dd5ebe4a", - "name": "realm roles", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-realm-role-mapper", - "consentRequired": false, - "config": { - "user.attribute": "foo", - "access.token.claim": "true", - "claim.name": "realm_access.roles", - "jsonType.label": "String", - "multivalued": "true" - } - }, - { - "id": "8594b20e-3ade-4661-bea2-bf0b5d47ff1e", - "name": "client roles", - "protocol": "openid-connect", - "protocolMapper": "oidc-usermodel-client-role-mapper", - "consentRequired": false, - "config": { - "user.attribute": "foo", - "access.token.claim": "true", - "claim.name": "resource_access.${client_id}.roles", - "jsonType.label": "String", - "multivalued": "true" - } - } - ] - }, - { - "id": "801527ae-e765-4d90-8d87-5547fc96d2be", - "name": "address", - "description": "OpenID Connect built-in scope: address", - "protocol": "openid-connect", - "attributes": { - "include.in.token.scope": "true", - "display.on.consent.screen": "true", - "consent.screen.text": "${addressScopeConsentText}" - }, - "protocolMappers": [ - { - "id": "5519fbcf-8042-4b00-9c2a-a79bf16b9d59", - "name": "address", - "protocol": "openid-connect", - "protocolMapper": "oidc-address-mapper", - "consentRequired": false, - "config": { - "user.attribute.formatted": "formatted", - "user.attribute.country": "country", - "user.attribute.postal_code": "postal_code", - "userinfo.token.claim": "true", - "user.attribute.street": "street", - "id.token.claim": "true", - "user.attribute.region": "region", - "access.token.claim": "true", - "user.attribute.locality": "locality" - } - } - ] - }, - { - "id": "99a7cadd-76c0-406f-88bf-24947fec442e", - "name": "web-origins", - "description": "OpenID Connect scope for add allowed web origins to the access token", - "protocol": "openid-connect", - "attributes": { - "include.in.token.scope": "false", - "display.on.consent.screen": "false", - "consent.screen.text": "" - }, - "protocolMappers": [ - { - "id": "a57ca5de-7d7a-4695-b181-1099790ec07f", - "name": "allowed web origins", - "protocol": "openid-connect", - "protocolMapper": "oidc-allowed-origins-mapper", - "consentRequired": false, - "config": {} - } - ] - } - ], - "defaultDefaultClientScopes": [ - "role_list", - "profile", - "email", - "roles", - "web-origins", - "acr" - ], - "defaultOptionalClientScopes": [ - "offline_access", - "address", - "phone", - "microprofile-jwt" - ], - "browserSecurityHeaders": { - "contentSecurityPolicyReportOnly": "", - "xContentTypeOptions": "nosniff", - "xRobotsTag": "none", - "xFrameOptions": "SAMEORIGIN", - "contentSecurityPolicy": "frame-src 'self'; frame-ancestors 'self'; object-src 'none';", - "xXSSProtection": "1; mode=block", - "strictTransportSecurity": "max-age=31536000; includeSubDomains" - }, - "smtpServer": {}, - "eventsEnabled": false, - "eventsListeners": [ - "jboss-logging" - ], - "enabledEventTypes": [], - "adminEventsEnabled": false, - "adminEventsDetailsEnabled": false, - "identityProviders": [], - "identityProviderMappers": [], - "components": { - "org.keycloak.services.clientregistration.policy.ClientRegistrationPolicy": [ - { - "id": "bc6e125a-0c96-4a44-ac91-bf6ecc035cec", - "name": "Allowed Client Scopes", - "providerId": "allowed-client-templates", - "subType": "authenticated", - "subComponents": {}, - "config": { - "allow-default-scopes": [ - "true" - ] - } - }, - { - "id": "a9aceec7-3d4d-4fc7-9ee7-b0862b3f212a", - "name": "Allowed Client Scopes", - "providerId": "allowed-client-templates", - "subType": "anonymous", - "subComponents": {}, - "config": { - "allow-default-scopes": [ - "true" - ] - } - }, - { - "id": "476306a8-3346-430b-a6da-f3fc52910ce9", - "name": "Max Clients Limit", - "providerId": "max-clients", - "subType": "anonymous", - "subComponents": {}, - "config": { - "max-clients": [ - "200" - ] - } - }, - { - "id": "b3cc2af0-dc32-4a7d-9298-fdc664f3bb83", - "name": "Allowed Protocol Mapper Types", - "providerId": "allowed-protocol-mappers", - "subType": "authenticated", - "subComponents": {}, - "config": { - "allowed-protocol-mapper-types": [ - "oidc-sha256-pairwise-sub-mapper", - "saml-user-attribute-mapper", - "saml-user-property-mapper", - "oidc-full-name-mapper", - "oidc-usermodel-attribute-mapper", - "saml-role-list-mapper", - "oidc-address-mapper", - "oidc-usermodel-property-mapper" - ] - } - }, - { - "id": "7da42bd3-7368-4be2-bc0c-82067fc48463", - "name": "Allowed Protocol Mapper Types", - "providerId": "allowed-protocol-mappers", - "subType": "anonymous", - "subComponents": {}, - "config": { - "allowed-protocol-mapper-types": [ - "oidc-full-name-mapper", - "saml-user-attribute-mapper", - "oidc-address-mapper", - "oidc-sha256-pairwise-sub-mapper", - "oidc-usermodel-property-mapper", - "saml-user-property-mapper", - "oidc-usermodel-attribute-mapper", - "saml-role-list-mapper" - ] - } - }, - { - "id": "706c9166-d41a-4d1e-872c-45c587b0ac6b", - "name": "Full Scope Disabled", - "providerId": "scope", - "subType": "anonymous", - "subComponents": {}, - "config": {} - }, - { - "id": "bc67afe8-8f95-49eb-915c-18d11f4bbc2b", - "name": "Consent Required", - "providerId": "consent-required", - "subType": "anonymous", - "subComponents": {}, - "config": {} - }, - { - "id": "c8570184-4c4c-460f-9d78-95d36838e89a", - "name": "Trusted Hosts", - "providerId": "trusted-hosts", - "subType": "anonymous", - "subComponents": {}, - "config": { - "host-sending-registration-request-must-match": [ - "true" - ], - "client-uris-must-match": [ - "true" - ] - } - } - ], - "org.keycloak.userprofile.UserProfileProvider": [ - { - "id": "254a0e2b-b22b-4e1e-94ba-feb82f4e55f4", - "providerId": "declarative-user-profile", - "subComponents": {}, - "config": {} - } - ], - "org.keycloak.keys.KeyProvider": [ - { - "id": "f19c25ec-b555-4a60-8d98-fa41190c58d8", - "name": "hmac-generated", - "providerId": "hmac-generated", - "subComponents": {}, - "config": { - "priority": [ - "100" - ], - "algorithm": [ - "HS256" - ] - } - }, - { - "id": "25496642-de17-48e8-8b48-49982e3e0bff", - "name": "aes-generated", - "providerId": "aes-generated", - "subComponents": {}, - "config": { - "priority": [ - "100" - ] - } - }, - { - "id": "31fc839e-8c60-48b7-b9a2-66ecaa0902e5", - "name": "rsa-enc-generated", - "providerId": "rsa-enc-generated", - "subComponents": {}, - "config": { - "priority": [ - "100" - ], - "algorithm": [ - "RSA-OAEP" - ] - } - }, - { - "id": "c09f0435-5a5c-4ee6-af62-6bc7db9fbc88", - "name": "rsa-generated", - "providerId": "rsa-generated", - "subComponents": {}, - "config": { - "priority": [ - "100" - ] - } - } - ] - }, - "internationalizationEnabled": false, - "supportedLocales": [], - "authenticationFlows": [ - { - "id": "04cc2aa7-9e5b-4178-a1a2-dad58cf99367", - "alias": "Account verification options", - "description": "Method with which to verity the existing account", - "providerId": "basic-flow", - "topLevel": false, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "idp-email-verification", - "authenticatorFlow": false, - "requirement": "ALTERNATIVE", - "priority": 10, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticatorFlow": true, - "requirement": "ALTERNATIVE", - "priority": 20, - "autheticatorFlow": true, - "flowAlias": "Verify Existing Account by Re-authentication", - "userSetupAllowed": false - } - ] - }, - { - "id": "fa4d6b27-5fac-4b3b-9cbc-badb7cfe90ed", - "alias": "Authentication Options", - "description": "Authentication options.", - "providerId": "basic-flow", - "topLevel": false, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "basic-auth", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 10, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticator": "basic-auth-otp", - "authenticatorFlow": false, - "requirement": "DISABLED", - "priority": 20, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticator": "auth-spnego", - "authenticatorFlow": false, - "requirement": "DISABLED", - "priority": 30, - "autheticatorFlow": false, - "userSetupAllowed": false - } - ] - }, - { - "id": "266db702-5928-4149-b2bd-701d0722eb93", - "alias": "Browser - Conditional OTP", - "description": "Flow to determine if the OTP is required for the authentication", - "providerId": "basic-flow", - "topLevel": false, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "conditional-user-configured", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 10, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticator": "auth-otp-form", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 20, - "autheticatorFlow": false, - "userSetupAllowed": false - } - ] - }, - { - "id": "dd326252-8827-445d-a098-9ec953932387", - "alias": "Direct Grant - Conditional OTP", - "description": "Flow to determine if the OTP is required for the authentication", - "providerId": "basic-flow", - "topLevel": false, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "conditional-user-configured", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 10, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticator": "direct-grant-validate-otp", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 20, - "autheticatorFlow": false, - "userSetupAllowed": false - } - ] - }, - { - "id": "b8f5c247-b9ba-40c7-a14e-05a235bed46f", - "alias": "First broker login - Conditional OTP", - "description": "Flow to determine if the OTP is required for the authentication", - "providerId": "basic-flow", - "topLevel": false, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "conditional-user-configured", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 10, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticator": "auth-otp-form", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 20, - "autheticatorFlow": false, - "userSetupAllowed": false - } - ] - }, - { - "id": "f40cbe9a-ad2a-476c-b85d-ec426ce100b2", - "alias": "Handle Existing Account", - "description": "Handle what to do if there is existing account with same email/username like authenticated identity provider", - "providerId": "basic-flow", - "topLevel": false, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "idp-confirm-link", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 10, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticatorFlow": true, - "requirement": "REQUIRED", - "priority": 20, - "autheticatorFlow": true, - "flowAlias": "Account verification options", - "userSetupAllowed": false - } - ] - }, - { - "id": "60ba180d-92f3-4195-abd4-a925121994e7", - "alias": "Reset - Conditional OTP", - "description": "Flow to determine if the OTP should be reset or not. Set to REQUIRED to force.", - "providerId": "basic-flow", - "topLevel": false, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "conditional-user-configured", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 10, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticator": "reset-otp", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 20, - "autheticatorFlow": false, - "userSetupAllowed": false - } - ] - }, - { - "id": "0b5f7bb3-59e5-4d0e-9e8e-6d0e52984ad2", - "alias": "User creation or linking", - "description": "Flow for the existing/non-existing user alternatives", - "providerId": "basic-flow", - "topLevel": false, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticatorConfig": "create unique user config", - "authenticator": "idp-create-user-if-unique", - "authenticatorFlow": false, - "requirement": "ALTERNATIVE", - "priority": 10, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticatorFlow": true, - "requirement": "ALTERNATIVE", - "priority": 20, - "autheticatorFlow": true, - "flowAlias": "Handle Existing Account", - "userSetupAllowed": false - } - ] - }, - { - "id": "37290b7b-23f8-4653-ad2c-2593db5760f3", - "alias": "Verify Existing Account by Re-authentication", - "description": "Reauthentication of existing account", - "providerId": "basic-flow", - "topLevel": false, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "idp-username-password-form", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 10, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticatorFlow": true, - "requirement": "CONDITIONAL", - "priority": 20, - "autheticatorFlow": true, - "flowAlias": "First broker login - Conditional OTP", - "userSetupAllowed": false - } - ] - }, - { - "id": "2e5ceac1-9c0d-4109-b8f2-22c9efb00f0b", - "alias": "browser", - "description": "browser based authentication", - "providerId": "basic-flow", - "topLevel": true, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "auth-cookie", - "authenticatorFlow": false, - "requirement": "ALTERNATIVE", - "priority": 10, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticator": "auth-spnego", - "authenticatorFlow": false, - "requirement": "DISABLED", - "priority": 20, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticator": "identity-provider-redirector", - "authenticatorFlow": false, - "requirement": "ALTERNATIVE", - "priority": 25, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticatorFlow": true, - "requirement": "ALTERNATIVE", - "priority": 30, - "autheticatorFlow": true, - "flowAlias": "forms", - "userSetupAllowed": false - } - ] - }, - { - "id": "c35579f7-cd70-4c66-9ee7-c21bf7ddd1e0", - "alias": "clients", - "description": "Base authentication for clients", - "providerId": "client-flow", - "topLevel": true, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "client-secret", - "authenticatorFlow": false, - "requirement": "ALTERNATIVE", - "priority": 10, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticator": "client-jwt", - "authenticatorFlow": false, - "requirement": "ALTERNATIVE", - "priority": 20, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticator": "client-secret-jwt", - "authenticatorFlow": false, - "requirement": "ALTERNATIVE", - "priority": 30, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticator": "client-x509", - "authenticatorFlow": false, - "requirement": "ALTERNATIVE", - "priority": 40, - "autheticatorFlow": false, - "userSetupAllowed": false - } - ] - }, - { - "id": "c2487b50-dbf9-4536-be9d-940c8ac5eb21", - "alias": "direct grant", - "description": "OpenID Connect Resource Owner Grant", - "providerId": "basic-flow", - "topLevel": true, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "direct-grant-validate-username", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 10, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticator": "direct-grant-validate-password", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 20, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticatorFlow": true, - "requirement": "CONDITIONAL", - "priority": 30, - "autheticatorFlow": true, - "flowAlias": "Direct Grant - Conditional OTP", - "userSetupAllowed": false - } - ] - }, - { - "id": "e98419d1-4cb4-469d-a866-2adc9fdb4c6a", - "alias": "docker auth", - "description": "Used by Docker clients to authenticate against the IDP", - "providerId": "basic-flow", - "topLevel": true, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "docker-http-basic-authenticator", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 10, - "autheticatorFlow": false, - "userSetupAllowed": false - } - ] - }, - { - "id": "672acd89-be23-48ee-ac51-c5d846e77faf", - "alias": "first broker login", - "description": "Actions taken after first broker login with identity provider account, which is not yet linked to any Keycloak account", - "providerId": "basic-flow", - "topLevel": true, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticatorConfig": "review profile config", - "authenticator": "idp-review-profile", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 10, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticatorFlow": true, - "requirement": "REQUIRED", - "priority": 20, - "autheticatorFlow": true, - "flowAlias": "User creation or linking", - "userSetupAllowed": false - } - ] - }, - { - "id": "1099c284-d2f6-44de-b1b3-87d5cb0990c1", - "alias": "forms", - "description": "Username, password, otp and other auth forms.", - "providerId": "basic-flow", - "topLevel": false, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "auth-username-password-form", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 10, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticatorFlow": true, - "requirement": "CONDITIONAL", - "priority": 20, - "autheticatorFlow": true, - "flowAlias": "Browser - Conditional OTP", - "userSetupAllowed": false - } - ] - }, - { - "id": "d02c9502-c51d-4968-ba5d-d3771054e85a", - "alias": "http challenge", - "description": "An authentication flow based on challenge-response HTTP Authentication Schemes", - "providerId": "basic-flow", - "topLevel": true, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "no-cookie-redirect", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 10, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticatorFlow": true, - "requirement": "REQUIRED", - "priority": 20, - "autheticatorFlow": true, - "flowAlias": "Authentication Options", - "userSetupAllowed": false - } - ] - }, - { - "id": "18ee7c5d-3b4b-45c7-8d5a-761c2de30711", - "alias": "registration", - "description": "registration flow", - "providerId": "basic-flow", - "topLevel": true, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "registration-page-form", - "authenticatorFlow": true, - "requirement": "REQUIRED", - "priority": 10, - "autheticatorFlow": true, - "flowAlias": "registration form", - "userSetupAllowed": false - } - ] - }, - { - "id": "41c9dfb7-686d-4679-b471-abd04c08519d", - "alias": "registration form", - "description": "registration form", - "providerId": "form-flow", - "topLevel": false, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "registration-user-creation", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 20, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticator": "registration-profile-action", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 40, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticator": "registration-password-action", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 50, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticator": "registration-recaptcha-action", - "authenticatorFlow": false, - "requirement": "DISABLED", - "priority": 60, - "autheticatorFlow": false, - "userSetupAllowed": false - } - ] - }, - { - "id": "2d4c9ede-ca14-4454-bf7b-60e9c23b1951", - "alias": "reset credentials", - "description": "Reset credentials for a user if they forgot their password or something", - "providerId": "basic-flow", - "topLevel": true, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "reset-credentials-choose-user", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 10, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticator": "reset-credential-email", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 20, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticator": "reset-password", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 30, - "autheticatorFlow": false, - "userSetupAllowed": false - }, - { - "authenticatorFlow": true, - "requirement": "CONDITIONAL", - "priority": 40, - "autheticatorFlow": true, - "flowAlias": "Reset - Conditional OTP", - "userSetupAllowed": false - } - ] - }, - { - "id": "d1fea7bd-8e31-4b67-9cb8-b720c2b5b49c", - "alias": "saml ecp", - "description": "SAML ECP Profile Authentication Flow", - "providerId": "basic-flow", - "topLevel": true, - "builtIn": true, - "authenticationExecutions": [ - { - "authenticator": "http-basic-authenticator", - "authenticatorFlow": false, - "requirement": "REQUIRED", - "priority": 10, - "autheticatorFlow": false, - "userSetupAllowed": false - } - ] - } - ], - "authenticatorConfig": [ - { - "id": "519345fd-5f36-411f-ac29-9a28fea6e1f1", - "alias": "create unique user config", - "config": { - "require.password.update.after.registration": "false" - } - }, - { - "id": "2ad5fe8b-f6aa-4608-bbc2-cbf2ff218b67", - "alias": "review profile config", - "config": { - "update.profile.on.first.login": "missing" - } - } - ], - "requiredActions": [ - { - "alias": "CONFIGURE_TOTP", - "name": "Configure OTP", - "providerId": "CONFIGURE_TOTP", - "enabled": true, - "defaultAction": false, - "priority": 10, - "config": {} - }, - { - "alias": "TERMS_AND_CONDITIONS", - "name": "Terms and Conditions", - "providerId": "TERMS_AND_CONDITIONS", - "enabled": false, - "defaultAction": false, - "priority": 20, - "config": {} - }, - { - "alias": "UPDATE_PASSWORD", - "name": "Update Password", - "providerId": "UPDATE_PASSWORD", - "enabled": true, - "defaultAction": false, - "priority": 30, - "config": {} - }, - { - "alias": "UPDATE_PROFILE", - "name": "Update Profile", - "providerId": "UPDATE_PROFILE", - "enabled": true, - "defaultAction": false, - "priority": 40, - "config": {} - }, - { - "alias": "VERIFY_EMAIL", - "name": "Verify Email", - "providerId": "VERIFY_EMAIL", - "enabled": true, - "defaultAction": false, - "priority": 50, - "config": {} - }, - { - "alias": "delete_account", - "name": "Delete Account", - "providerId": "delete_account", - "enabled": false, - "defaultAction": false, - "priority": 60, - "config": {} - }, - { - "alias": "webauthn-register", - "name": "Webauthn Register", - "providerId": "webauthn-register", - "enabled": true, - "defaultAction": false, - "priority": 70, - "config": {} - }, - { - "alias": "webauthn-register-passwordless", - "name": "Webauthn Register Passwordless", - "providerId": "webauthn-register-passwordless", - "enabled": true, - "defaultAction": false, - "priority": 80, - "config": {} - }, - { - "alias": "update_user_locale", - "name": "Update User Locale", - "providerId": "update_user_locale", - "enabled": true, - "defaultAction": false, - "priority": 1000, - "config": {} - } - ], - "browserFlow": "browser", - "registrationFlow": "registration", - "directGrantFlow": "direct grant", - "resetCredentialsFlow": "reset credentials", - "clientAuthenticationFlow": "clients", - "dockerAuthenticationFlow": "docker auth", - "attributes": { - "cibaBackchannelTokenDeliveryMode": "poll", - "cibaAuthRequestedUserHint": "login_hint", - "clientOfflineSessionMaxLifespan": "0", - "oauth2DevicePollingInterval": "5", - "clientSessionIdleTimeout": "0", - "actionTokenGeneratedByUserLifespan-execute-actions": "", - "actionTokenGeneratedByUserLifespan-verify-email": "", - "clientOfflineSessionIdleTimeout": "0", - "actionTokenGeneratedByUserLifespan-reset-credentials": "", - "cibaInterval": "5", - "realmReusableOtpCode": "false", - "cibaExpiresIn": "120", - "oauth2DeviceCodeLifespan": "600", - "actionTokenGeneratedByUserLifespan-idp-verify-account-via-email": "", - "parRequestUriLifespan": "60", - "clientSessionMaxLifespan": "0" - }, - "keycloakVersion": "21.1", - "userManagedAccessAllowed": false, - "clientProfiles": { - "profiles": [] - }, - "clientPolicies": { - "policies": [] - } -} \ No newline at end of file diff --git a/edc-tests/miw-tests/src/test/resources/docker-environment/postgres/db.sh b/edc-tests/miw-tests/src/test/resources/docker-environment/postgres/db.sh deleted file mode 100755 index 0be008b1e..000000000 --- a/edc-tests/miw-tests/src/test/resources/docker-environment/postgres/db.sh +++ /dev/null @@ -1,28 +0,0 @@ -################################################################################# -# Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) -# -# See the NOTICE file(s) distributed with this work for additional -# information regarding copyright ownership. -# -# This program and the accompanying materials are made available under the -# terms of the Apache License, Version 2.0 which is available at -# https://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. -# -# SPDX-License-Identifier: Apache-2.0 -################################################################################# - -set -e - -psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL - CREATE DATABASE $POSTGRES_DB_NAME_MIW; - CREATE USER $POSTGRES_USERNAME_MIW WITH ENCRYPTED PASSWORD '$POSTGRES_PASSWORD_MIW'; - GRANT ALL PRIVILEGES ON DATABASE $POSTGRES_DB_NAME_MIW TO $POSTGRES_USERNAME_MIW; - \c $POSTGRES_DB_NAME_MIW - GRANT ALL ON SCHEMA public TO $POSTGRES_USERNAME_MIW; -EOSQL diff --git a/edc-tests/miw-tests/src/test/resources/docker-environment/postgres/seed.sh b/edc-tests/miw-tests/src/test/resources/docker-environment/postgres/seed.sh deleted file mode 100755 index 5c505a387..000000000 --- a/edc-tests/miw-tests/src/test/resources/docker-environment/postgres/seed.sh +++ /dev/null @@ -1,29 +0,0 @@ -#!/bin/bash -################################################################################# -# Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) -# -# See the NOTICE file(s) distributed with this work for additional -# information regarding copyright ownership. -# -# This program and the accompanying materials are made available under the -# terms of the Apache License, Version 2.0 which is available at -# https://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. -# -# SPDX-License-Identifier: Apache-2.0 -################################################################################# - -set -e - -psql -v ON_ERROR_STOP=1 --username "keycloak" --dbname "keycloak" <<-EOSQL - -- the following lines add one additional participant to MiW, used for the impersonation attack test - \c miw - INSERT INTO public.wallet (id, name, did, bpn, algorithm, did_document, created_at, modified_at, modified_from) VALUES (2, 'Another Participant', 'did:web:localhost%3A8000:BPNL000000000042', 'BPNL000000000042', 'ED25519', '{"verificationMethod":[{"publicKeyJwk":{"kty":"OKP","crv":"Ed25519","x":"Xok4qFXhNjMC3l-VHoQBJ_RHhtDmxevaoN13PE3j8MY"},"controller":"did:web:localhost%3A8000:BPNL000000000000","id":"did:web:localhost%3A8000:BPNL000000000000#","type":"JsonWebKey2020"}],"@context":"https://www.w3.org/ns/did/v1","id":"did:web:localhost%3A8000:BPNL000000000000"}', '2023-06-29 13:49:07.138000', '2023-06-29 13:49:07.140000', null); - INSERT INTO public.issuers_credential (id, holder_did, issuer_did, credential_id, credential_data, credential_type, created_at, modified_at, modified_from) VALUES (3, 'did:web:localhost%3A8000:BPNL000000000042', 'did:web:localhost%3A8000:BPNL000000000042', 'a043c406-d51d-4672-ad89-517c68d025f9', '{"issuanceDate":"2023-06-29T13:49:11Z","credentialSubject":[{"holderIdentifier":"BPNL000000000000","id":"did:web:localhost%3A8000:BPNL000000000000","type":"SummaryCredential","items":["BpnCredential"],"contractTemplates":"https://public.catena-x.org/contracts/"}],"id":"a043c406-d51d-4672-ad89-517c68d025f9","proof":{"assertionMethod":"did:web:localhost%3A8000:BPNL000000000000#","proofPurpose":"proofPurpose","type":"JsonWebSignature2020","created":"2023-06-29T13:49:11Z","jws":"eyJhbGciOiJFZERTQSJ9..waFlAQyE42TddNz0v4q_MkIbSgbjexDQqdt-k6LEQG3BvhE1Adj6SIERtUzmYowuLtdcTBbwVAROf9yzpfNMAg"},"type":["VerifiableCredential","SummaryCredential"],"@context":["https://www.w3.org/2018/credentials/v1","https://catenax-ng.github.io/product-core-schemas/SummaryVC.json"],"issuer":"did:web:localhost%3A8000:BPNL000000000000","expirationDate":"2025-01-01T00:00:00Z"}', 'SummaryCredential', '2023-06-29 13:49:11.870000', '2023-06-29 13:49:11.925000', null); - INSERT INTO public.holders_credential (id, holder_did, issuer_did, credential_id, credential_data, credential_type, created_at, modified_at, modified_from) VALUES (3, 'did:web:localhost%3A8000:BPNL000000000042', 'did:web:localhost%3A8000:BPNL000000000042', 'a043c406-d51d-4672-ad89-517c68d025f9', '{"issuanceDate":"2023-06-29T13:49:11Z","credentialSubject":[{"holderIdentifier":"BPNL000000000000","id":"did:web:localhost%3A8000:BPNL000000000000","type":"SummaryCredential","items":["BpnCredential"],"contractTemplates":"https://public.catena-x.org/contracts/"}],"id":"a043c406-d51d-4672-ad89-517c68d025f9","proof":{"assertionMethod":"did:web:localhost%3A8000:BPNL000000000000#","proofPurpose":"proofPurpose","type":"JsonWebSignature2020","created":"2023-06-29T13:49:11Z","jws":"eyJhbGciOiJFZERTQSJ9..waFlAQyE42TddNz0v4q_MkIbSgbjexDQqdt-k6LEQG3BvhE1Adj6SIERtUzmYowuLtdcTBbwVAROf9yzpfNMAg"},"type":["VerifiableCredential","SummaryCredential"],"@context":["https://www.w3.org/2018/credentials/v1","https://catenax-ng.github.io/product-core-schemas/SummaryVC.json"],"issuer":"did:web:localhost%3A8000:BPNL000000000000","expirationDate":"2025-01-01T00:00:00Z"}', 'SummaryCredential', '2023-06-29 13:49:11.870000', '2023-06-29 13:49:11.925000', null); -EOSQL diff --git a/edc-tests/miw-tests/src/test/resources/env-files/env.docker b/edc-tests/miw-tests/src/test/resources/env-files/env.docker deleted file mode 100644 index 30c2fe9a2..000000000 --- a/edc-tests/miw-tests/src/test/resources/env-files/env.docker +++ /dev/null @@ -1,52 +0,0 @@ -# Personal development data -GITHUB_USERNAME= -GITHUB_TOKEN= - -# Build -SKIP_GRADLE_TASKS_PARAM="-x jacocoTestCoverageVerification -x test" -DEV_ENVIRONMENT=docker - -# Docker: Postgres config -POSTGRES_DB=keycloak -POSTGRES_USER=keycloak -POSTGRES_PASSWORD=postgres -POSTGRES_DB_NAME_MIW=miw -POSTGRES_USERNAME_MIW=miw_user -POSTGRES_PASSWORD_MIW=postgres - -# Docker: Keycloak config -KEYCLOAK_MIW_PUBLIC_CLIENT=miw_public -DB_DATABASE=keycloak -KEYCLOAK_ADMIN=admin -KEYCLOAK_ADMIN_PASSWORD=admin -KC_HOSTNAME=keycloak -KC_HEALTH_ENABLED=true - -# Docker: App config -KEYCLOAK_CLIENT_ID=miw_private_client -ENCRYPTION_KEY=Woh9waid4Ei5eez0aitieghoow9so4oe -AUTHORITY_WALLET_BPN=BPNL000000000000 -AUTHORITY_WALLET_DID=did:web:miw:BPNL000000000000 -AUTHORITY_WALLET_NAME=Catena-X -KEYCLOAK_REALM=miw_test -VC_SCHEMA_LINK="https://www.w3.org/2018/credentials/v1, https://catenax-ng.github.io/product-core-schemas/businessPartnerData.json" -VC_EXPIRY_DATE=01-01-2025 -SUPPORTED_FRAMEWORK_VC_TYPES="PcfCredential, SustainabilityCredential, QualityCredential, TraceabilityCredential, BehaviorTwinCredential, ResiliencyCredential" -MIW_HOST_NAME=localhost:8000 -ENFORCE_HTTPS_IN_DID_RESOLUTION=false - -######### DON'T MODIFY ANYTHING BELOW THIS LINE !!! ######### -AUTH_SERVER_URL=http://keycloak:8080 -DEV_ENVIRONMENT=docker -APPLICATION_PORT=8000 -MANAGEMENT_PORT=8090 -APPLICATION_ENVIRONMENT=dev -DB_HOST=postgres -DB_PORT=5432 -USE_SSL=false -DB_USER=${POSTGRES_USER} -DB_NAME=${POSTGRES_DB_NAME_MIW} -DB_USER_NAME=${POSTGRES_USERNAME_MIW} -DB_PASSWORD=${POSTGRES_PASSWORD_MIW} -ORG_GRADLE_PROJECT_githubUserName=${GITHUB_USERNAME} -ORG_GRADLE_PROJECT_githubToken=${GITHUB_TOKEN} diff --git a/edc-tests/runtime/iatp/runtime-memory-iatp-dim-ih/build.gradle.kts b/edc-tests/runtime/iatp/runtime-memory-iatp-dim-ih/build.gradle.kts index 336d021f4..78de2f073 100644 --- a/edc-tests/runtime/iatp/runtime-memory-iatp-dim-ih/build.gradle.kts +++ b/edc-tests/runtime/iatp/runtime-memory-iatp-dim-ih/build.gradle.kts @@ -26,10 +26,7 @@ dependencies { // use basic (all in-mem) control plane implementation(project(":edc-controlplane:edc-controlplane-base")) { - exclude(module = "ssi-identity-core") - exclude(module = "ssi-miw-credential-client") - exclude(module = "ssi-identity-extractor") - exclude(module = "cx-policy-legacy") + exclude(module = "bdrs-client") } implementation(project(":core:json-ld-core")) implementation(project(":edc-extensions:iatp:tx-iatp")) @@ -44,8 +41,8 @@ dependencies { } implementation(libs.edc.core.controlplane) - implementation(libs.edc.identity.core.trust) - implementation(libs.edc.identity.core.did) + implementation(libs.edc.core.identitytrust) + implementation(libs.edc.core.did) implementation(libs.edc.identity.trust.transform) implementation(libs.edc.identity.trust.issuers.configuration) implementation(libs.edc.auth.oauth2.client) diff --git a/edc-tests/runtime/iatp/runtime-memory-iatp-dim/build.gradle.kts b/edc-tests/runtime/iatp/runtime-memory-iatp-dim/build.gradle.kts index 373987e6a..c9ebd1ba2 100644 --- a/edc-tests/runtime/iatp/runtime-memory-iatp-dim/build.gradle.kts +++ b/edc-tests/runtime/iatp/runtime-memory-iatp-dim/build.gradle.kts @@ -25,12 +25,7 @@ plugins { dependencies { // use basic (all in-mem) control plane - implementation(project(":edc-controlplane:edc-controlplane-base")) { - exclude(module = "ssi-identity-core") - exclude(module = "ssi-miw-credential-client") - exclude(module = "ssi-identity-extractor") - exclude(module = "cx-policy-legacy") - } + implementation(project(":edc-controlplane:edc-controlplane-base")) implementation(project(":edc-extensions:cx-policy")) implementation(project(":core:json-ld-core")) implementation(project(":edc-extensions:iatp:tx-iatp")) @@ -45,8 +40,8 @@ dependencies { } implementation(libs.edc.core.controlplane) - implementation(libs.edc.identity.core.trust) - implementation(libs.edc.identity.core.did) + implementation(libs.edc.core.identitytrust) + implementation(libs.edc.core.did) implementation(libs.edc.identity.did.web) implementation(libs.edc.identity.trust.transform) implementation(libs.edc.identity.trust.issuers.configuration) diff --git a/edc-tests/runtime/iatp/runtime-memory-iatp-ih/build.gradle.kts b/edc-tests/runtime/iatp/runtime-memory-iatp-ih/build.gradle.kts index 94429bd90..3097edb1e 100644 --- a/edc-tests/runtime/iatp/runtime-memory-iatp-ih/build.gradle.kts +++ b/edc-tests/runtime/iatp/runtime-memory-iatp-ih/build.gradle.kts @@ -26,10 +26,7 @@ dependencies { // use basic (all in-mem) control plane implementation(project(":edc-controlplane:edc-controlplane-base")) { - exclude(module = "ssi-identity-core") - exclude(module = "ssi-miw-credential-client") - exclude(module = "ssi-identity-extractor") - exclude(module = "cx-policy-legacy") + exclude(module = "bdrs-client") exclude(module = "tx-iatp-sts-dim") } implementation(project(":edc-extensions:cx-policy")) @@ -45,8 +42,8 @@ dependencies { } implementation(libs.edc.core.controlplane) - implementation(libs.edc.identity.core.trust) - implementation(libs.edc.identity.core.did) + implementation(libs.edc.core.identitytrust) + implementation(libs.edc.core.did) implementation(libs.edc.identity.trust.transform) implementation(libs.edc.identity.trust.sts.remote) implementation(libs.edc.identity.trust.issuers.configuration) diff --git a/edc-tests/runtime/iatp/runtime-memory-sts/build.gradle.kts b/edc-tests/runtime/iatp/runtime-memory-sts/build.gradle.kts index 5bd47e714..b83afc130 100644 --- a/edc-tests/runtime/iatp/runtime-memory-sts/build.gradle.kts +++ b/edc-tests/runtime/iatp/runtime-memory-sts/build.gradle.kts @@ -29,7 +29,6 @@ dependencies { exclude(module = "ssi-identity-core") exclude(module = "ssi-miw-credential-client") exclude(module = "ssi-identity-extractor") - exclude(module = "cx-policy-legacy") exclude(module = "tx-iatp-sts-dim") } implementation(project(":core:json-ld-core")) diff --git a/edc-tests/runtime/runtime-memory-ssi/README.md b/edc-tests/runtime/runtime-memory-ssi/README.md deleted file mode 100644 index 2f9593a75..000000000 --- a/edc-tests/runtime/runtime-memory-ssi/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# In-Memory Runtime for Testing Purposes - -This module provides a very small, purely in-mem runtime to execute tests against. Not intended for anything other than testing! diff --git a/edc-tests/runtime/runtime-memory-ssi/build.gradle.kts b/edc-tests/runtime/runtime-memory-ssi/build.gradle.kts deleted file mode 100644 index fab744c27..000000000 --- a/edc-tests/runtime/runtime-memory-ssi/build.gradle.kts +++ /dev/null @@ -1,57 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -plugins { - `java-library` - id("application") -} - - -dependencies { - - // use basic (all in-mem) control plane - implementation(project(":edc-controlplane:edc-controlplane-base")) - implementation(project(":core:json-ld-core")) - - - implementation(project(":edc-extensions:ssi:ssi-identity-core")) - implementation(project(":edc-extensions:ssi:ssi-miw-credential-client")) - implementation(project(":edc-extensions:ssi:ssi-identity-extractor")) - implementation(project(":edc-extensions:cx-policy-legacy")) - - implementation(project(":edc-tests:runtime:extensions")) - - // use basic (all in-mem) data plane - runtimeOnly(project(":edc-dataplane:edc-dataplane-base")) { - exclude("org.eclipse.edc", "api-observability") - } - - - implementation(libs.edc.core.controlplane) - // for the controller - implementation(libs.jakarta.rsApi) -} - -application { - mainClass.set("org.eclipse.edc.boot.system.runtime.BaseRuntime") -} - -edcBuild { - publish.set(false) -} diff --git a/edc-tests/runtime/runtime-memory/build.gradle.kts b/edc-tests/runtime/runtime-memory/build.gradle.kts index 6cb248998..448119c86 100644 --- a/edc-tests/runtime/runtime-memory/build.gradle.kts +++ b/edc-tests/runtime/runtime-memory/build.gradle.kts @@ -31,7 +31,6 @@ dependencies { exclude(module = "ssi-identity-core") exclude(module = "ssi-miw-credential-client") exclude(module = "ssi-identity-extractor") - exclude(module = "cx-policy-legacy") exclude(module = "tx-iatp-sts-dim") } diff --git a/edc-tests/runtime/runtime-postgresql/build.gradle.kts b/edc-tests/runtime/runtime-postgresql/build.gradle.kts index c50092596..a03e1746d 100644 --- a/edc-tests/runtime/runtime-postgresql/build.gradle.kts +++ b/edc-tests/runtime/runtime-postgresql/build.gradle.kts @@ -31,7 +31,6 @@ dependencies { exclude(module = "ssi-identity-core") exclude(module = "ssi-miw-credential-client") exclude(module = "ssi-identity-extractor") - exclude(module = "cx-policy-legacy") exclude(module = "tx-iatp-sts-dim") exclude(group = "org.eclipse.edc", "vault-hashicorp") } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 2e6ab4618..5dd19b8c2 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -2,7 +2,7 @@ format.version = "1.1" [versions] -edc = "0.6.0" +edc = "0.6.1-SNAPSHOT" apache-sshd = "2.12.1" assertj = "3.25.3" awaitility = "4.2.0" @@ -41,7 +41,6 @@ edc-controlplane-apiclient = { module = "org.eclipse.edc:control-plane-api-clien edc-spi-web = { module = "org.eclipse.edc:web-spi", version.ref = "edc" } edc-spi-http = { module = "org.eclipse.edc:http-spi", version.ref = "edc" } edc-spi-keys = { module = "org.eclipse.edc:keys-spi", version.ref = "edc" } -edc-spi-identitytrust = { module = "org.eclipse.edc:identity-trust-spi", version.ref = "edc" } edc-spi-jsonld = { module = "org.eclipse.edc:json-ld-spi", version.ref = "edc" } edc-spi-jwt = { module = "org.eclipse.edc:jwt-spi", version.ref = "edc" } edc-spi-token = { module = "org.eclipse.edc:token-spi", version.ref = "edc" } @@ -125,9 +124,9 @@ edc-controlplane-callback-dispatcher-event = { module = "org.eclipse.edc:callbac edc-controlplane-callback-dispatcher-http = { module = "org.eclipse.edc:callback-http-dispatcher", version.ref = "edc" } # IATP Modules -edc-identity-trust-spi = { module = "org.eclipse.edc:identity-trust-spi", version.ref = "edc" } -edc-identity-core-trust = { module = "org.eclipse.edc:identity-trust-core", version.ref = "edc" } -edc-identity-core-did = { module = "org.eclipse.edc:identity-did-core", version.ref = "edc" } +edc-spi-identitytrust = { module = "org.eclipse.edc:identity-trust-spi", version.ref = "edc" } +edc-core-identitytrust = { module = "org.eclipse.edc:identity-trust-core", version.ref = "edc" } +edc-core-did = { module = "org.eclipse.edc:identity-did-core", version.ref = "edc" } edc-identity-did-web = { module = "org.eclipse.edc:identity-did-web", version.ref = "edc" } edc-identity-vc-ldp = { module = "org.eclipse.edc:ldp-verifiable-credentials", version.ref = "edc" } diff --git a/samples/multi-tenancy/src/main/java/org/eclipse/tractusx/edc/samples/multitenancy/MultiTenantRuntime.java b/samples/multi-tenancy/src/main/java/org/eclipse/tractusx/edc/samples/multitenancy/MultiTenantRuntime.java index fac9b12cf..d7ac26513 100644 --- a/samples/multi-tenancy/src/main/java/org/eclipse/tractusx/edc/samples/multitenancy/MultiTenantRuntime.java +++ b/samples/multi-tenancy/src/main/java/org/eclipse/tractusx/edc/samples/multitenancy/MultiTenantRuntime.java @@ -51,11 +51,6 @@ protected void boot() { loadTenantsConfig().getConfig("edc.tenants").partition().forEach(this::bootTenant); } - @Override - protected void onError(Exception e) { - throw new EdcException(e); - } - private void bootTenant(Config tenantConfig) { var baseProperties = System.getProperties(); tenantConfig.getRelativeEntries().forEach(System::setProperty); diff --git a/settings.gradle.kts b/settings.gradle.kts index 88ad36697..d582762f0 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -23,7 +23,6 @@ rootProject.name = "tractusx-edc" include(":spi:callback-spi") include(":spi:edr-spi") include(":spi:core-spi") -include(":spi:ssi-spi") include(":spi:tokenrefresh-spi") @@ -49,10 +48,6 @@ include(":edc-extensions:transferprocess-sftp-provisioner") include(":edc-extensions:edr:edr-api-v2") include(":edc-extensions:edr:edr-callback") include(":edc-extensions:cx-policy") -include(":edc-extensions:cx-policy-legacy") -include(":edc-extensions:ssi:ssi-identity-core") -include(":edc-extensions:ssi:ssi-miw-credential-client") -include(":edc-extensions:ssi:ssi-identity-extractor") include(":edc-extensions:iatp:tx-iatp") include(":edc-extensions:iatp:tx-iatp-sts-dim") @@ -69,13 +64,10 @@ include(":edc-tests:edc-controlplane:catalog-tests") include(":edc-tests:edc-controlplane:transfer-tests") include(":edc-tests:edc-controlplane:iatp-tests") include(":edc-tests:edc-controlplane:policy-tests") -include(":edc-tests:edc-controlplane:ssi-summarycred-tests") include(":edc-tests:edc-controlplane:fixtures") -include(":edc-tests:miw-tests") include(":edc-tests:runtime:extensions") include(":edc-tests:runtime:runtime-memory") include(":edc-tests:runtime:dataplane-cloud") -include(":edc-tests:runtime:runtime-memory-ssi") include(":edc-tests:runtime:runtime-postgresql") include(":edc-tests:runtime:iatp:runtime-memory-iatp-ih") include(":edc-tests:runtime:iatp:runtime-memory-iatp-dim-ih") diff --git a/spi/ssi-spi/build.gradle.kts b/spi/ssi-spi/build.gradle.kts deleted file mode 100644 index c934a34f0..000000000 --- a/spi/ssi-spi/build.gradle.kts +++ /dev/null @@ -1,35 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -plugins { - `java-library` - `java-test-fixtures` -} - -dependencies { - implementation(libs.edc.spi.core) - implementation(libs.edc.spi.jwt) - implementation(libs.edc.spi.token) - implementation(libs.jakartaJson) - - testFixturesImplementation(libs.jacksonJsonP) - testFixturesImplementation(libs.jackson.datatypeJsr310) - testFixturesImplementation(libs.titaniumJsonLd) - testFixturesImplementation(libs.jackson.datatypeJsr310) -} diff --git a/spi/ssi-spi/src/main/java/org/eclipse/tractusx/edc/iam/ssi/spi/SsiConstants.java b/spi/ssi-spi/src/main/java/org/eclipse/tractusx/edc/iam/ssi/spi/SsiConstants.java deleted file mode 100644 index 87d1896b4..000000000 --- a/spi/ssi-spi/src/main/java/org/eclipse/tractusx/edc/iam/ssi/spi/SsiConstants.java +++ /dev/null @@ -1,25 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.iam.ssi.spi; - -public interface SsiConstants { - String SSI_TOKEN_CONTEXT = "ssi-token-context"; - -} diff --git a/spi/ssi-spi/src/main/java/org/eclipse/tractusx/edc/iam/ssi/spi/SsiCredentialClient.java b/spi/ssi-spi/src/main/java/org/eclipse/tractusx/edc/iam/ssi/spi/SsiCredentialClient.java deleted file mode 100644 index e422455f6..000000000 --- a/spi/ssi-spi/src/main/java/org/eclipse/tractusx/edc/iam/ssi/spi/SsiCredentialClient.java +++ /dev/null @@ -1,53 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.iam.ssi.spi; - -import org.eclipse.edc.runtime.metamodel.annotation.ExtensionPoint; -import org.eclipse.edc.spi.iam.ClaimToken; -import org.eclipse.edc.spi.iam.TokenParameters; -import org.eclipse.edc.spi.iam.TokenRepresentation; -import org.eclipse.edc.spi.result.Result; - -/** - * Obtains client security tokens from an identity provider. - * Providers may implement different authorization protocols such as OAuth2. - */ - -@ExtensionPoint -public interface SsiCredentialClient { - - /** - * Obtains a client token encoded as a JWT. - * - * @param parameters parameter object defining the token properties. - * @return generated client token. - */ - - Result obtainClientCredentials(TokenParameters parameters); - - /** - * Verifies a JWT bearer token. - * - * @param tokenRepresentation A token representation including the token to verify. - * @return Result of the validation. - */ - - Result validate(TokenRepresentation tokenRepresentation); -} diff --git a/spi/ssi-spi/src/main/java/org/eclipse/tractusx/edc/iam/ssi/spi/SsiTokenValidationService.java b/spi/ssi-spi/src/main/java/org/eclipse/tractusx/edc/iam/ssi/spi/SsiTokenValidationService.java deleted file mode 100644 index 05f3a6a7b..000000000 --- a/spi/ssi-spi/src/main/java/org/eclipse/tractusx/edc/iam/ssi/spi/SsiTokenValidationService.java +++ /dev/null @@ -1,38 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.iam.ssi.spi; - -import org.eclipse.edc.runtime.metamodel.annotation.ExtensionPoint; -import org.eclipse.edc.spi.iam.ClaimToken; -import org.eclipse.edc.spi.iam.TokenRepresentation; -import org.eclipse.edc.spi.result.Result; -import org.eclipse.edc.token.spi.TokenValidationRule; - -import java.util.List; - -/** - * Validates SSI tokens - */ - -@ExtensionPoint -public interface SsiTokenValidationService { - - Result validate(TokenRepresentation tokenRepresentation, List rules); -} diff --git a/spi/ssi-spi/src/main/java/org/eclipse/tractusx/edc/iam/ssi/spi/jsonld/CredentialsNamespaces.java b/spi/ssi-spi/src/main/java/org/eclipse/tractusx/edc/iam/ssi/spi/jsonld/CredentialsNamespaces.java deleted file mode 100644 index 48a11fb1b..000000000 --- a/spi/ssi-spi/src/main/java/org/eclipse/tractusx/edc/iam/ssi/spi/jsonld/CredentialsNamespaces.java +++ /dev/null @@ -1,49 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.iam.ssi.spi.jsonld; - -/** - * Defines policy namespaces. - */ -public interface CredentialsNamespaces { - - String W3C_VC_PREFIX = "https://www.w3.org/2018/credentials"; - String W3C_VC_NS = W3C_VC_PREFIX + "/v1"; - String VP_PROPERTY = "vp"; - @Deprecated - String CX_NS = "https://w3id.org/2023/catenax/credentials/"; - @Deprecated - String CX_SUMMARY_NS = CX_NS + "summary"; - @Deprecated - String CX_SUMMARY_NS_V1 = CX_SUMMARY_NS + "/v1"; - @Deprecated - String SUMMARY_CREDENTIAL_TYPE = CX_SUMMARY_NS + "/SummaryCredential"; - @Deprecated - String HOLDER_IDENTIFIER = CX_SUMMARY_NS + "/holderIdentifier"; - @Deprecated - String CX_USE_CASE_NS = CX_NS + "usecase"; - @Deprecated - String CX_USE_CASE_NS_V1 = CX_USE_CASE_NS + "/v1"; - @Deprecated - String CX_SUMMARY_CREDENTIAL = "SummaryCredential"; - String CREDENTIAL_SUBJECT = W3C_VC_PREFIX + "#credentialSubject"; - String CREDENTIAL_ISSUER = W3C_VC_PREFIX + "#issuer"; - -} diff --git a/spi/ssi-spi/src/main/java/org/eclipse/tractusx/edc/iam/ssi/spi/jsonld/JsonLdFieldExtractor.java b/spi/ssi-spi/src/main/java/org/eclipse/tractusx/edc/iam/ssi/spi/jsonld/JsonLdFieldExtractor.java deleted file mode 100644 index 1d9e6df46..000000000 --- a/spi/ssi-spi/src/main/java/org/eclipse/tractusx/edc/iam/ssi/spi/jsonld/JsonLdFieldExtractor.java +++ /dev/null @@ -1,98 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.iam.ssi.spi.jsonld; - -import jakarta.json.JsonObject; -import org.eclipse.edc.spi.result.Result; - -import java.util.Objects; - -import static jakarta.json.JsonValue.ValueType.ARRAY; -import static jakarta.json.JsonValue.ValueType.OBJECT; -import static java.lang.String.format; - -/** - * Extractor for field from a {@link JsonObject} with a customizable error reporting - */ -public class JsonLdFieldExtractor { - - private String fieldAlias; - private String errorPrefix = ""; - private String field; - - private JsonLdFieldExtractor() { - } - - /** - * Extract a field by name. If not found return an error. - */ - public Result extract(JsonObject root) { - var subjectArray = root.get(field); - if (subjectArray == null || subjectArray.getValueType() != ARRAY) { - return Result.failure(errorPrefix + format(" no %s found", fieldAlias)); - } - if (subjectArray.asJsonArray().size() != 1) { - return Result.failure(errorPrefix + format(" empty %s", fieldAlias)); - } - - var subjectValue = subjectArray.asJsonArray().get(0); - if (subjectValue == null || subjectValue.getValueType() != OBJECT) { - return Result.failure(errorPrefix + format(" invalid %s format", fieldAlias)); - } - return Result.success(subjectValue.asJsonObject()); - } - - public static class Builder { - - private final JsonLdFieldExtractor extractor; - - private Builder(JsonLdFieldExtractor extractor) { - this.extractor = extractor; - } - - public static Builder newInstance() { - return new Builder(new JsonLdFieldExtractor()); - } - - public Builder field(String field) { - this.extractor.field = field; - return this; - } - - public Builder fieldAlias(String fieldAlias) { - this.extractor.fieldAlias = fieldAlias; - return this; - } - - public Builder errorPrefix(String errorPrefix) { - this.extractor.errorPrefix = errorPrefix; - return this; - } - - public JsonLdFieldExtractor build() { - Objects.requireNonNull(extractor.field); - Objects.requireNonNull(extractor.fieldAlias); - Objects.requireNonNull(extractor.errorPrefix); - return extractor; - } - - } - -} diff --git a/spi/ssi-spi/src/main/java/org/eclipse/tractusx/edc/iam/ssi/spi/jsonld/JsonLdTypeFunctions.java b/spi/ssi-spi/src/main/java/org/eclipse/tractusx/edc/iam/ssi/spi/jsonld/JsonLdTypeFunctions.java deleted file mode 100644 index e3b5f80d0..000000000 --- a/spi/ssi-spi/src/main/java/org/eclipse/tractusx/edc/iam/ssi/spi/jsonld/JsonLdTypeFunctions.java +++ /dev/null @@ -1,111 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.iam.ssi.spi.jsonld; - -import jakarta.json.JsonArray; -import jakarta.json.JsonObject; -import jakarta.json.JsonString; -import jakarta.json.JsonStructure; -import jakarta.json.JsonValue; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Set; -import java.util.stream.Stream; - -import static java.util.Collections.emptySet; -import static java.util.stream.Collectors.toSet; - -/** - * Provides functions for working with Json-Ld types. - */ -public class JsonLdTypeFunctions { - private static final String TYPE = "@type"; - private static final Stream EMPTY_STREAM = Stream.of(); - - private JsonLdTypeFunctions() { - } - - /** - * Returns a stream of objects that are of the given Json-Ld type starting at the root. - * - * @param typeValue the type to include - * @param root the root object to traverse - * @return the stream of types - */ - public static Stream extractObjectsOfType(String typeValue, JsonStructure root) { - if (root instanceof JsonObject rootObject) { - return matchTypeValue(typeValue, rootObject.get(TYPE)) ? Stream.of(rootObject) : - extractObjectsOfType(typeValue, rootObject.values().stream()); - } else if (root instanceof JsonArray rootArray) { - return extractObjectsOfType(typeValue, rootArray.stream()); - } - return EMPTY_STREAM; - } - - /** - * Returns a stream of objects that are of the given Json-Ld type in the stream. - * - * @param typeValue the type to include - * @param stream the stream of roots to traverse - * @return the stream of types - */ - public static Stream extractObjectsOfType(String typeValue, Stream stream) { - return stream.filter(v -> v instanceof JsonStructure) - .flatMap(v -> extractObjectsOfType(typeValue, (JsonStructure) v)).filter(Objects::nonNull); - } - - /** - * Partitions a stream of objects by their type, returning a type-to-collection mapping. - */ - public static Map> partitionByType(Stream stream) { - var partitions = new HashMap>(); - stream.forEach(object -> getTypes(object).forEach(type -> partitions.computeIfAbsent(type, k -> new ArrayList<>()).add(object))); - return partitions; - } - - /** - * Returns the types associated with the object - */ - private static Set getTypes(JsonObject object) { - var result = object.get(TYPE); - if (result instanceof JsonArray resultArray) { - return resultArray.stream().filter(e -> e instanceof JsonString).map(s -> ((JsonString) s).getString()).collect(toSet()); - } else if (result instanceof JsonString resultString) { - return Set.of(resultString.getString()); - } - return emptySet(); - } - - /** - * Returns true if the type value matches the Json value. - */ - private static boolean matchTypeValue(String typeValue, JsonValue jsonValue) { - if (jsonValue instanceof JsonString stringValue) { - return typeValue.equals(stringValue.getString()); - } else if (jsonValue instanceof JsonArray arrayValue) { - return arrayValue.stream().anyMatch(v -> v instanceof JsonString && typeValue.equals(((JsonString) v).getString())); - } - return false; - } -} diff --git a/spi/ssi-spi/src/main/java/org/eclipse/tractusx/edc/iam/ssi/spi/jsonld/JsonLdValueFunctions.java b/spi/ssi-spi/src/main/java/org/eclipse/tractusx/edc/iam/ssi/spi/jsonld/JsonLdValueFunctions.java deleted file mode 100644 index e0abefdc7..000000000 --- a/spi/ssi-spi/src/main/java/org/eclipse/tractusx/edc/iam/ssi/spi/jsonld/JsonLdValueFunctions.java +++ /dev/null @@ -1,76 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.iam.ssi.spi.jsonld; - -import jakarta.json.JsonArray; -import jakarta.json.JsonNumber; -import jakarta.json.JsonObject; -import jakarta.json.JsonString; -import jakarta.json.JsonValue; -import org.jetbrains.annotations.Nullable; - -import static jakarta.json.JsonValue.ValueType; - -/** - * Functions for working with Json-ld values. - */ -public class JsonLdValueFunctions { - private static final String VALUE = "@value"; - - private JsonLdValueFunctions() { - } - - /** - * Extracts the value of a root node and converts it to a string representation. Note this method accepts null nodes as a convenience. - */ - @Nullable - public static String extractStringValue(@Nullable JsonValue root) { - if (root == null) { - return null; - } else if (root instanceof JsonArray rootArray) { - if (rootArray.isEmpty()) { - return null; - } - var jsonValue = rootArray.get(0); - return (jsonValue instanceof JsonObject elementObject) ? convertType(elementObject.get(VALUE)) : null; - } else if (root instanceof JsonObject rootObject) { - return convertType(rootObject.get(VALUE)); - } else { - return convertType(root); - } - } - - /** - * Converts the value to a string representation. - */ - @Nullable - private static String convertType(JsonValue value) { - if (value instanceof JsonString valueString) { - return valueString.getString(); - } else if (value instanceof JsonNumber valueNumber) { - return valueNumber.isIntegral() ? String.valueOf(valueNumber.longValue()) : String.valueOf(valueNumber.doubleValue()); - } else if (ValueType.TRUE == value.getValueType()) { - return "TRUE"; - } else if (ValueType.FALSE == value.getValueType()) { - return "FALSE"; - } - return null; - } -} diff --git a/spi/ssi-spi/src/test/java/org/eclipse/tractusx/edc/iam/ssi/spi/jsonld/JsonLdFieldExtractorTest.java b/spi/ssi-spi/src/test/java/org/eclipse/tractusx/edc/iam/ssi/spi/jsonld/JsonLdFieldExtractorTest.java deleted file mode 100644 index 9e7cb3b66..000000000 --- a/spi/ssi-spi/src/test/java/org/eclipse/tractusx/edc/iam/ssi/spi/jsonld/JsonLdFieldExtractorTest.java +++ /dev/null @@ -1,80 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.iam.ssi.spi.jsonld; - -import jakarta.json.JsonObject; -import org.eclipse.edc.spi.result.Result; -import org.junit.jupiter.api.Test; - -import java.util.Map; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.eclipse.tractusx.edc.iam.ssi.spi.jsonld.CredentialsNamespaces.CREDENTIAL_SUBJECT; -import static org.eclipse.tractusx.edc.iam.ssi.spi.jsonld.CredentialsNamespaces.CX_SUMMARY_NS_V1; -import static org.eclipse.tractusx.edc.iam.ssi.spi.jsonld.CredentialsNamespaces.HOLDER_IDENTIFIER; -import static org.eclipse.tractusx.edc.iam.ssi.spi.jsonld.CredentialsNamespaces.SUMMARY_CREDENTIAL_TYPE; -import static org.eclipse.tractusx.edc.iam.ssi.spi.jsonld.JsonLdTextFixtures.createObjectMapper; -import static org.eclipse.tractusx.edc.iam.ssi.spi.jsonld.JsonLdTextFixtures.expand; -import static org.eclipse.tractusx.edc.iam.ssi.spi.jsonld.JsonLdTypeFunctions.extractObjectsOfType; -import static org.eclipse.tractusx.edc.iam.ssi.spi.jsonld.SummaryCredential.SUMMARY_VP; - -public class JsonLdFieldExtractorTest { - - private static final Map CONTEXT_CACHE = Map.of(CX_SUMMARY_NS_V1, SummaryContext.SUMMARY_CONTEXT); - - @Test - void extract() throws Exception { - var vp = expand(createObjectMapper().readValue(SUMMARY_VP, JsonObject.class), CONTEXT_CACHE); - - var extractor = JsonLdFieldExtractor.Builder.newInstance() - .field(CREDENTIAL_SUBJECT) - .fieldAlias("credentialSubject") - .errorPrefix("prefix") - .build(); - - - var summaryCredential = extractObjectsOfType(SUMMARY_CREDENTIAL_TYPE, vp).findFirst().orElseThrow(); - - var subject = extractor.extract(summaryCredential); - assertThat(subject).matches(Result::succeeded).extracting(Result::getContent) - .satisfies(jsonObject -> assertThat(jsonObject.containsKey(HOLDER_IDENTIFIER)).isTrue()); - - } - - @Test - void extract_fail() throws Exception { - var vp = expand(createObjectMapper().readValue(SUMMARY_VP, JsonObject.class), CONTEXT_CACHE); - - var extractor = JsonLdFieldExtractor.Builder.newInstance() - .field(HOLDER_IDENTIFIER) - .fieldAlias("holderIdentifier") - .errorPrefix("prefix") - .build(); - - var summaryCredential = extractObjectsOfType(SUMMARY_CREDENTIAL_TYPE, vp).findFirst().orElseThrow(); - - var subject = extractor.extract(summaryCredential); - assertThat(subject).matches(Result::failed).extracting(Result::getFailureDetail) - .satisfies(errorMessage -> { - assertThat(errorMessage).isEqualTo("prefix no holderIdentifier found"); - }); - - } -} diff --git a/spi/ssi-spi/src/test/java/org/eclipse/tractusx/edc/iam/ssi/spi/jsonld/JsonLdTypeFunctionsTest.java b/spi/ssi-spi/src/test/java/org/eclipse/tractusx/edc/iam/ssi/spi/jsonld/JsonLdTypeFunctionsTest.java deleted file mode 100644 index a8acea1a9..000000000 --- a/spi/ssi-spi/src/test/java/org/eclipse/tractusx/edc/iam/ssi/spi/jsonld/JsonLdTypeFunctionsTest.java +++ /dev/null @@ -1,132 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.iam.ssi.spi.jsonld; - -import com.fasterxml.jackson.core.JsonProcessingException; -import jakarta.json.JsonObject; -import jakarta.json.JsonString; -import org.junit.jupiter.api.Test; - -import java.util.List; -import java.util.Map; - -import static java.lang.String.format; -import static org.assertj.core.api.Assertions.assertThat; -import static org.eclipse.tractusx.edc.iam.ssi.spi.jsonld.CredentialsNamespaces.W3C_VC_PREFIX; -import static org.eclipse.tractusx.edc.iam.ssi.spi.jsonld.JsonLdTextFixtures.createObjectMapper; -import static org.eclipse.tractusx.edc.iam.ssi.spi.jsonld.JsonLdTextFixtures.expand; -import static org.eclipse.tractusx.edc.iam.ssi.spi.jsonld.JsonLdTypeFunctions.extractObjectsOfType; -import static org.eclipse.tractusx.edc.iam.ssi.spi.jsonld.JsonLdTypeFunctions.partitionByType; - -class JsonLdTypeFunctionsTest { - private static final String TYPE = "@type"; - private static final String VC_TYPE = W3C_VC_PREFIX + "#VerifiableCredential"; - - private static final String BAR_CREDENTIAL_TYPE = "BarCredential"; - private static final String FOO_CREDENTIAL_TYPE = "FooCredential"; - private static final String FOO_CREDENTIAL = """ - { - "type": "VerifiablePresentation", - "verifiableCredential": [ - { - "@context": [ - "https://www.w3.org/2018/credentials/v1" - ], - "id": "urn:uuid:12345678-1234-1234-1234-123456789abc", - "type": [ - "VerifiableCredential", - "FooCredential" - ] - } - ] - }"""; - private static final String BAR_CREDENTIAL = """ - { - "type": "VerifiablePresentation", - "verifiableCredential": [ - { - "@context": [ - "https://www.w3.org/2018/credentials/v1" - ], - "type": [ - "VerifiableCredential", - "BarCredential" - ] - } - ] - }"""; - private static final String MULTIPLE_VCS_CLAIM = format(""" - { - "@context": [ - "https://www.w3.org/2018/credentials/v1", - { - "vp":"test:vp" - } - ], - "vp": [%s,%s] - }""", FOO_CREDENTIAL, BAR_CREDENTIAL); - private static final String SINGLE_VC_CLAIM = format(""" - { - "@context": [ - "https://www.w3.org/2018/credentials/v1", - { - "vp":"test:vp" - } - ], - "vp": %s - }""", FOO_CREDENTIAL); - - @Test - void verify_credential_extraction() throws JsonProcessingException { - var vp = expand(createObjectMapper().readValue(SINGLE_VC_CLAIM, JsonObject.class), Map.of()); - - var credentials = extractObjectsOfType(VC_TYPE, vp).toList(); - - assertThat(credentials.size()).isEqualTo(1); - assertAllOfType(FOO_CREDENTIAL_TYPE, credentials); - } - - @Test - void verify_partitions_based_on_type() throws JsonProcessingException { - var vp = expand(createObjectMapper().readValue(MULTIPLE_VCS_CLAIM, JsonObject.class), Map.of()); - - var credentials = extractObjectsOfType(VC_TYPE, vp); - var partitions = partitionByType(credentials); - - assertThat(partitions.size()).isEqualTo(3); - - assertAllOfType(FOO_CREDENTIAL_TYPE, partitions.get(FOO_CREDENTIAL_TYPE)); - assertAllOfType(BAR_CREDENTIAL_TYPE, partitions.get(BAR_CREDENTIAL_TYPE)); - assertThat(partitions.get(VC_TYPE).size()).isEqualTo(2); - } - - /** - * Asserts that all objects in the collection are of a given type. - */ - private void assertAllOfType(String type, List objects) { - assertThat(objects.stream() - .flatMap(object -> object.get(TYPE).asJsonArray().stream()) - .filter(value -> value instanceof JsonString) - .filter(entryType -> type.equals(((JsonString) entryType).getString())) - .count()).isEqualTo(objects.size()); - } - - -} diff --git a/spi/ssi-spi/src/test/java/org/eclipse/tractusx/edc/iam/ssi/spi/jsonld/JsonLdValueFunctionsTest.java b/spi/ssi-spi/src/test/java/org/eclipse/tractusx/edc/iam/ssi/spi/jsonld/JsonLdValueFunctionsTest.java deleted file mode 100644 index d1e0ff98c..000000000 --- a/spi/ssi-spi/src/test/java/org/eclipse/tractusx/edc/iam/ssi/spi/jsonld/JsonLdValueFunctionsTest.java +++ /dev/null @@ -1,70 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.iam.ssi.spi.jsonld; - -import org.junit.jupiter.api.Test; - -import static jakarta.json.Json.createArrayBuilder; -import static jakarta.json.Json.createObjectBuilder; -import static org.assertj.core.api.Assertions.assertThat; -import static org.eclipse.tractusx.edc.iam.ssi.spi.jsonld.JsonLdValueFunctions.extractStringValue; - -class JsonLdValueFunctionsTest { - private static final String VALUE = "@value"; - - @Test - void validate_nested_array() { - var root = createArrayBuilder() - .add(createObjectBuilder().add(VALUE, "test").build()) - .build(); - - assertThat(extractStringValue(root)).isEqualTo("test"); - } - - @Test - void validate_empty_array() { - var root = createArrayBuilder().build(); - assertThat(extractStringValue(root)).isNull(); - } - - @Test - void validate_object() { - var root = createObjectBuilder().add(VALUE, "test").build(); - assertThat(extractStringValue(root)).isEqualTo("test"); - } - - @Test - void validate_object_int() { - var root = createObjectBuilder().add(VALUE, 1).build(); - assertThat(extractStringValue(root)).isEqualTo("1"); - } - - @Test - void validate_object_double() { - var root = createObjectBuilder().add(VALUE, 1.1d).build(); - assertThat(extractStringValue(root)).isEqualTo("1.1"); - } - - @Test - void validate_null() { - assertThat(extractStringValue(null)).isNull(); - } - -} diff --git a/spi/ssi-spi/src/testFixtures/java/org/eclipse/tractusx/edc/iam/ssi/spi/jsonld/JsonLdTextFixtures.java b/spi/ssi-spi/src/testFixtures/java/org/eclipse/tractusx/edc/iam/ssi/spi/jsonld/JsonLdTextFixtures.java deleted file mode 100644 index cfe9216d3..000000000 --- a/spi/ssi-spi/src/testFixtures/java/org/eclipse/tractusx/edc/iam/ssi/spi/jsonld/JsonLdTextFixtures.java +++ /dev/null @@ -1,95 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.iam.ssi.spi.jsonld; - -import com.apicatalog.jsonld.JsonLdError; -import com.apicatalog.jsonld.JsonLdOptions; -import com.apicatalog.jsonld.document.JsonDocument; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.module.SimpleModule; -import com.fasterxml.jackson.datatype.jsonp.JSONPModule; -import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; -import jakarta.json.Json; -import jakarta.json.JsonObject; - -import java.io.StringReader; -import java.util.HashMap; -import java.util.Map; - -import static com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES; -import static org.eclipse.tractusx.edc.iam.ssi.spi.jsonld.CredentialsNamespaces.W3C_VC_NS; -import static org.eclipse.tractusx.edc.iam.ssi.spi.jsonld.W3cVcContext.W3C_VC_CONTEXT; - -/** - * Test helpers for processing Json-Ld. - */ -public class JsonLdTextFixtures { - - /** - * Creates a mapper configured to support Json-Ld processing. - */ - public static ObjectMapper createObjectMapper() { - var mapper = new ObjectMapper(); - mapper.configure(FAIL_ON_UNKNOWN_PROPERTIES, false); - mapper.registerModule(new JavaTimeModule()); - mapper.registerModule(new JSONPModule()); - var module = new SimpleModule() { - @Override - public void setupModule(SetupContext context) { - super.setupModule(context); - } - }; - mapper.registerModule(module); - return mapper; - } - - /** - * Performs Json-Ld compaction on an object. - */ - public static JsonObject compact(JsonObject json) { - try { - var document = JsonDocument.of(json); - var jsonFactory = Json.createBuilderFactory(Map.of()); - var contextDocument = JsonDocument.of(jsonFactory.createObjectBuilder().build()); - return com.apicatalog.jsonld.JsonLd.compact(document, contextDocument).get(); - } catch (JsonLdError e) { - throw new AssertionError(e); - } - } - - /** - * Expands the document using the provided cache for resolving referenced contexts. The {@link CredentialsNamespaces#W3C_VC_NS} context is implicitly added to the cache. - */ - public static JsonObject expand(JsonObject json, Map contextCache) { - var map = new HashMap<>(contextCache); - map.put(W3C_VC_NS, W3C_VC_CONTEXT); - try { - var document = JsonDocument.of(json); - var options = new JsonLdOptions((url, options1) -> JsonDocument.of(new StringReader(map.get(url.toString())))); - var expanded = com.apicatalog.jsonld.JsonLd.expand(document).options(options).get(); - if (expanded.size() > 0) { - return expanded.getJsonObject(0); - } - return Json.createObjectBuilder().build(); - } catch (JsonLdError e) { - throw new AssertionError(e); - } - } -} diff --git a/spi/ssi-spi/src/testFixtures/java/org/eclipse/tractusx/edc/iam/ssi/spi/jsonld/SummaryContext.java b/spi/ssi-spi/src/testFixtures/java/org/eclipse/tractusx/edc/iam/ssi/spi/jsonld/SummaryContext.java deleted file mode 100644 index 2b8d33063..000000000 --- a/spi/ssi-spi/src/testFixtures/java/org/eclipse/tractusx/edc/iam/ssi/spi/jsonld/SummaryContext.java +++ /dev/null @@ -1,54 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.iam.ssi.spi.jsonld; - -/** - * Defines the summary context. - */ -public interface SummaryContext { - String SUMMARY_CONTEXT = """ - { - "@context": { - "@version": 1.1, - "@protected": true, - "summary": "https://w3id.org/2023/catenax/credentials/summary/", - "id": "@id", - "type": "@type", - "SummaryCredential" : { - "@id":"summary:SummaryCredential" - }, - "holderIdentifier": { - "@id": "summary:holderIdentifier" - }, - "name": { - "@id": "summary:name", - "@type": "https://schema.org/Text" - }, - "items": { - "@id": "summary:items", - "@type": "https://schema.org/Text" - }, - "contract-template": { - "@id": "summary:contract-template", - "@type": "https://schema.org/Text" - } - } - }"""; -} diff --git a/spi/ssi-spi/src/testFixtures/java/org/eclipse/tractusx/edc/iam/ssi/spi/jsonld/SummaryCredential.java b/spi/ssi-spi/src/testFixtures/java/org/eclipse/tractusx/edc/iam/ssi/spi/jsonld/SummaryCredential.java deleted file mode 100644 index 66266823b..000000000 --- a/spi/ssi-spi/src/testFixtures/java/org/eclipse/tractusx/edc/iam/ssi/spi/jsonld/SummaryCredential.java +++ /dev/null @@ -1,153 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.iam.ssi.spi.jsonld; - -/** - * Sample summary credential. - */ -public interface SummaryCredential { - String SUMMARY_VP = """ - { - "@context": [ - "https://www.w3.org/2018/credentials/v1" - ], - "type": "VerifiablePresentation", - "verifiableCredential": [ - { - "@context": [ - "https://www.w3.org/2018/credentials/v1", - "https://w3id.org/2023/catenax/credentials/summary/v1" - ], - "id": "urn:uuid:12345678-1234-1234-1234-123456789abc", - "type": [ - "VerifiableCredential", - "SummaryCredential" - ], - "issuer": "did:web:issuer-example.com", - "issuanceDate": "2023-06-02T12:00:00Z", - "expirationDate": "2022-06-16T18:56:59Z", - "credentialSubject": { - "id": "did:web:example.com", - "holderIdentifier": "BPN of holder", - "type": "Summary-List", - "name": "CX-Credentials", - "items": [ - "MembershipCredential", - "DismantlerCredential", - "PcfCredential", - "SustainabilityCredential", - "QualityCredential", - "TraceabilityCredential", - "BehaviorTwinCredential", - "BpnCredential" - ], - "contractTemplates": "https://public.catena-x.org/contracts/" - }, - "proof": { - "type": "Ed25519Signature2018", - "created": "2023-06-02T12:00:00Z", - "proofPurpose": "assertionMethod", - "verificationMethod": "did:web:example.com#key-1", - "jws": "xxxx" - } - } - ] - } - """; - - String SIMPLE_VP = """ - { - "@context": [ - "https://www.w3.org/2018/credentials/v1" - ], - "type": "VerifiablePresentation", - "verifiableCredential": [ - { - "@context": [ - "https://www.w3.org/2018/credentials/v1" - ], - "id": "urn:uuid:12345678-1234-1234-1234-123456789abc", - "type": [ - "VerifiableCredential" - ], - "issuer": "did:web:example.com", - "issuanceDate": "2023-06-02T12:00:00Z", - "expirationDate": "2022-06-16T18:56:59Z", - "credentialSubject": { - "id": "did:web:example.com" - } - } - ] - } - """; - - String SUMMARY_VP_NO_HOLDER = """ - { - "@context": [ - "https://www.w3.org/2018/credentials/v1" - ], - "type": "VerifiablePresentation", - "verifiableCredential": [ - { - "@context": [ - "https://www.w3.org/2018/credentials/v1", - "https://w3id.org/2023/catenax/credentials/summary/v1" - ], - "id": "urn:uuid:12345678-1234-1234-1234-123456789abc", - "type": [ - "VerifiableCredential", - "SummaryCredential" - ], - "issuer": "did:web:no-holder.example.com:BPNL000000000000", - "issuanceDate": "2023-06-02T12:00:00Z", - "expirationDate": "2022-06-16T18:56:59Z", - "credentialSubject": { - "id": "did:web:example.com" - } - } - ] - } - """; - - String SUMMARY_VP_NO_SUBJECT = """ - { - "@context": [ - "https://www.w3.org/2018/credentials/v1" - ], - "type": "VerifiablePresentation", - "verifiableCredential": [ - { - "@context": [ - "https://www.w3.org/2018/credentials/v1", - "https://w3id.org/2023/catenax/credentials/summary/v1" - ], - "id": "urn:uuid:12345678-1234-1234-1234-123456789abc", - "type": [ - "VerifiableCredential", - "SummaryCredential" - ], - "issuer": "did:web:example.com", - "issuanceDate": "2023-06-02T12:00:00Z", - "expirationDate": "2022-06-16T18:56:59Z" - } - ] - } - """; -} diff --git a/spi/ssi-spi/src/testFixtures/java/org/eclipse/tractusx/edc/iam/ssi/spi/jsonld/W3cVcContext.java b/spi/ssi-spi/src/testFixtures/java/org/eclipse/tractusx/edc/iam/ssi/spi/jsonld/W3cVcContext.java deleted file mode 100644 index 4df64ba35..000000000 --- a/spi/ssi-spi/src/testFixtures/java/org/eclipse/tractusx/edc/iam/ssi/spi/jsonld/W3cVcContext.java +++ /dev/null @@ -1,268 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.iam.ssi.spi.jsonld; - -/** - * Local copy of the W3C VC data model context for testing, obtained from {@code https://www.w3.org/ns/credentials/v2}. - */ -public interface W3cVcContext { - - String W3C_VC_CONTEXT = """ - { - "@context": { - "@version": 1.1, - "@protected": true, - - "id": "@id", - "type": "@type", - - "VerifiableCredential": { - "@id": "https://www.w3.org/2018/credentials#VerifiableCredential", - "@context": { - "@version": 1.1, - "@protected": true, - - "id": "@id", - "type": "@type", - - "cred": "https://www.w3.org/2018/credentials#", - "sec": "https://w3id.org/security#", - "xsd": "http://www.w3.org/2001/XMLSchema#", - - "credentialSchema": { - "@id": "cred:credentialSchema", - "@type": "@id", - "@context": { - "@version": 1.1, - "@protected": true, - - "id": "@id", - "type": "@type", - - "cred": "https://www.w3.org/2018/credentials#", - - "JsonSchemaValidator2018": "cred:JsonSchemaValidator2018" - } - }, - "credentialStatus": {"@id": "cred:credentialStatus", "@type": "@id"}, - "credentialSubject": {"@id": "cred:credentialSubject", "@type": "@id"}, - "evidence": {"@id": "cred:evidence", "@type": "@id"}, - "expirationDate": {"@id": "cred:expirationDate", "@type": "xsd:dateTime"}, - "holder": {"@id": "cred:holder", "@type": "@id"}, - "issued": {"@id": "cred:issued", "@type": "xsd:dateTime"}, - "issuer": {"@id": "cred:issuer", "@type": "@id"}, - "issuanceDate": {"@id": "cred:issuanceDate", "@type": "xsd:dateTime"}, - "proof": {"@id": "sec:proof", "@type": "@id", "@container": "@graph"}, - "refreshService": { - "@id": "cred:refreshService", - "@type": "@id", - "@context": { - "@version": 1.1, - "@protected": true, - - "id": "@id", - "type": "@type", - - "cred": "https://www.w3.org/2018/credentials#", - - "ManualRefreshService2018": "cred:ManualRefreshService2018" - } - }, - "termsOfUse": {"@id": "cred:termsOfUse", "@type": "@id"}, - "validFrom": {"@id": "cred:validFrom", "@type": "xsd:dateTime"}, - "validUntil": {"@id": "cred:validUntil", "@type": "xsd:dateTime"} - } - }, - - "VerifiablePresentation": { - "@id": "https://www.w3.org/2018/credentials#VerifiablePresentation", - "@context": { - "@version": 1.1, - "@protected": true, - - "id": "@id", - "type": "@type", - - "cred": "https://www.w3.org/2018/credentials#", - "sec": "https://w3id.org/security#", - - "holder": {"@id": "cred:holder", "@type": "@id"}, - "proof": {"@id": "sec:proof", "@type": "@id", "@container": "@graph"}, - "verifiableCredential": {"@id": "cred:verifiableCredential", "@type": "@id", "@container": "@graph"} - } - }, - - "EcdsaSecp256k1Signature2019": { - "@id": "https://w3id.org/security#EcdsaSecp256k1Signature2019", - "@context": { - "@version": 1.1, - "@protected": true, - - "id": "@id", - "type": "@type", - - "sec": "https://w3id.org/security#", - "xsd": "http://www.w3.org/2001/XMLSchema#", - - "challenge": "sec:challenge", - "created": {"@id": "http://purl.org/dc/terms/created", "@type": "xsd:dateTime"}, - "domain": "sec:domain", - "expires": {"@id": "sec:expiration", "@type": "xsd:dateTime"}, - "jws": "sec:jws", - "nonce": "sec:nonce", - "proofPurpose": { - "@id": "sec:proofPurpose", - "@type": "@vocab", - "@context": { - "@version": 1.1, - "@protected": true, - - "id": "@id", - "type": "@type", - - "sec": "https://w3id.org/security#", - - "assertionMethod": {"@id": "sec:assertionMethod", "@type": "@id", "@container": "@set"}, - "authentication": {"@id": "sec:authenticationMethod", "@type": "@id", "@container": "@set"} - } - }, - "proofValue": "sec:proofValue", - "verificationMethod": {"@id": "sec:verificationMethod", "@type": "@id"} - } - }, - - "EcdsaSecp256r1Signature2019": { - "@id": "https://w3id.org/security#EcdsaSecp256r1Signature2019", - "@context": { - "@version": 1.1, - "@protected": true, - - "id": "@id", - "type": "@type", - - "sec": "https://w3id.org/security#", - "xsd": "http://www.w3.org/2001/XMLSchema#", - - "challenge": "sec:challenge", - "created": {"@id": "http://purl.org/dc/terms/created", "@type": "xsd:dateTime"}, - "domain": "sec:domain", - "expires": {"@id": "sec:expiration", "@type": "xsd:dateTime"}, - "jws": "sec:jws", - "nonce": "sec:nonce", - "proofPurpose": { - "@id": "sec:proofPurpose", - "@type": "@vocab", - "@context": { - "@version": 1.1, - "@protected": true, - - "id": "@id", - "type": "@type", - - "sec": "https://w3id.org/security#", - - "assertionMethod": {"@id": "sec:assertionMethod", "@type": "@id", "@container": "@set"}, - "authentication": {"@id": "sec:authenticationMethod", "@type": "@id", "@container": "@set"} - } - }, - "proofValue": "sec:proofValue", - "verificationMethod": {"@id": "sec:verificationMethod", "@type": "@id"} - } - }, - - "Ed25519Signature2018": { - "@id": "https://w3id.org/security#Ed25519Signature2018", - "@context": { - "@version": 1.1, - "@protected": true, - - "id": "@id", - "type": "@type", - - "sec": "https://w3id.org/security#", - "xsd": "http://www.w3.org/2001/XMLSchema#", - - "challenge": "sec:challenge", - "created": {"@id": "http://purl.org/dc/terms/created", "@type": "xsd:dateTime"}, - "domain": "sec:domain", - "expires": {"@id": "sec:expiration", "@type": "xsd:dateTime"}, - "jws": "sec:jws", - "nonce": "sec:nonce", - "proofPurpose": { - "@id": "sec:proofPurpose", - "@type": "@vocab", - "@context": { - "@version": 1.1, - "@protected": true, - - "id": "@id", - "type": "@type", - - "sec": "https://w3id.org/security#", - - "assertionMethod": {"@id": "sec:assertionMethod", "@type": "@id", "@container": "@set"}, - "authentication": {"@id": "sec:authenticationMethod", "@type": "@id", "@container": "@set"} - } - }, - "proofValue": "sec:proofValue", - "verificationMethod": {"@id": "sec:verificationMethod", "@type": "@id"} - } - }, - - "RsaSignature2018": { - "@id": "https://w3id.org/security#RsaSignature2018", - "@context": { - "@version": 1.1, - "@protected": true, - - "challenge": "sec:challenge", - "created": {"@id": "http://purl.org/dc/terms/created", "@type": "xsd:dateTime"}, - "domain": "sec:domain", - "expires": {"@id": "sec:expiration", "@type": "xsd:dateTime"}, - "jws": "sec:jws", - "nonce": "sec:nonce", - "proofPurpose": { - "@id": "sec:proofPurpose", - "@type": "@vocab", - "@context": { - "@version": 1.1, - "@protected": true, - - "id": "@id", - "type": "@type", - - "sec": "https://w3id.org/security#", - - "assertionMethod": {"@id": "sec:assertionMethod", "@type": "@id", "@container": "@set"}, - "authentication": {"@id": "sec:authenticationMethod", "@type": "@id", "@container": "@set"} - } - }, - "proofValue": "sec:proofValue", - "verificationMethod": {"@id": "sec:verificationMethod", "@type": "@id"} - } - }, - - "proof": {"@id": "https://w3id.org/security#proof", "@type": "@id", "@container": "@graph"} - } - } - """; - - -} From 524d5f5b5bfedfea65993517869dd7466dd765f6 Mon Sep 17 00:00:00 2001 From: Enrico Risa Date: Fri, 29 Mar 2024 14:58:40 +0100 Subject: [PATCH 081/100] chore: old EDR stuff removal + refactor (#1171) --- .github/workflows/verify.yaml | 3 +- .../edc/edr/core/EdrCacheCoreExtension.java | 59 --- .../defaults/EdrCacheEntryPropertyLookup.java | 56 --- .../InMemoryEndpointDataReferenceCache.java | 241 ---------- .../core/defaults/PersistentCacheEntry.java | 45 -- ...rg.eclipse.edc.spi.system.ServiceExtension | 20 - ...nMemoryEndpointDataReferenceCacheTest.java | 63 --- .../defaults/PersistentCacheEntryTest.java | 60 --- core/edr-core/build.gradle.kts | 8 +- .../edc/edr/core/EdrCoreExtension.java | 134 ------ .../edc/edr/core/EdrCoreServiceExtension.java | 15 +- .../edc/edr/core/manager/EdrManagerImpl.java | 382 ---------------- .../edc/edr/core/service/EdrServiceImpl.java | 108 +++-- ...rg.eclipse.edc.spi.system.ServiceExtension | 1 - .../edc/edr/core/EdrCoreExtensionTest.java | 52 --- .../edr/core/EdrCoreServiceExtensionTest.java | 12 +- .../edc/edr/core/fixtures/TestFunctions.java | 33 +- .../edr/core/manager/EdrManagerImplTest.java | 274 ------------ .../edr/core/service/EdrServiceImplTest.java | 193 ++++---- .../edc-controlplane-base/build.gradle.kts | 1 - .../edc-dataplane-base/build.gradle.kts | 5 +- .../sql/SqlBusinessPartnerStoreTest.java | 2 + .../build.gradle.kts | 1 + .../DataPlaneProxyConsumerApiExtension.java | 6 +- .../asset/ConsumerAssetRequestController.java | 96 ++-- .../api/asset/model/AssetRequest.java | 12 +- .../api/asset/model/AssetRequestTest.java | 6 +- .../ConsumerAssetRequestControllerTest.java | 106 ++--- .../DataPlaneTokenRefreshServiceImpl.java | 2 +- .../tractusx/edc/api/edr/v2/EdrCacheApi.java | 2 +- .../edc/api/edr/v2/EdrCacheApiController.java | 77 ++-- .../edc/api/edr/v2/EdrCacheApiExtension.java | 11 +- .../edc/api/edr/v2/schema/EdrSchema.java | 2 +- ...DataReferenceToDataAddressTransformer.java | 57 --- .../api/edr/v2/EdrCacheApiControllerTest.java | 97 +++- .../edc/api/edr/v2/TestFunctions.java | 10 + ...ReferenceToDataAddressTransformerTest.java | 66 --- ...ointDataReferenceEntryTransformerTest.java | 10 +- edc-extensions/edr/edr-api/README.md | 20 - edc-extensions/edr/edr-api/build.gradle.kts | 40 -- .../eclipse/tractusx/edc/api/edr/EdrApi.java | 81 ---- .../tractusx/edc/api/edr/EdrApiExtension.java | 77 ---- .../tractusx/edc/api/edr/EdrController.java | 161 ------- .../api/edr/dto/NegotiateEdrRequestDto.java | 139 ------ .../edc/api/edr/schema/EdrSchema.java | 137 ------ ...DataReferenceToDataAddressTransformer.java | 57 --- ...EndpointDataReferenceEntryTransformer.java | 70 --- ...ctToNegotiateEdrRequestDtoTransformer.java | 101 ----- ...tDtoToNegotiatedEdrRequestTransformer.java | 65 --- .../NegotiateEdrRequestDtoValidator.java | 84 ---- ...rg.eclipse.edc.spi.system.ServiceExtension | 20 - .../edc/api/edr/EdrApiExtensionTest.java | 70 --- .../tractusx/edc/api/edr/EdrApiTest.java | 152 ------- .../edc/api/edr/EdrControllerTest.java | 397 ----------------- .../tractusx/edc/api/edr/TestFunctions.java | 94 ---- ...ReferenceToDataAddressTransformerTest.java | 66 --- ...ointDataReferenceEntryTransformerTest.java | 75 ---- ...NegotiateEdrRequestDtoTransformerTest.java | 208 --------- ...oToNegotiateEdrRequestTransformerTest.java | 125 ------ .../NegotiateEdrRequestDtoValidatorTest.java | 117 ----- edc-extensions/edr/edr-cache-sql/README.md | 28 -- .../edr/edr-cache-sql/build.gradle.kts | 42 -- .../edr/edr-cache-sql/docs/schema.sql | 56 --- .../sql/SqlEndpointDataReferenceCache.java | 315 ------------- ...qlEndpointDataReferenceCacheExtension.java | 83 ---- .../sql/schema/BaseSqlEdrStatements.java | 102 ----- .../edc/edr/store/sql/schema/EdrMapping.java | 37 -- .../edr/store/sql/schema/EdrStatements.java | 98 ----- .../postgres/PostgresEdrStatements.java | 31 -- ...rg.eclipse.edc.spi.system.ServiceExtension | 20 - ...dpointDataReferenceCacheExtensionTest.java | 59 --- .../SqlEndpointDataReferenceCacheTest.java | 142 ------ ...ntDataReferenceCacheTransactionalTest.java | 157 ------- .../edc/callback/LocalCallbackExtension.java | 14 +- .../TransferProcessLocalCallback.java | 198 --------- .../callback/LocalCallbackExtensionTest.java | 4 +- .../tractusx/edc/callback/TestFunctions.java | 11 - .../TransferProcessLocalCallbackTest.java | 263 ----------- .../tokenrefresh/TokenRefreshHandlerImpl.java | 11 +- .../TokenRefreshHandlerImplTest.java | 1 - .../tractusx/edc/lifecycle/DataWiper.java | 8 +- .../edc/tests/ParticipantDataApi.java | 4 +- .../edc/tests/runtimes/DataWiper.java | 8 +- .../DataPlaneTokenRefreshEndToEndTest.java | 4 +- samples/multi-tenancy/build.gradle.kts | 1 + settings.gradle.kts | 1 - spi/edr-spi/build.gradle.kts | 2 +- .../tractusx/edc/edr/spi/EdrManager.java | 42 -- .../edc/edr/spi/service/EdrService.java | 33 +- .../spi/store/EndpointDataReferenceCache.java | 92 ---- .../spi/types/EndpointDataReferenceEntry.java | 235 ---------- .../EndpointDataReferenceEntryStates.java | 52 --- .../edc/edr/spi/types/RefreshMode.java | 24 +- .../spi/EndpointDataReferenceEntryTest.java | 49 --- .../EndpointDataReferenceCacheTestBase.java | 414 ------------------ .../tractusx/edc/edr/spi/TestFunctions.java | 64 --- .../common/TokenRefreshHandler.java | 6 +- 97 files changed, 504 insertions(+), 6891 deletions(-) delete mode 100644 core/edr-cache-core/src/main/java/org/eclipse/tractusx/edc/edr/core/EdrCacheCoreExtension.java delete mode 100644 core/edr-cache-core/src/main/java/org/eclipse/tractusx/edc/edr/core/defaults/EdrCacheEntryPropertyLookup.java delete mode 100644 core/edr-cache-core/src/main/java/org/eclipse/tractusx/edc/edr/core/defaults/InMemoryEndpointDataReferenceCache.java delete mode 100644 core/edr-cache-core/src/main/java/org/eclipse/tractusx/edc/edr/core/defaults/PersistentCacheEntry.java delete mode 100644 core/edr-cache-core/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension delete mode 100644 core/edr-cache-core/src/test/java/org/eclipse/tractusx/edc/edr/core/defaults/InMemoryEndpointDataReferenceCacheTest.java delete mode 100644 core/edr-cache-core/src/test/java/org/eclipse/tractusx/edc/edr/core/defaults/PersistentCacheEntryTest.java delete mode 100644 core/edr-core/src/main/java/org/eclipse/tractusx/edc/edr/core/EdrCoreExtension.java delete mode 100644 core/edr-core/src/main/java/org/eclipse/tractusx/edc/edr/core/manager/EdrManagerImpl.java delete mode 100644 core/edr-core/src/test/java/org/eclipse/tractusx/edc/edr/core/EdrCoreExtensionTest.java delete mode 100644 core/edr-core/src/test/java/org/eclipse/tractusx/edc/edr/core/manager/EdrManagerImplTest.java delete mode 100644 edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/transform/EndpointDataReferenceToDataAddressTransformer.java delete mode 100644 edc-extensions/edr/edr-api-v2/src/test/java/org/eclipse/tractusx/edc/api/edr/v2/transform/EndpointDataReferenceToDataAddressTransformerTest.java delete mode 100644 edc-extensions/edr/edr-api/README.md delete mode 100644 edc-extensions/edr/edr-api/build.gradle.kts delete mode 100644 edc-extensions/edr/edr-api/src/main/java/org/eclipse/tractusx/edc/api/edr/EdrApi.java delete mode 100644 edc-extensions/edr/edr-api/src/main/java/org/eclipse/tractusx/edc/api/edr/EdrApiExtension.java delete mode 100644 edc-extensions/edr/edr-api/src/main/java/org/eclipse/tractusx/edc/api/edr/EdrController.java delete mode 100644 edc-extensions/edr/edr-api/src/main/java/org/eclipse/tractusx/edc/api/edr/dto/NegotiateEdrRequestDto.java delete mode 100644 edc-extensions/edr/edr-api/src/main/java/org/eclipse/tractusx/edc/api/edr/schema/EdrSchema.java delete mode 100644 edc-extensions/edr/edr-api/src/main/java/org/eclipse/tractusx/edc/api/edr/transform/EndpointDataReferenceToDataAddressTransformer.java delete mode 100644 edc-extensions/edr/edr-api/src/main/java/org/eclipse/tractusx/edc/api/edr/transform/JsonObjectFromEndpointDataReferenceEntryTransformer.java delete mode 100644 edc-extensions/edr/edr-api/src/main/java/org/eclipse/tractusx/edc/api/edr/transform/JsonObjectToNegotiateEdrRequestDtoTransformer.java delete mode 100644 edc-extensions/edr/edr-api/src/main/java/org/eclipse/tractusx/edc/api/edr/transform/NegotiateEdrRequestDtoToNegotiatedEdrRequestTransformer.java delete mode 100644 edc-extensions/edr/edr-api/src/main/java/org/eclipse/tractusx/edc/api/edr/validation/NegotiateEdrRequestDtoValidator.java delete mode 100644 edc-extensions/edr/edr-api/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension delete mode 100644 edc-extensions/edr/edr-api/src/test/java/org/eclipse/tractusx/edc/api/edr/EdrApiExtensionTest.java delete mode 100644 edc-extensions/edr/edr-api/src/test/java/org/eclipse/tractusx/edc/api/edr/EdrApiTest.java delete mode 100644 edc-extensions/edr/edr-api/src/test/java/org/eclipse/tractusx/edc/api/edr/EdrControllerTest.java delete mode 100644 edc-extensions/edr/edr-api/src/test/java/org/eclipse/tractusx/edc/api/edr/TestFunctions.java delete mode 100644 edc-extensions/edr/edr-api/src/test/java/org/eclipse/tractusx/edc/api/edr/transform/EndpointDataReferenceToDataAddressTransformerTest.java delete mode 100644 edc-extensions/edr/edr-api/src/test/java/org/eclipse/tractusx/edc/api/edr/transform/JsonObjectFromEndpointDataReferenceEntryTransformerTest.java delete mode 100644 edc-extensions/edr/edr-api/src/test/java/org/eclipse/tractusx/edc/api/edr/transform/JsonObjectToNegotiateEdrRequestDtoTransformerTest.java delete mode 100644 edc-extensions/edr/edr-api/src/test/java/org/eclipse/tractusx/edc/api/edr/transform/NegotiateEdrRequestDtoToNegotiateEdrRequestTransformerTest.java delete mode 100644 edc-extensions/edr/edr-api/src/test/java/org/eclipse/tractusx/edc/api/edr/validation/NegotiateEdrRequestDtoValidatorTest.java delete mode 100644 edc-extensions/edr/edr-cache-sql/README.md delete mode 100644 edc-extensions/edr/edr-cache-sql/build.gradle.kts delete mode 100644 edc-extensions/edr/edr-cache-sql/docs/schema.sql delete mode 100644 edc-extensions/edr/edr-cache-sql/src/main/java/org/eclipse/tractusx/edc/edr/store/sql/SqlEndpointDataReferenceCache.java delete mode 100644 edc-extensions/edr/edr-cache-sql/src/main/java/org/eclipse/tractusx/edc/edr/store/sql/SqlEndpointDataReferenceCacheExtension.java delete mode 100644 edc-extensions/edr/edr-cache-sql/src/main/java/org/eclipse/tractusx/edc/edr/store/sql/schema/BaseSqlEdrStatements.java delete mode 100644 edc-extensions/edr/edr-cache-sql/src/main/java/org/eclipse/tractusx/edc/edr/store/sql/schema/EdrMapping.java delete mode 100644 edc-extensions/edr/edr-cache-sql/src/main/java/org/eclipse/tractusx/edc/edr/store/sql/schema/EdrStatements.java delete mode 100644 edc-extensions/edr/edr-cache-sql/src/main/java/org/eclipse/tractusx/edc/edr/store/sql/schema/postgres/PostgresEdrStatements.java delete mode 100644 edc-extensions/edr/edr-cache-sql/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension delete mode 100644 edc-extensions/edr/edr-cache-sql/src/test/java/org/eclipse/tractusx/edc/edr/store/sql/SqlEndpointDataReferenceCacheExtensionTest.java delete mode 100644 edc-extensions/edr/edr-cache-sql/src/test/java/org/eclipse/tractusx/edc/edr/store/sql/SqlEndpointDataReferenceCacheTest.java delete mode 100644 edc-extensions/edr/edr-cache-sql/src/test/java/org/eclipse/tractusx/edc/edr/store/sql/SqlEndpointDataReferenceCacheTransactionalTest.java delete mode 100644 edc-extensions/edr/edr-callback/src/main/java/org/eclipse/tractusx/edc/callback/TransferProcessLocalCallback.java delete mode 100644 edc-extensions/edr/edr-callback/src/test/java/org/eclipse/tractusx/edc/callback/TransferProcessLocalCallbackTest.java delete mode 100644 spi/edr-spi/src/main/java/org/eclipse/tractusx/edc/edr/spi/EdrManager.java delete mode 100644 spi/edr-spi/src/main/java/org/eclipse/tractusx/edc/edr/spi/store/EndpointDataReferenceCache.java delete mode 100644 spi/edr-spi/src/main/java/org/eclipse/tractusx/edc/edr/spi/types/EndpointDataReferenceEntry.java delete mode 100644 spi/edr-spi/src/main/java/org/eclipse/tractusx/edc/edr/spi/types/EndpointDataReferenceEntryStates.java rename core/edr-cache-core/build.gradle.kts => spi/edr-spi/src/main/java/org/eclipse/tractusx/edc/edr/spi/types/RefreshMode.java (71%) delete mode 100644 spi/edr-spi/src/test/java/org/eclipse/tractusx/edc/edr/spi/EndpointDataReferenceEntryTest.java delete mode 100644 spi/edr-spi/src/testFixtures/java/org/eclipse/tractusx/edc/edr/spi/EndpointDataReferenceCacheTestBase.java delete mode 100644 spi/edr-spi/src/testFixtures/java/org/eclipse/tractusx/edc/edr/spi/TestFunctions.java diff --git a/.github/workflows/verify.yaml b/.github/workflows/verify.yaml index b57bdf745..3824cd3f0 100644 --- a/.github/workflows/verify.yaml +++ b/.github/workflows/verify.yaml @@ -116,7 +116,8 @@ jobs: { dir: edc-tests/edc-controlplane/edr-api-tests }, { dir: edc-tests/edc-controlplane/iatp-tests }, { dir: edc-tests/edc-controlplane/policy-tests }, - { dir: edc-tests/edc-controlplane/transfer-tests } + { dir: edc-tests/edc-controlplane/transfer-tests }, + { dir: edc-tests/edc-dataplane/edc-dataplane-tokenrefresh-tests } ] steps: - uses: actions/checkout@v4 diff --git a/core/edr-cache-core/src/main/java/org/eclipse/tractusx/edc/edr/core/EdrCacheCoreExtension.java b/core/edr-cache-core/src/main/java/org/eclipse/tractusx/edc/edr/core/EdrCacheCoreExtension.java deleted file mode 100644 index 3f273bea8..000000000 --- a/core/edr-cache-core/src/main/java/org/eclipse/tractusx/edc/edr/core/EdrCacheCoreExtension.java +++ /dev/null @@ -1,59 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.edr.core; - -import org.eclipse.edc.runtime.metamodel.annotation.Extension; -import org.eclipse.edc.runtime.metamodel.annotation.Inject; -import org.eclipse.edc.runtime.metamodel.annotation.Provider; -import org.eclipse.edc.spi.query.CriterionOperatorRegistry; -import org.eclipse.edc.spi.system.ServiceExtension; -import org.eclipse.edc.spi.system.ServiceExtensionContext; -import org.eclipse.tractusx.edc.edr.core.defaults.EdrCacheEntryPropertyLookup; -import org.eclipse.tractusx.edc.edr.core.defaults.InMemoryEndpointDataReferenceCache; -import org.eclipse.tractusx.edc.edr.spi.store.EndpointDataReferenceCache; - -/** - * Registers default services for the EDR cache. - */ -@Extension(value = EdrCacheCoreExtension.NAME) -public class EdrCacheCoreExtension implements ServiceExtension { - - static final String NAME = "EDR Cache Core"; - - @Inject - private CriterionOperatorRegistry operatorRegistry; - - @Override - public String name() { - return NAME; - } - - - @Override - public void initialize(ServiceExtensionContext context) { - operatorRegistry.registerPropertyLookup(new EdrCacheEntryPropertyLookup()); - } - - @Provider(isDefault = true) - public EndpointDataReferenceCache edrCache() { - return new InMemoryEndpointDataReferenceCache(operatorRegistry); - } - -} diff --git a/core/edr-cache-core/src/main/java/org/eclipse/tractusx/edc/edr/core/defaults/EdrCacheEntryPropertyLookup.java b/core/edr-cache-core/src/main/java/org/eclipse/tractusx/edc/edr/core/defaults/EdrCacheEntryPropertyLookup.java deleted file mode 100644 index 9cc2de91c..000000000 --- a/core/edr-cache-core/src/main/java/org/eclipse/tractusx/edc/edr/core/defaults/EdrCacheEntryPropertyLookup.java +++ /dev/null @@ -1,56 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.edr.core.defaults; - -import org.eclipse.edc.spi.query.PropertyLookup; -import org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntry; - -/** - * This class is almost a 1:1 copy of the {@code CriterionToPredicateConverterImpl} (except for the {@code property()} method) from the {@code control-plane-core} module. - * Pulling in that module is not possible, because that would pull in almost the entire Control Plane - */ -public class EdrCacheEntryPropertyLookup implements PropertyLookup { - - public static final String ASSET_ID = "assetId"; - public static final String AGREEMENT_ID = "agreementId"; - public static final String PROVIDER_ID = "providerId"; - public static final String CONTRACT_NEGOTIATION_ID = "contractNegotiationId"; - public static final String STATE = "state"; - - @Override - public Object getProperty(String key, Object object) { - return property(key, object); - } - - protected Object property(String key, Object object) { - if (object instanceof EndpointDataReferenceEntry entry) { - return switch (key) { - case ASSET_ID -> entry.getAssetId(); - case AGREEMENT_ID -> entry.getAgreementId(); - case PROVIDER_ID -> entry.getProviderId(); - case CONTRACT_NEGOTIATION_ID -> entry.getContractNegotiationId(); - case STATE -> entry.getState(); - default -> null; - }; - } - return null; - } - -} diff --git a/core/edr-cache-core/src/main/java/org/eclipse/tractusx/edc/edr/core/defaults/InMemoryEndpointDataReferenceCache.java b/core/edr-cache-core/src/main/java/org/eclipse/tractusx/edc/edr/core/defaults/InMemoryEndpointDataReferenceCache.java deleted file mode 100644 index 7d9ab3376..000000000 --- a/core/edr-cache-core/src/main/java/org/eclipse/tractusx/edc/edr/core/defaults/InMemoryEndpointDataReferenceCache.java +++ /dev/null @@ -1,241 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.edr.core.defaults; - -import org.eclipse.edc.spi.entity.StatefulEntity; -import org.eclipse.edc.spi.persistence.Lease; -import org.eclipse.edc.spi.query.Criterion; -import org.eclipse.edc.spi.query.CriterionOperatorRegistry; -import org.eclipse.edc.spi.query.QuerySpec; -import org.eclipse.edc.spi.result.StoreResult; -import org.eclipse.edc.spi.types.domain.edr.EndpointDataReference; -import org.eclipse.edc.util.concurrency.LockManager; -import org.eclipse.tractusx.edc.edr.spi.store.EndpointDataReferenceCache; -import org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntry; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.time.Clock; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Optional; -import java.util.UUID; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.locks.ReentrantReadWriteLock; -import java.util.function.Predicate; -import java.util.stream.Stream; - -import static java.lang.String.format; -import static java.util.Collections.emptyList; -import static java.util.Comparator.comparingLong; -import static java.util.stream.Collectors.toList; -import static org.eclipse.edc.spi.result.StoreResult.notFound; -import static org.eclipse.edc.spi.result.StoreResult.success; - -/** - * An in-memory, threadsafe implementation of the cache. - */ -public class InMemoryEndpointDataReferenceCache implements EndpointDataReferenceCache { - private static final long DEFAULT_LEASE_TIME_MILLIS = 60_000; - protected final CriterionOperatorRegistry criterionOperatorRegistry; - private final LockManager lockManager; - private final Map> entriesByAssetId; - - private final Map entriesByEdrId; - - private final Map edrsByTransferProcessId; - private final String lockId; - - private final Map leases; - - private final Clock clock; - - - public InMemoryEndpointDataReferenceCache(CriterionOperatorRegistry criterionOperatorRegistry) { - this(criterionOperatorRegistry, UUID.randomUUID().toString(), Clock.systemUTC(), new ConcurrentHashMap<>()); - } - - public InMemoryEndpointDataReferenceCache(CriterionOperatorRegistry criterionOperatorRegistry, String lockId, Clock clock, Map leases) { - this.criterionOperatorRegistry = criterionOperatorRegistry; - this.lockId = lockId; - lockManager = new LockManager(new ReentrantReadWriteLock()); - entriesByAssetId = new HashMap<>(); - entriesByEdrId = new ConcurrentHashMap<>(); - edrsByTransferProcessId = new HashMap<>(); - this.leases = leases; - this.clock = clock; - } - - @Override - public @Nullable EndpointDataReference resolveReference(String transferProcessId) { - return lockManager.readLock(() -> edrsByTransferProcessId.get(transferProcessId)); - } - - @Override - public StoreResult findByIdAndLease(String transferProcessId) { - return lockManager.readLock(() -> { - var edr = edrsByTransferProcessId.get(transferProcessId); - var edrEntry = entriesByEdrId.get(edr.getId()); - return edrEntry == null ? StoreResult.notFound(format("EndpointDataReferenceEntry %s not found", transferProcessId)) : - StoreResult.success(edrEntry); - }); - } - - @Override - @NotNull - public List referencesForAsset(String assetId, String providerId) { - return lockManager.readLock(() -> { - var entries = entriesByAssetId.get(assetId); - - Predicate providerIdFilter = (cached) -> - Optional.ofNullable(providerId) - .map(id -> id.equals(cached.getProviderId())) - .orElse(true); - - if (entries == null) { - return emptyList(); - } - return entries.stream() - .filter(providerIdFilter) - .filter(this::filterActive) - .map(e -> resolveReference(e.getTransferProcessId())) - .filter(Objects::nonNull) - .collect(toList()); - - }); - } - - @Override - public Stream queryForEntries(QuerySpec spec) { - return filterBy(spec.getFilterExpression()); - } - - @Override - public void save(EndpointDataReferenceEntry entry, EndpointDataReference edr) { - lockManager.writeLock(() -> { - entriesByEdrId.put(edr.getId(), entry); - var list = entriesByAssetId.computeIfAbsent(entry.getAssetId(), k -> new ArrayList<>()); - list.add(entry); - - edrsByTransferProcessId.put(entry.getTransferProcessId(), edr); - return null; - }); - } - - @Override - public void update(EndpointDataReferenceEntry entry) { - lockManager.writeLock(() -> { - acquireLease(entry.getTransferProcessId(), lockId); - var edr = edrsByTransferProcessId.get(entry.getTransferProcessId()); - entriesByEdrId.put(edr.getId(), entry); - var list = entriesByAssetId.computeIfAbsent(entry.getAssetId(), k -> new ArrayList<>()); - list.removeIf((edrEntry) -> edrEntry.getTransferProcessId().equals(entry.getTransferProcessId())); - list.add(entry); - freeLease(entry.getTransferProcessId()); - return null; - }); - } - - @Override - public StoreResult deleteByTransferProcessId(String id) { - return lockManager.writeLock(() -> { - if (isLeased(id)) { - throw new IllegalStateException("EndpointDataReferenceEntry is leased and cannot be deleted!"); - } - var edr = edrsByTransferProcessId.remove(id); - if (edr == null) { - return notFound("EDR entry not found for id: " + id); - } - var entry = entriesByEdrId.remove(edr.getId()); - var entries = entriesByAssetId.get(entry.getAssetId()); - entries.remove(entry); - if (entries.isEmpty()) { - entriesByAssetId.remove(entry.getAssetId()); - } - - return success(entry); - }); - } - - @Override - public EndpointDataReferenceEntry findById(String correlationId) { - return findByIdAndLease(correlationId).orElse(storeFailure -> null); - } - - @Override - public @NotNull List nextNotLeased(int max, Criterion... criteria) { - return leaseAndGet(max, criteria); - } - - @Override - public void save(EndpointDataReferenceEntry entity) { - throw new UnsupportedOperationException("Please use save(EndpointDataReferenceEntry, EndpointDataReference) instead!"); - } - - private @NotNull List leaseAndGet(int max, Criterion... criteria) { - return lockManager.writeLock(() -> { - var filterPredicate = Arrays.stream(criteria).map(criterionOperatorRegistry::toPredicate).reduce(x -> true, Predicate::and); - var entities = entriesByEdrId.values().stream() - .filter(filterPredicate) - .filter(e -> !isLeased(e.getId())) - .sorted(comparingLong(StatefulEntity::getStateTimestamp)) //order by state timestamp, oldest first - .limit(max) - .toList(); - entities.forEach(i -> acquireLease(i.getId(), lockId)); - return entities.stream().map(StatefulEntity::copy).collect(toList()); - }); - } - - private Stream filterBy(List criteria) { - return lockManager.readLock(() -> { - var predicate = criteria.stream() - .map(criterionOperatorRegistry::toPredicate) - .reduce(x -> true, Predicate::and); - - return entriesByEdrId.values().stream() - .filter(predicate); - }); - - } - - private void freeLease(String id) { - leases.remove(id); - } - - private void acquireLease(String id, String lockId) { - if (!isLeased(id) || isLeasedBy(id, lockId)) { - leases.put(id, new Lease(lockId, clock.millis(), DEFAULT_LEASE_TIME_MILLIS)); - } else { - throw new IllegalStateException("Cannot acquire lease, is already leased by someone else!"); - } - } - - private boolean isLeased(String id) { - return leases.containsKey(id) && !leases.get(id).isExpired(clock.millis()); - } - - private boolean isLeasedBy(String id, String lockId) { - return isLeased(id) && leases.get(id).getLeasedBy().equals(lockId); - } -} diff --git a/core/edr-cache-core/src/main/java/org/eclipse/tractusx/edc/edr/core/defaults/PersistentCacheEntry.java b/core/edr-cache-core/src/main/java/org/eclipse/tractusx/edc/edr/core/defaults/PersistentCacheEntry.java deleted file mode 100644 index a14ebcf82..000000000 --- a/core/edr-cache-core/src/main/java/org/eclipse/tractusx/edc/edr/core/defaults/PersistentCacheEntry.java +++ /dev/null @@ -1,45 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.edr.core.defaults; - -import com.fasterxml.jackson.annotation.JsonProperty; -import org.eclipse.edc.spi.types.domain.edr.EndpointDataReference; -import org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntry; - -/** - * A wrapper to persist {@link EndpointDataReferenceEntry}s and {@link EndpointDataReference}s. - */ -public class PersistentCacheEntry { - private EndpointDataReferenceEntry edrEntry; - private EndpointDataReference edr; - - public PersistentCacheEntry(@JsonProperty("edrEntry") EndpointDataReferenceEntry edrEntry, @JsonProperty("edr") EndpointDataReference edr) { - this.edrEntry = edrEntry; - this.edr = edr; - } - - public EndpointDataReferenceEntry getEdrEntry() { - return edrEntry; - } - - public EndpointDataReference getEdr() { - return edr; - } -} diff --git a/core/edr-cache-core/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension b/core/edr-cache-core/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension deleted file mode 100644 index 82993677d..000000000 --- a/core/edr-cache-core/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension +++ /dev/null @@ -1,20 +0,0 @@ -################################################################################# -# Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) -# -# See the NOTICE file(s) distributed with this work for additional -# information regarding copyright ownership. -# -# This program and the accompanying materials are made available under the -# terms of the Apache License, Version 2.0 which is available at -# https://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. -# -# SPDX-License-Identifier: Apache-2.0 -################################################################################# - -org.eclipse.tractusx.edc.edr.core.EdrCacheCoreExtension diff --git a/core/edr-cache-core/src/test/java/org/eclipse/tractusx/edc/edr/core/defaults/InMemoryEndpointDataReferenceCacheTest.java b/core/edr-cache-core/src/test/java/org/eclipse/tractusx/edc/edr/core/defaults/InMemoryEndpointDataReferenceCacheTest.java deleted file mode 100644 index b10c2fe95..000000000 --- a/core/edr-cache-core/src/test/java/org/eclipse/tractusx/edc/edr/core/defaults/InMemoryEndpointDataReferenceCacheTest.java +++ /dev/null @@ -1,63 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.edr.core.defaults; - -import org.eclipse.edc.query.CriterionOperatorRegistryImpl; -import org.eclipse.edc.spi.persistence.Lease; -import org.eclipse.tractusx.edc.edr.spi.EndpointDataReferenceCacheTestBase; -import org.eclipse.tractusx.edc.edr.spi.store.EndpointDataReferenceCache; -import org.junit.jupiter.api.BeforeEach; - -import java.time.Clock; -import java.time.Duration; -import java.util.HashMap; - -class InMemoryEndpointDataReferenceCacheTest extends EndpointDataReferenceCacheTestBase { - private final HashMap leases = new HashMap<>(); - private InMemoryEndpointDataReferenceCache cache; - - @BeforeEach - void setUp() { - var criterionOperatorRegistry = CriterionOperatorRegistryImpl.ofDefaults(); - criterionOperatorRegistry.registerPropertyLookup(new EdrCacheEntryPropertyLookup()); - cache = new InMemoryEndpointDataReferenceCache(criterionOperatorRegistry, CONNECTOR_NAME, Clock.systemUTC(), leases); - } - - @Override - protected EndpointDataReferenceCache getStore() { - return cache; - } - - @Override - protected void lockEntity(String negotiationId, String owner, Duration duration) { - leases.put(negotiationId, new Lease(owner, Clock.systemUTC().millis(), duration.toMillis())); - } - - @Override - protected boolean isLockedBy(String negotiationId, String owner) { - return leases.entrySet().stream().anyMatch(e -> e.getKey().equals(negotiationId) && - e.getValue().getLeasedBy().equals(owner) && - !isExpired(e.getValue())); - } - - private boolean isExpired(Lease e) { - return e.getLeasedAt() + e.getLeaseDuration() < Clock.systemUTC().millis(); - } -} diff --git a/core/edr-cache-core/src/test/java/org/eclipse/tractusx/edc/edr/core/defaults/PersistentCacheEntryTest.java b/core/edr-cache-core/src/test/java/org/eclipse/tractusx/edc/edr/core/defaults/PersistentCacheEntryTest.java deleted file mode 100644 index 4ce68d560..000000000 --- a/core/edr-cache-core/src/test/java/org/eclipse/tractusx/edc/edr/core/defaults/PersistentCacheEntryTest.java +++ /dev/null @@ -1,60 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.edr.core.defaults; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import org.eclipse.edc.spi.types.domain.edr.EndpointDataReference; -import org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntry; -import org.junit.jupiter.api.Test; - -import static java.util.UUID.randomUUID; -import static org.assertj.core.api.Assertions.assertThat; - -class PersistentCacheEntryTest { - - @Test - void verify_serializeDeserialize() throws JsonProcessingException { - var mapper = new ObjectMapper(); - - var edr = EndpointDataReference.Builder.newInstance() - .endpoint("http://test.com") - .id(randomUUID().toString()) - .authCode("11111") - .contractId("test-contract-id") - .authKey("authentication").build(); - - var edrEntry = EndpointDataReferenceEntry.Builder.newInstance() - .assetId(randomUUID().toString()) - .agreementId(randomUUID().toString()) - .transferProcessId(randomUUID().toString()) - .providerId(randomUUID().toString()) - .build(); - - var serialized = mapper.writeValueAsString(new PersistentCacheEntry(edrEntry, edr)); - - var deserialized = mapper.readValue(serialized, PersistentCacheEntry.class); - - assertThat(deserialized.getEdrEntry()).isNotNull(); - assertThat(deserialized.getEdr()).isNotNull(); - } - - -} diff --git a/core/edr-core/build.gradle.kts b/core/edr-core/build.gradle.kts index 96604fd45..96040bb2a 100644 --- a/core/edr-core/build.gradle.kts +++ b/core/edr-core/build.gradle.kts @@ -22,13 +22,11 @@ plugins { } dependencies { - implementation(libs.edc.spi.core) - implementation(libs.edc.config.filesystem) implementation(libs.edc.util) - implementation(libs.edc.spi.contract) - implementation(libs.edc.spi.controlplane) - implementation(libs.edc.lib.statemachine) + implementation(libs.edc.spi.edrstore) + implementation(libs.edc.spi.transactionspi) + implementation(project(":spi:tokenrefresh-spi")) implementation(project(":spi:edr-spi")) implementation(project(":spi:core-spi")) diff --git a/core/edr-core/src/main/java/org/eclipse/tractusx/edc/edr/core/EdrCoreExtension.java b/core/edr-core/src/main/java/org/eclipse/tractusx/edc/edr/core/EdrCoreExtension.java deleted file mode 100644 index f9fb137dd..000000000 --- a/core/edr-core/src/main/java/org/eclipse/tractusx/edc/edr/core/EdrCoreExtension.java +++ /dev/null @@ -1,134 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.edr.core; - -import org.eclipse.edc.connector.spi.contractnegotiation.ContractNegotiationService; -import org.eclipse.edc.connector.spi.transferprocess.TransferProcessService; -import org.eclipse.edc.runtime.metamodel.annotation.Extension; -import org.eclipse.edc.runtime.metamodel.annotation.Inject; -import org.eclipse.edc.runtime.metamodel.annotation.Provides; -import org.eclipse.edc.runtime.metamodel.annotation.Setting; -import org.eclipse.edc.spi.monitor.Monitor; -import org.eclipse.edc.spi.retry.ExponentialWaitStrategy; -import org.eclipse.edc.spi.system.ExecutorInstrumentation; -import org.eclipse.edc.spi.system.ServiceExtension; -import org.eclipse.edc.spi.system.ServiceExtensionContext; -import org.eclipse.edc.spi.telemetry.Telemetry; -import org.eclipse.tractusx.edc.edr.core.manager.EdrManagerImpl; -import org.eclipse.tractusx.edc.edr.spi.EdrManager; -import org.eclipse.tractusx.edc.edr.spi.store.EndpointDataReferenceCache; - -import java.time.Clock; -import java.time.Duration; - -/** - * Registers default services for the EDR cache. - */ -@Provides(EdrManager.class) -@Extension(value = EdrCoreExtension.NAME) -public class EdrCoreExtension implements ServiceExtension { - public static final long DEFAULT_ITERATION_WAIT = 1000; - - public static final int DEFAULT_BATCH_SIZE = 20; - - public static final int DEFAULT_SEND_RETRY_LIMIT = 7; - - public static final long DEFAULT_SEND_RETRY_BASE_DELAY = 1000L; - public static final long DEFAULT_EXPIRING_DURATION = 60; - - public static final long DEFAULT_EXPIRED_RETENTION = 60; - - protected static final String NAME = "EDR Core"; - @Setting(value = "The iteration wait time in milliseconds in the edr state machine.", type = "long", defaultValue = "" + DEFAULT_ITERATION_WAIT) - private static final String EDR_STATE_MACHINE_ITERATION_WAIT_MILLIS = "edc.edr.state-machine.iteration-wait-millis"; - @Setting(value = "The batch size in the edr negotiation state machine.", type = "int", defaultValue = "" + DEFAULT_BATCH_SIZE) - private static final String EDR_STATE_MACHINE_BATCH_SIZE = "edc.edr.state-machine.batch-size"; - @Setting(value = "The minimum duration on which the EDR token can be eligible for renewal", type = "long", defaultValue = "" + DEFAULT_EXPIRING_DURATION) - private static final String EDR_STATE_MACHINE_EXPIRING_DURATION = "edc.edr.state-machine.expiring-duration"; - - @Setting(value = "The minimum duration on with the EDR token can be eligible for deletion when it's expired.", type = "long", defaultValue = "" + DEFAULT_EXPIRED_RETENTION) - private static final String EDR_STATE_MACHINE_EXPIRED_RETENTION = "edc.edr.state-machine.expired-retention"; - - @Inject - private Monitor monitor; - - @Inject - private ContractNegotiationService contractNegotiationService; - - @Inject - private TransferProcessService transferProcessService; - @Inject - private EndpointDataReferenceCache endpointDataReferenceCache; - - @Inject - private ExecutorInstrumentation executorInstrumentation; - - @Inject - private Telemetry telemetry; - - @Inject - private Clock clock; - private EdrManagerImpl edrManager; - - @Override - public String name() { - return NAME; - } - - @Override - public void initialize(ServiceExtensionContext context) { - - var iterationWaitMillis = context.getSetting(EDR_STATE_MACHINE_ITERATION_WAIT_MILLIS, DEFAULT_ITERATION_WAIT); - - var expiringDuration = context.getSetting(EDR_STATE_MACHINE_EXPIRING_DURATION, DEFAULT_EXPIRING_DURATION); - - var expiredRetention = context.getSetting(EDR_STATE_MACHINE_EXPIRED_RETENTION, DEFAULT_EXPIRED_RETENTION); - - - edrManager = EdrManagerImpl.Builder.newInstance() - .contractNegotiationService(contractNegotiationService) - .monitor(monitor) - .waitStrategy(new ExponentialWaitStrategy(iterationWaitMillis)) - .executorInstrumentation(executorInstrumentation) - .edrCache(endpointDataReferenceCache) - .transferProcessService(transferProcessService) - .telemetry(telemetry) - .batchSize(context.getSetting(EDR_STATE_MACHINE_BATCH_SIZE, DEFAULT_BATCH_SIZE)) - .expiringDuration(Duration.ofSeconds(expiringDuration)) - .expiredRetention(Duration.ofSeconds(expiredRetention)) - .clock(clock) - .build(); - - context.registerService(EdrManager.class, edrManager); - } - - @Override - public void start() { - edrManager.start(); - } - - @Override - public void shutdown() { - if (edrManager != null) { - edrManager.stop(); - } - } - -} diff --git a/core/edr-core/src/main/java/org/eclipse/tractusx/edc/edr/core/EdrCoreServiceExtension.java b/core/edr-core/src/main/java/org/eclipse/tractusx/edc/edr/core/EdrCoreServiceExtension.java index 012cd65b2..8c579a4cc 100644 --- a/core/edr-core/src/main/java/org/eclipse/tractusx/edc/edr/core/EdrCoreServiceExtension.java +++ b/core/edr-core/src/main/java/org/eclipse/tractusx/edc/edr/core/EdrCoreServiceExtension.java @@ -19,15 +19,16 @@ package org.eclipse.tractusx.edc.edr.core; +import org.eclipse.edc.edr.spi.store.EndpointDataReferenceStore; import org.eclipse.edc.runtime.metamodel.annotation.Extension; import org.eclipse.edc.runtime.metamodel.annotation.Inject; import org.eclipse.edc.runtime.metamodel.annotation.Provider; import org.eclipse.edc.spi.monitor.Monitor; import org.eclipse.edc.spi.system.ServiceExtension; +import org.eclipse.edc.transaction.spi.TransactionContext; import org.eclipse.tractusx.edc.edr.core.service.EdrServiceImpl; -import org.eclipse.tractusx.edc.edr.spi.EdrManager; import org.eclipse.tractusx.edc.edr.spi.service.EdrService; -import org.eclipse.tractusx.edc.edr.spi.store.EndpointDataReferenceCache; +import org.eclipse.tractusx.edc.spi.tokenrefresh.common.TokenRefreshHandler; /** * Registers default services for the EDR cache. @@ -40,19 +41,21 @@ public class EdrCoreServiceExtension implements ServiceExtension { private Monitor monitor; @Inject - private EdrManager edrManager; + private EndpointDataReferenceStore edrStore; @Inject - private EndpointDataReferenceCache endpointDataReferenceCache; + private TokenRefreshHandler tokenRefreshHandler; + + @Inject + private TransactionContext transactionContext; @Override public String name() { return NAME; } - @Provider public EdrService edrService() { - return new EdrServiceImpl(edrManager, endpointDataReferenceCache); + return new EdrServiceImpl(edrStore, tokenRefreshHandler, transactionContext, monitor); } } diff --git a/core/edr-core/src/main/java/org/eclipse/tractusx/edc/edr/core/manager/EdrManagerImpl.java b/core/edr-core/src/main/java/org/eclipse/tractusx/edc/edr/core/manager/EdrManagerImpl.java deleted file mode 100644 index 9a6818d3e..000000000 --- a/core/edr-core/src/main/java/org/eclipse/tractusx/edc/edr/core/manager/EdrManagerImpl.java +++ /dev/null @@ -1,382 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.edr.core.manager; - -import org.eclipse.edc.connector.contract.spi.types.negotiation.ContractNegotiation; -import org.eclipse.edc.connector.contract.spi.types.negotiation.ContractRequest; -import org.eclipse.edc.connector.spi.contractnegotiation.ContractNegotiationService; -import org.eclipse.edc.connector.spi.transferprocess.TransferProcessService; -import org.eclipse.edc.connector.transfer.spi.types.TransferRequest; -import org.eclipse.edc.spi.monitor.Monitor; -import org.eclipse.edc.spi.query.Criterion; -import org.eclipse.edc.spi.query.QuerySpec; -import org.eclipse.edc.spi.response.ResponseStatus; -import org.eclipse.edc.spi.response.StatusResult; -import org.eclipse.edc.spi.retry.ExponentialWaitStrategy; -import org.eclipse.edc.spi.retry.WaitStrategy; -import org.eclipse.edc.spi.system.ExecutorInstrumentation; -import org.eclipse.edc.spi.telemetry.Telemetry; -import org.eclipse.edc.spi.types.domain.callback.CallbackAddress; -import org.eclipse.edc.statemachine.ProcessorImpl; -import org.eclipse.edc.statemachine.StateMachineManager; -import org.eclipse.edc.statemachine.retry.EntityRetryProcessConfiguration; -import org.eclipse.edc.statemachine.retry.EntityRetryProcessFactory; -import org.eclipse.tractusx.edc.edr.spi.EdrManager; -import org.eclipse.tractusx.edc.edr.spi.store.EndpointDataReferenceCache; -import org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntry; -import org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntryStates; -import org.eclipse.tractusx.edc.edr.spi.types.NegotiateEdrRequest; -import org.jetbrains.annotations.NotNull; - -import java.time.Clock; -import java.time.Duration; -import java.time.Instant; -import java.time.ZoneOffset; -import java.util.Collection; -import java.util.Objects; -import java.util.Set; -import java.util.function.Function; -import java.util.function.Supplier; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import static java.lang.String.format; -import static org.eclipse.edc.spi.persistence.StateEntityStore.hasState; -import static org.eclipse.tractusx.edc.edr.core.EdrCoreExtension.DEFAULT_BATCH_SIZE; -import static org.eclipse.tractusx.edc.edr.core.EdrCoreExtension.DEFAULT_EXPIRED_RETENTION; -import static org.eclipse.tractusx.edc.edr.core.EdrCoreExtension.DEFAULT_EXPIRING_DURATION; -import static org.eclipse.tractusx.edc.edr.core.EdrCoreExtension.DEFAULT_ITERATION_WAIT; -import static org.eclipse.tractusx.edc.edr.core.EdrCoreExtension.DEFAULT_SEND_RETRY_BASE_DELAY; -import static org.eclipse.tractusx.edc.edr.core.EdrCoreExtension.DEFAULT_SEND_RETRY_LIMIT; -import static org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntryStates.DELETING; -import static org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntryStates.EXPIRED; -import static org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntryStates.NEGOTIATED; -import static org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntryStates.from; - -/** - * Manages the EDR negotiation and lifecycle. - **/ -public class EdrManagerImpl implements EdrManager { - - public static final String LOCAL_ADAPTER_URI = "local://adapter"; - public static final Set LOCAL_EVENTS = Set.of("contract.negotiation", "transfer.process"); - public static final CallbackAddress LOCAL_CALLBACK = CallbackAddress.Builder.newInstance() - .transactional(true) - .uri(LOCAL_ADAPTER_URI) - .events(LOCAL_EVENTS) - .build(); - protected Monitor monitor; - protected ExecutorInstrumentation executorInstrumentation = ExecutorInstrumentation.noop(); - protected WaitStrategy waitStrategy = () -> DEFAULT_ITERATION_WAIT; - - protected int batchSize = DEFAULT_BATCH_SIZE; - protected EntityRetryProcessFactory entityRetryProcessFactory; - protected EntityRetryProcessConfiguration entityRetryProcessConfiguration = defaultEntityRetryProcessConfiguration(); - private ContractNegotiationService contractNegotiationService; - - private TransferProcessService transferProcessService; - private StateMachineManager stateMachineManager; - private EndpointDataReferenceCache edrCache; - private Telemetry telemetry = new Telemetry(); - private Clock clock; - private Duration expiringDuration; - - private Duration expiredRetention; - - - private EdrManagerImpl() { - expiringDuration = Duration.ofSeconds(DEFAULT_EXPIRING_DURATION); - expiredRetention = Duration.ofSeconds(DEFAULT_EXPIRED_RETENTION); - } - - @Override - public StatusResult initiateEdrNegotiation(NegotiateEdrRequest request) { - var negotiation = contractNegotiationService.initiateNegotiation(createContractRequest(request)); - return StatusResult.success(negotiation); - } - - public void start() { - stateMachineManager = StateMachineManager.Builder.newInstance("edr-manager", monitor, executorInstrumentation, waitStrategy) - .processor(processEdrInState(NEGOTIATED, this::processNegotiated)) - .processor(processEdrInState(EXPIRED, this::processExpired)) - .processor(processDeletingEdr(this::processDeleting)) - .build(); - - stateMachineManager.start(); - } - - public void stop() { - if (stateMachineManager != null) { - stateMachineManager.stop(); - } - } - - protected void transitionToRefreshing(EndpointDataReferenceEntry edrEntry) { - edrEntry.transitionToRefreshing(); - update(edrEntry); - } - - protected void transitionToNegotiated(EndpointDataReferenceEntry edrEntry) { - edrEntry.transitionToNegotiated(); - update(edrEntry); - } - - protected void transitionToError(EndpointDataReferenceEntry edrEntry, String message) { - edrEntry.setErrorDetail(message); - edrEntry.transitionError(); - update(edrEntry); - } - - protected void transitionToDeleting(EndpointDataReferenceEntry edrEntry) { - edrEntry.transitionToDeleting(); - update(edrEntry); - } - - private void update(EndpointDataReferenceEntry edrEntry) { - edrCache.update(edrEntry); - monitor.debug(format("Edr entry %s is now in state %s.", edrEntry.getId(), from(edrEntry.getState()))); - } - - - private ProcessorImpl processEdrInState(EndpointDataReferenceEntryStates state, Function function) { - var filter = new Criterion[]{ hasState(state.code()) }; - return processor(() -> edrCache.nextNotLeased(batchSize, filter), telemetry.contextPropagationMiddleware(function)); - } - - private ProcessorImpl processor(Supplier> o, Function telemetryPropagationFunction) { - return ProcessorImpl.Builder.newInstance(o) - .process(telemetryPropagationFunction) - .build(); - } - - - private ProcessorImpl processDeletingEdr(Function function) { - var query = QuerySpec.Builder.newInstance() - .filter(hasState(DELETING.code())) - .limit(batchSize) - .build(); - - return processor(() -> edrCache.queryForEntries(query).collect(Collectors.toList()), telemetry.contextPropagationMiddleware(function)); - } - - private ContractRequest createContractRequest(NegotiateEdrRequest request) { - var callbacks = Stream.concat(request.getCallbackAddresses().stream(), Stream.of(LOCAL_CALLBACK)).collect(Collectors.toList()); - - return ContractRequest.Builder.newInstance() - .counterPartyAddress(request.getConnectorAddress()) - .contractOffer(request.getOffer()) - .protocol(request.getProtocol()) - .callbackAddresses(callbacks).build(); - } - - private boolean processNegotiated(EndpointDataReferenceEntry edrEntry) { - if (isAboutToExpire(edrEntry)) { - return entityRetryProcessFactory.doSyncProcess(edrEntry, () -> fireTransferProcess(edrEntry)) - .onDelay(this::breakLease) - .onSuccess((n, result) -> transitionToRefreshing(n)) - .onFailure((n, throwable) -> transitionToNegotiated(n)) - .onFatalError((n, failure) -> transitionToError(n, failure.getFailureDetail())) - .onRetryExhausted((n, failure) -> transitionToError(n, format("Failed renew EDR token: %s", failure.getFailureDetail()))) - .execute("Start an EDR token renewal"); - } else { - breakLease(edrEntry); - return false; - } - } - - private boolean processExpired(EndpointDataReferenceEntry edrEntry) { - return entityRetryProcessFactory.doSyncProcess(edrEntry, () -> checkExpiration(edrEntry)) - .onDelay(this::breakLease) - .execute("Start EDR token deletion check"); - - } - - - private boolean processDeleting(EndpointDataReferenceEntry edrEntry) { - return entityRetryProcessFactory.doSyncProcess(edrEntry, () -> deleteEntry(edrEntry)) - .onDelay(this::breakLease) - .onSuccess((n, result) -> { - }) - .onFailure((n, throwable) -> transitionToDeleting(n)) - .onFatalError((n, failure) -> transitionToError(n, failure.getFailureDetail())) - .onRetryExhausted((n, failure) -> transitionToError(n, format("Failed deleted EDR token: %s", failure.getFailureDetail()))) - .execute("Start EDR token deletion"); - } - - private StatusResult checkExpiration(EndpointDataReferenceEntry entry) { - if (shouldBeRemoved(entry)) { - transitionToDeleting(entry); - return StatusResult.success(); - } else { - breakLease(entry); - return StatusResult.success(); - } - } - - private StatusResult deleteEntry(EndpointDataReferenceEntry entry) { - var result = edrCache.deleteByTransferProcessId(entry.getTransferProcessId()); - if (result.succeeded()) { - monitor.debug(format("Deleted EDR cached entry for transfer process id %s", entry.getTransferProcessId())); - return StatusResult.success(); - } else { - return StatusResult.failure(ResponseStatus.FATAL_ERROR, format("Failed to delete EDR for transfer process id %s, error: %s", entry.getTransferProcessId(), result.getFailureDetail())); - } - } - - private StatusResult fireTransferProcess(EndpointDataReferenceEntry entry) { - - var transferProcess = transferProcessService.findById(entry.getTransferProcessId()); - - if (transferProcess == null) { - return StatusResult.failure(ResponseStatus.FATAL_ERROR, format("Failed to find transfer process %s", entry.getTransferProcessId())); - } - var transferRequest = TransferRequest.Builder.newInstance() - .assetId(transferProcess.getAssetId()) - .contractId(transferProcess.getContractId()) - .protocol(transferProcess.getProtocol()) - .counterPartyAddress(transferProcess.getCounterPartyAddress()) - .dataDestination(transferProcess.getDataDestination()) - .callbackAddresses(transferProcess.getCallbackAddresses()) - .build(); - - var result = transferProcessService.initiateTransfer(transferRequest); - if (result.failed()) { - var msg = format("Failed to initiate a transfer for contract %s and asset %s, error: %s", transferProcess.getContractId(), transferProcess.getAssetId(), result.getFailureDetail()); - monitor.severe(msg); - return StatusResult.failure(ResponseStatus.ERROR_RETRY, result.getFailureDetail()); - } - monitor.debug(format("Transfer with id %s initiated", result.getContent())); - return StatusResult.success(); - } - - @NotNull - private EntityRetryProcessConfiguration defaultEntityRetryProcessConfiguration() { - return new EntityRetryProcessConfiguration(DEFAULT_SEND_RETRY_LIMIT, () -> new ExponentialWaitStrategy(DEFAULT_SEND_RETRY_BASE_DELAY)); - } - - private boolean isAboutToExpire(EndpointDataReferenceEntry entry) { - if (entry.getExpirationTimestamp() == null) { - return false; - } - var expiration = Instant.ofEpochMilli(entry.getExpirationTimestamp()).atOffset(ZoneOffset.UTC).toInstant(); - var now = clock.instant().atOffset(ZoneOffset.UTC).toInstant(); - var duration = Duration.between(now, expiration); - return expiringDuration.compareTo(duration) > 0; - } - - private boolean shouldBeRemoved(EndpointDataReferenceEntry entry) { - if (entry.getExpirationTimestamp() == null) { - return false; - } - var expiration = Instant.ofEpochMilli(entry.getExpirationTimestamp()).atOffset(ZoneOffset.UTC).toInstant(); - var now = clock.instant().atOffset(ZoneOffset.UTC).toInstant(); - var duration = Duration.between(now, expiration).abs(); - return expiredRetention.compareTo(duration) <= 0; - } - - private void breakLease(EndpointDataReferenceEntry edrEntry) { - edrCache.update(edrEntry); - } - - public static class Builder { - - private final EdrManagerImpl edrManager; - - private Builder() { - edrManager = new EdrManagerImpl(); - } - - public static Builder newInstance() { - return new Builder(); - } - - public Builder contractNegotiationService(ContractNegotiationService negotiationService) { - edrManager.contractNegotiationService = negotiationService; - return this; - } - - public Builder transferProcessService(TransferProcessService transferProcessService) { - edrManager.transferProcessService = transferProcessService; - return this; - } - - public Builder monitor(Monitor monitor) { - edrManager.monitor = monitor; - return this; - } - - public Builder waitStrategy(WaitStrategy waitStrategy) { - edrManager.waitStrategy = waitStrategy; - return this; - } - - public Builder executorInstrumentation(ExecutorInstrumentation executorInstrumentation) { - edrManager.executorInstrumentation = executorInstrumentation; - return this; - } - - public Builder telemetry(Telemetry telemetry) { - edrManager.telemetry = telemetry; - return this; - } - - public Builder clock(Clock clock) { - edrManager.clock = clock; - return this; - } - - public Builder expiringDuration(Duration duration) { - edrManager.expiringDuration = duration; - return this; - } - - public Builder expiredRetention(Duration duration) { - edrManager.expiredRetention = duration; - return this; - } - - public Builder edrCache(EndpointDataReferenceCache edrCache) { - edrManager.edrCache = edrCache; - return this; - } - - public Builder batchSize(int batchSize) { - edrManager.batchSize = batchSize; - return this; - } - - public EdrManagerImpl build() { - Objects.requireNonNull(edrManager.contractNegotiationService); - Objects.requireNonNull(edrManager.monitor); - Objects.requireNonNull(edrManager.waitStrategy); - Objects.requireNonNull(edrManager.executorInstrumentation); - Objects.requireNonNull(edrManager.edrCache); - Objects.requireNonNull(edrManager.telemetry); - Objects.requireNonNull(edrManager.transferProcessService); - Objects.requireNonNull(edrManager.clock); - Objects.requireNonNull(edrManager.expiringDuration); - Objects.requireNonNull(edrManager.expiredRetention); - - edrManager.entityRetryProcessFactory = new EntityRetryProcessFactory(edrManager.monitor, edrManager.clock, edrManager.entityRetryProcessConfiguration); - - return edrManager; - } - } -} diff --git a/core/edr-core/src/main/java/org/eclipse/tractusx/edc/edr/core/service/EdrServiceImpl.java b/core/edr-core/src/main/java/org/eclipse/tractusx/edc/edr/core/service/EdrServiceImpl.java index 968611e59..17eb5adf6 100644 --- a/core/edr-core/src/main/java/org/eclipse/tractusx/edc/edr/core/service/EdrServiceImpl.java +++ b/core/edr-core/src/main/java/org/eclipse/tractusx/edc/edr/core/service/EdrServiceImpl.java @@ -19,61 +19,99 @@ package org.eclipse.tractusx.edc.edr.core.service; -import org.eclipse.edc.connector.contract.spi.types.negotiation.ContractNegotiation; +import org.eclipse.edc.edr.spi.store.EndpointDataReferenceStore; +import org.eclipse.edc.edr.spi.types.EndpointDataReferenceEntry; +import org.eclipse.edc.spi.monitor.Monitor; import org.eclipse.edc.spi.query.QuerySpec; import org.eclipse.edc.spi.result.ServiceResult; -import org.eclipse.edc.spi.types.domain.edr.EndpointDataReference; -import org.eclipse.tractusx.edc.edr.spi.EdrManager; +import org.eclipse.edc.spi.types.domain.DataAddress; +import org.eclipse.edc.transaction.spi.TransactionContext; import org.eclipse.tractusx.edc.edr.spi.service.EdrService; -import org.eclipse.tractusx.edc.edr.spi.store.EndpointDataReferenceCache; -import org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntry; -import org.eclipse.tractusx.edc.edr.spi.types.NegotiateEdrRequest; +import org.eclipse.tractusx.edc.edr.spi.types.RefreshMode; +import org.eclipse.tractusx.edc.spi.tokenrefresh.common.TokenRefreshHandler; +import java.time.Instant; import java.util.List; -import java.util.Optional; -import java.util.stream.Collectors; -import static java.lang.String.format; +import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.EDR_PROPERTY_EXPIRES_IN; public class EdrServiceImpl implements EdrService { - private final EdrManager edrManager; + private final EndpointDataReferenceStore edrStore; + private final TokenRefreshHandler tokenRefreshHandler; + private final TransactionContext transactionContext; + private final Monitor monitor; - private final EndpointDataReferenceCache endpointDataReferenceCache; - - public EdrServiceImpl(EdrManager edrManager, EndpointDataReferenceCache endpointDataReferenceCache) { - this.edrManager = edrManager; - this.endpointDataReferenceCache = endpointDataReferenceCache; + public EdrServiceImpl(EndpointDataReferenceStore edrStore, TokenRefreshHandler tokenRefreshHandler, TransactionContext transactionContext, Monitor monitor) { + this.edrStore = edrStore; + this.tokenRefreshHandler = tokenRefreshHandler; + this.transactionContext = transactionContext; + this.monitor = monitor; } @Override - public ServiceResult initiateEdrNegotiation(NegotiateEdrRequest request) { - var contractNegotiation = edrManager.initiateEdrNegotiation(request); - if (contractNegotiation.succeeded()) { - return ServiceResult.success(contractNegotiation.getContent()); - } else { - return ServiceResult.badRequest(contractNegotiation.getFailureMessages()); - } + public ServiceResult resolveByTransferProcess(String transferProcessId, RefreshMode mode) { + return transactionContext.execute(() -> edrStore.resolveByTransferProcess(transferProcessId) + .flatMap(ServiceResult::from) + .compose(edr -> handleRefresh(transferProcessId, edr, mode))); + } @Override - public ServiceResult findByTransferProcessId(String transferProcessId) { - var edr = endpointDataReferenceCache.resolveReference(transferProcessId); - return Optional.ofNullable(edr) - .map(ServiceResult::success) - .orElse(ServiceResult.notFound(format("No Edr found associated to the transfer process with id: %s", transferProcessId))); + public ServiceResult> query(QuerySpec query) { + return transactionContext.execute(() -> edrStore.query(query).flatMap(ServiceResult::from)); } - @Override - public ServiceResult> findBy(QuerySpec querySpec) { - var results = endpointDataReferenceCache.queryForEntries(querySpec).collect(Collectors.toList()); - return ServiceResult.success(results); + private ServiceResult handleRefresh(String id, DataAddress edr, RefreshMode mode) { + return switch (mode) { + case NO_REFRESH -> ServiceResult.success(edr); + case AUTO_REFRESH, FORCE_REFRESH -> autoRefresh(id, edr, mode); + }; } - @Override - public ServiceResult deleteByTransferProcessId(String transferProcessId) { - var deleted = endpointDataReferenceCache.deleteByTransferProcessId(transferProcessId); - return ServiceResult.from(deleted); + private ServiceResult autoRefresh(String id, DataAddress edr, RefreshMode mode) { + var edrEntry = edrStore.findById(id); + if (edrEntry == null) { + return ServiceResult.notFound("An EndpointDataReferenceEntry with ID '%s' does not exist".formatted(id)); + } + if (isExpired(edr, edrEntry) || mode.equals(RefreshMode.FORCE_REFRESH)) { + monitor.debug("Token expired, need to refresh."); + return tokenRefreshHandler.refreshToken(id, edr) + .compose(updated -> updateEdr(edrEntry, updated)); + } + return ServiceResult.success(edr); + } + + private ServiceResult updateEdr(EndpointDataReferenceEntry entry, DataAddress dataAddress) { + var newEntry = EndpointDataReferenceEntry.Builder.newInstance() + .assetId(entry.getAssetId()) + .agreementId(entry.getAgreementId()) + .providerId(entry.getProviderId()) + .transferProcessId(entry.getTransferProcessId()) + .contractNegotiationId(entry.getContractNegotiationId()) + .agreementId(entry.getAgreementId()) + .build(); + + var updateResult = edrStore.save(newEntry, dataAddress); + + if (updateResult.failed()) { + return ServiceResult.fromFailure(updateResult); + } + return ServiceResult.success(dataAddress); + } + + private boolean isExpired(DataAddress edr, EndpointDataReferenceEntry metadata) { + var expiresInString = edr.getStringProperty(EDR_PROPERTY_EXPIRES_IN); + if (expiresInString == null) { + return false; + } + + var expiresIn = Long.parseLong(expiresInString); + // createdAt is in millis, expires-in is in seconds + var expiresAt = metadata.getCreatedAt() / 1000L + expiresIn; + var expiresAtInstant = Instant.ofEpochSecond(expiresAt); + + return expiresAtInstant.isBefore(Instant.now()); } } diff --git a/core/edr-core/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension b/core/edr-core/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension index e5f833dc9..bddcb77ff 100644 --- a/core/edr-core/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension +++ b/core/edr-core/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension @@ -17,5 +17,4 @@ # SPDX-License-Identifier: Apache-2.0 ################################################################################# -org.eclipse.tractusx.edc.edr.core.EdrCoreExtension org.eclipse.tractusx.edc.edr.core.EdrCoreServiceExtension diff --git a/core/edr-core/src/test/java/org/eclipse/tractusx/edc/edr/core/EdrCoreExtensionTest.java b/core/edr-core/src/test/java/org/eclipse/tractusx/edc/edr/core/EdrCoreExtensionTest.java deleted file mode 100644 index 1b0381ba0..000000000 --- a/core/edr-core/src/test/java/org/eclipse/tractusx/edc/edr/core/EdrCoreExtensionTest.java +++ /dev/null @@ -1,52 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.edr.core; - -import org.eclipse.edc.connector.spi.contractnegotiation.ContractNegotiationService; -import org.eclipse.edc.junit.extensions.DependencyInjectionExtension; -import org.eclipse.edc.spi.system.ServiceExtensionContext; -import org.eclipse.tractusx.edc.edr.core.manager.EdrManagerImpl; -import org.eclipse.tractusx.edc.edr.spi.EdrManager; -import org.eclipse.tractusx.edc.edr.spi.store.EndpointDataReferenceCache; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.mock; - -@ExtendWith(DependencyInjectionExtension.class) -public class EdrCoreExtensionTest { - - @BeforeEach - void setUp(ServiceExtensionContext context) { - context.registerService(ContractNegotiationService.class, mock(ContractNegotiationService.class)); - context.registerService(EndpointDataReferenceCache.class, mock(EndpointDataReferenceCache.class)); - } - - @Test - void shouldInitializeTheExtension(ServiceExtensionContext context, EdrCoreExtension extension) { - extension.initialize(context); - - var service = context.getService(EdrManager.class); - assertThat(service).isInstanceOf(EdrManagerImpl.class); - - } -} diff --git a/core/edr-core/src/test/java/org/eclipse/tractusx/edc/edr/core/EdrCoreServiceExtensionTest.java b/core/edr-core/src/test/java/org/eclipse/tractusx/edc/edr/core/EdrCoreServiceExtensionTest.java index 9b416ad66..214289be5 100644 --- a/core/edr-core/src/test/java/org/eclipse/tractusx/edc/edr/core/EdrCoreServiceExtensionTest.java +++ b/core/edr-core/src/test/java/org/eclipse/tractusx/edc/edr/core/EdrCoreServiceExtensionTest.java @@ -22,24 +22,14 @@ import org.eclipse.edc.junit.extensions.DependencyInjectionExtension; import org.eclipse.edc.spi.system.ServiceExtensionContext; import org.eclipse.tractusx.edc.edr.core.service.EdrServiceImpl; -import org.eclipse.tractusx.edc.edr.spi.EdrManager; -import org.eclipse.tractusx.edc.edr.spi.store.EndpointDataReferenceCache; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.mock; @ExtendWith(DependencyInjectionExtension.class) public class EdrCoreServiceExtensionTest { - - @BeforeEach - void setUp(ServiceExtensionContext context) { - context.registerService(EdrManager.class, mock(EdrManager.class)); - context.registerService(EndpointDataReferenceCache.class, mock(EndpointDataReferenceCache.class)); - } - + @Test void shouldInitializeTheExtension(ServiceExtensionContext context, EdrCoreServiceExtension extension) { extension.initialize(context); diff --git a/core/edr-core/src/test/java/org/eclipse/tractusx/edc/edr/core/fixtures/TestFunctions.java b/core/edr-core/src/test/java/org/eclipse/tractusx/edc/edr/core/fixtures/TestFunctions.java index 9e300bb22..76f959163 100644 --- a/core/edr-core/src/test/java/org/eclipse/tractusx/edc/edr/core/fixtures/TestFunctions.java +++ b/core/edr-core/src/test/java/org/eclipse/tractusx/edc/edr/core/fixtures/TestFunctions.java @@ -19,37 +19,6 @@ package org.eclipse.tractusx.edc.edr.core.fixtures; -import org.eclipse.edc.connector.contract.spi.types.negotiation.ContractNegotiation; -import org.eclipse.edc.policy.model.Policy; -import org.eclipse.edc.spi.types.domain.callback.CallbackAddress; -import org.eclipse.edc.spi.types.domain.offer.ContractOffer; -import org.eclipse.tractusx.edc.edr.spi.types.NegotiateEdrRequest; - -import java.util.List; -import java.util.Set; - public class TestFunctions { - - - public static NegotiateEdrRequest getNegotiateEdrRequest() { - return NegotiateEdrRequest.Builder.newInstance() - .protocol("protocol") - .connectorAddress("http://test") - .callbackAddresses(List.of(CallbackAddress.Builder.newInstance().uri("test").events(Set.of("test")).build())) - .offer(ContractOffer.Builder.newInstance() - .id("id") - .assetId("assetId") - .policy(Policy.Builder.newInstance().build()) - .build()) - .build(); - } - - public static ContractNegotiation getContractNegotiation() { - return ContractNegotiation.Builder.newInstance() - .id("id") - .counterPartyAddress("http://test") - .counterPartyId("provider") - .protocol("protocol") - .build(); - } + } diff --git a/core/edr-core/src/test/java/org/eclipse/tractusx/edc/edr/core/manager/EdrManagerImplTest.java b/core/edr-core/src/test/java/org/eclipse/tractusx/edc/edr/core/manager/EdrManagerImplTest.java deleted file mode 100644 index f3944c207..000000000 --- a/core/edr-core/src/test/java/org/eclipse/tractusx/edc/edr/core/manager/EdrManagerImplTest.java +++ /dev/null @@ -1,274 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.edr.core.manager; - -import org.eclipse.edc.connector.contract.spi.types.negotiation.ContractRequest; -import org.eclipse.edc.connector.spi.contractnegotiation.ContractNegotiationService; -import org.eclipse.edc.connector.spi.transferprocess.TransferProcessService; -import org.eclipse.edc.connector.transfer.spi.types.ProvisionedResourceSet; -import org.eclipse.edc.connector.transfer.spi.types.TransferProcess; -import org.eclipse.edc.connector.transfer.spi.types.TransferProcessStates; -import org.eclipse.edc.spi.monitor.Monitor; -import org.eclipse.edc.spi.query.Criterion; -import org.eclipse.edc.spi.query.QuerySpec; -import org.eclipse.edc.spi.result.ServiceResult; -import org.eclipse.edc.spi.result.StoreResult; -import org.eclipse.edc.spi.types.domain.DataAddress; -import org.eclipse.tractusx.edc.edr.spi.store.EndpointDataReferenceCache; -import org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntry; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.mockito.ArgumentCaptor; - -import java.time.Clock; -import java.time.Duration; -import java.time.Instant; -import java.time.ZoneOffset; -import java.util.List; -import java.util.UUID; -import java.util.stream.Stream; - -import static java.util.Collections.emptyList; -import static org.assertj.core.api.Assertions.assertThat; -import static org.awaitility.Awaitility.await; -import static org.eclipse.edc.connector.transfer.spi.types.TransferProcess.Type.CONSUMER; -import static org.eclipse.edc.spi.persistence.StateEntityStore.hasState; -import static org.eclipse.tractusx.edc.edr.core.EdrCoreExtension.DEFAULT_BATCH_SIZE; -import static org.eclipse.tractusx.edc.edr.core.EdrCoreExtension.DEFAULT_EXPIRING_DURATION; -import static org.eclipse.tractusx.edc.edr.core.fixtures.TestFunctions.getContractNegotiation; -import static org.eclipse.tractusx.edc.edr.core.fixtures.TestFunctions.getNegotiateEdrRequest; -import static org.eclipse.tractusx.edc.edr.core.manager.EdrManagerImpl.LOCAL_CALLBACK; -import static org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntryStates.DELETING; -import static org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntryStates.ERROR; -import static org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntryStates.EXPIRED; -import static org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntryStates.NEGOTIATED; -import static org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntryStates.REFRESHING; -import static org.mockito.AdditionalMatchers.aryEq; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.ArgumentMatchers.argThat; -import static org.mockito.Mockito.atLeast; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -public class EdrManagerImplTest { - - private final EndpointDataReferenceCache edrCache = mock(EndpointDataReferenceCache.class); - private final ContractNegotiationService negotiationService = mock(ContractNegotiationService.class); - private final TransferProcessService transferProcessService = mock(TransferProcessService.class); - private EdrManagerImpl edrManager; - - @BeforeEach - void setup() { - edrManager = EdrManagerImpl.Builder.newInstance() - .contractNegotiationService(negotiationService) - .transferProcessService(transferProcessService) - .edrCache(edrCache) - .monitor(mock(Monitor.class)) - .expiredRetention(Duration.ofSeconds(1)) - .clock(Clock.systemUTC()) - .build(); - } - - @Test - @DisplayName("Verify that EDR negotiation is initiated") - void initEdrNegotiation() { - - var captor = ArgumentCaptor.forClass(ContractRequest.class); - - when(negotiationService.initiateNegotiation(any())).thenReturn(getContractNegotiation()); - - var negotiateEdrRequest = getNegotiateEdrRequest(); - - var result = edrManager.initiateEdrNegotiation(negotiateEdrRequest); - - assertThat(result.succeeded()).isTrue(); - assertThat(result.getContent()).isNotNull(); - - verify(negotiationService).initiateNegotiation(captor.capture()); - - var msg = captor.getValue(); - - assertThat(msg.getCallbackAddresses()).usingRecursiveFieldByFieldElementComparator().containsAll(negotiateEdrRequest.getCallbackAddresses()); - assertThat(msg.getCallbackAddresses()).usingRecursiveFieldByFieldElementComparator().contains(LOCAL_CALLBACK); - assertThat(msg.getContractOffer()).usingRecursiveComparison().isEqualTo(negotiateEdrRequest.getOffer()); - assertThat(msg.getProtocol()).isEqualTo(negotiateEdrRequest.getProtocol()); - assertThat(msg.getCounterPartyAddress()).isEqualTo(negotiateEdrRequest.getConnectorAddress()); - - } - - @Test - @DisplayName("Verify that EDR state should transition to REFRESHING") - void initial_shouldTransitionRequesting() { - var edrEntry = edrEntryBuilder().state(NEGOTIATED.code()).build(); - var transferProcess = createTransferProcessBuilder().build(); - when(edrCache.nextNotLeased(anyInt(), stateIs(NEGOTIATED.code()))).thenReturn(List.of(edrEntry)).thenReturn(emptyList()); - when(edrCache.findByIdAndLease(edrEntry.getTransferProcessId())).thenReturn(StoreResult.success(edrEntry)); - when(transferProcessService.findById(edrEntry.getTransferProcessId())).thenReturn(transferProcess); - when(transferProcessService.initiateTransfer(any())).thenReturn(ServiceResult.success(transferProcess)); - - edrManager.start(); - - await().untilAsserted(() -> verify(edrCache).update(argThat(p -> p.getState() == REFRESHING.code()))); - } - - @Test - @DisplayName("Verify that EDR state should not transition to REFRESHING when the token it's not expired") - void initial_shouldNotTransitionToRefreshing_WhenNotExpired() { - var expiration = Instant.now().atOffset(ZoneOffset.UTC).toInstant().plusSeconds(DEFAULT_EXPIRING_DURATION + 10); - var edrEntry = edrEntryBuilder().expirationTimestamp(expiration.toEpochMilli()).state(NEGOTIATED.code()).build(); - var transferProcess = createTransferProcessBuilder().build(); - when(edrCache.nextNotLeased(anyInt(), stateIs(NEGOTIATED.code()))) - .thenReturn(List.of(edrEntry)) - .thenReturn(List.of(edrEntry)) - .thenReturn(emptyList()); - - when(edrCache.findByIdAndLease(edrEntry.getTransferProcessId())).thenReturn(StoreResult.success(edrEntry)); - when(transferProcessService.findById(edrEntry.getTransferProcessId())).thenReturn(transferProcess); - when(transferProcessService.initiateTransfer(any())).thenReturn(ServiceResult.success(transferProcess)); - - edrManager.start(); - - await().untilAsserted(() -> { - verify(edrCache, atLeast(2)).nextNotLeased(anyInt(), stateIs(NEGOTIATED.code())); - verify(edrCache, times(0)).update(argThat(p -> p.getState() == REFRESHING.code())); - }); - } - - - @Test - @DisplayName("Verify that EDR state should transition to ERROR the transfer process is not found") - void initial_shouldTransitionError_whenTransferProcessNotFound() { - var edrEntry = edrEntryBuilder().state(NEGOTIATED.code()).build(); - when(edrCache.nextNotLeased(anyInt(), stateIs(NEGOTIATED.code()))) - .thenReturn(List.of(edrEntry)) - .thenReturn(emptyList()); - - when(edrCache.findByIdAndLease(edrEntry.getTransferProcessId())).thenReturn(StoreResult.success(edrEntry)); - when(transferProcessService.findById(edrEntry.getTransferProcessId())).thenReturn(null); - - edrManager.start(); - - await().untilAsserted(() -> verify(edrCache).update(argThat(p -> p.getState() == ERROR.code()))); - } - - - @Test - @DisplayName("Verify that EDR state should not transition to ERROR on transient errors") - void initial_shouldNotTransitionError_whenInitiatedTransferFailsOnce() { - var edrEntry = edrEntryBuilder().state(NEGOTIATED.code()).build(); - var transferProcess = createTransferProcessBuilder().build(); - - when(edrCache.nextNotLeased(anyInt(), stateIs(NEGOTIATED.code()))) - .thenReturn(List.of(edrEntry)) - .thenReturn(List.of(edrEntry.copy())) - .thenReturn(emptyList()); - - when(edrCache.findByIdAndLease(edrEntry.getTransferProcessId())).thenReturn(StoreResult.success(edrEntry)); - when(transferProcessService.findById(edrEntry.getTransferProcessId())).thenReturn(transferProcess); - when(transferProcessService.initiateTransfer(any())) - .thenReturn(ServiceResult.badRequest("bad")) - .thenReturn(ServiceResult.success(transferProcess)); - - - edrManager.start(); - - await().untilAsserted(() -> { - var captor = ArgumentCaptor.forClass(EndpointDataReferenceEntry.class); - verify(edrCache, times(2)).update(captor.capture()); - var states = captor.getAllValues().stream().map(EndpointDataReferenceEntry::getState).toList(); - assertThat(states).containsExactly(NEGOTIATED.code(), REFRESHING.code()); - }); - } - - @Test - @DisplayName("Verify that EDR state should transition to deleting when the retention period is over") - void initial_shouldTransitionToDeleting_whenTheRetentionPeriodIsOver() { - var expiration = Instant.now().atOffset(ZoneOffset.UTC).toInstant().minusSeconds(DEFAULT_EXPIRING_DURATION + 10); - var edrEntry = edrEntryBuilder().state(EXPIRED.code()).expirationTimestamp(expiration.toEpochMilli()).build(); - - when(edrCache.nextNotLeased(anyInt(), stateIs(EXPIRED.code()))) - .thenReturn(List.of(edrEntry)) - .thenReturn(emptyList()); - - edrManager.start(); - - await().untilAsserted(() -> verify(edrCache).update(argThat(p -> p.getState() == DELETING.code()))); - } - - @Test - @DisplayName("Verify that EDR is deleted when state is DELETING") - void initial_shouldDeleteTheEntry_whenTheRetentionPeriodIsOver() { - var expiration = Instant.now().atOffset(ZoneOffset.UTC).toInstant().minusSeconds(DEFAULT_EXPIRING_DURATION + 10); - var edrEntry = edrEntryBuilder().state(DELETING.code()).expirationTimestamp(expiration.toEpochMilli()).build(); - - var query = QuerySpec.Builder.newInstance() - .filter(hasState(DELETING.code())) - .limit(DEFAULT_BATCH_SIZE) - .build(); - - when(edrCache.queryForEntries(query)) - .thenReturn(Stream.of(edrEntry)) - .thenReturn(Stream.empty()); - - - when(edrCache.deleteByTransferProcessId(edrEntry.getTransferProcessId())).thenReturn(StoreResult.success()); - - edrManager.start(); - - await().untilAsserted(() -> { - verify(edrCache, times(1)).deleteByTransferProcessId(edrEntry.getTransferProcessId()); - }); - } - - - private EndpointDataReferenceEntry.Builder edrEntryBuilder() { - return EndpointDataReferenceEntry.Builder.newInstance() - .id(UUID.randomUUID().toString()) - .assetId(UUID.randomUUID().toString()) - .agreementId(UUID.randomUUID().toString()) - .transferProcessId(UUID.randomUUID().toString()) - .expirationTimestamp(Instant.now().toEpochMilli()) - .stateTimestamp(Instant.now().toEpochMilli()); - } - - private TransferProcess.Builder createTransferProcessBuilder() { - var processId = UUID.randomUUID().toString(); - - return TransferProcess.Builder.newInstance() - .provisionedResourceSet(ProvisionedResourceSet.Builder.newInstance().build()) - .type(CONSUMER) - .id("test-process-" + processId) - .state(TransferProcessStates.COMPLETED.code()) - .contractId(UUID.randomUUID().toString()) - .assetId(UUID.randomUUID().toString()) - .protocol("protocol") - .dataDestination(DataAddress.Builder.newInstance().type("test-type").build()) - .counterPartyAddress("http://an/address"); - } - - private Criterion[] stateIs(int state) { - return aryEq(new Criterion[]{ hasState(state) }); - } - -} diff --git a/core/edr-core/src/test/java/org/eclipse/tractusx/edc/edr/core/service/EdrServiceImplTest.java b/core/edr-core/src/test/java/org/eclipse/tractusx/edc/edr/core/service/EdrServiceImplTest.java index d19b5e180..a99877af6 100644 --- a/core/edr-core/src/test/java/org/eclipse/tractusx/edc/edr/core/service/EdrServiceImplTest.java +++ b/core/edr-core/src/test/java/org/eclipse/tractusx/edc/edr/core/service/EdrServiceImplTest.java @@ -19,157 +19,162 @@ package org.eclipse.tractusx.edc.edr.core.service; -import org.eclipse.edc.connector.contract.spi.types.negotiation.ContractNegotiation; -import org.eclipse.edc.policy.model.Policy; +import org.assertj.core.api.Assertions; +import org.eclipse.edc.edr.spi.store.EndpointDataReferenceStore; +import org.eclipse.edc.edr.spi.types.EndpointDataReferenceEntry; import org.eclipse.edc.spi.query.QuerySpec; -import org.eclipse.edc.spi.response.StatusResult; -import org.eclipse.edc.spi.result.ServiceFailure; import org.eclipse.edc.spi.result.ServiceResult; import org.eclipse.edc.spi.result.StoreResult; -import org.eclipse.edc.spi.types.domain.callback.CallbackAddress; -import org.eclipse.edc.spi.types.domain.edr.EndpointDataReference; -import org.eclipse.edc.spi.types.domain.offer.ContractOffer; -import org.eclipse.tractusx.edc.edr.spi.EdrManager; -import org.eclipse.tractusx.edc.edr.spi.store.EndpointDataReferenceCache; -import org.eclipse.tractusx.edc.edr.spi.types.NegotiateEdrRequest; +import org.eclipse.edc.spi.types.domain.DataAddress; +import org.eclipse.edc.transaction.spi.NoopTransactionContext; +import org.eclipse.tractusx.edc.spi.tokenrefresh.common.TokenRefreshHandler; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; import java.util.List; -import java.util.Set; -import java.util.stream.Stream; +import java.util.UUID; -import static org.assertj.core.api.Assertions.assertThat; +import static org.eclipse.edc.junit.assertions.AbstractResultAssert.assertThat; +import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.TX_AUTH_NS; +import static org.eclipse.tractusx.edc.edr.spi.types.RefreshMode.AUTO_REFRESH; +import static org.eclipse.tractusx.edc.edr.spi.types.RefreshMode.FORCE_REFRESH; +import static org.eclipse.tractusx.edc.edr.spi.types.RefreshMode.NO_REFRESH; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoInteractions; +import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; public class EdrServiceImplTest { - EdrManager edrManager = mock(EdrManager.class); - - EndpointDataReferenceCache endpointDataReferenceCache = mock(EndpointDataReferenceCache.class); - - EdrServiceImpl transferService; + private final TokenRefreshHandler tokenRefreshHandler = mock(); + private final EndpointDataReferenceStore edrStore = mock(); + private EdrServiceImpl edrService; @BeforeEach void setup() { - transferService = new EdrServiceImpl(edrManager, endpointDataReferenceCache); + edrService = new EdrServiceImpl(edrStore, tokenRefreshHandler, new NoopTransactionContext(), mock()); + } + + @Test + void query() { + + when(edrStore.query(any())).thenReturn(StoreResult.success(List.of())); + + assertThat(edrService.query(QuerySpec.max())).isSucceeded().satisfies(results -> { + Assertions.assertThat(results).isEmpty(); + }); } @Test - void initEdrNegotiation_shouldFireContractNegotiation_WhenUsingCallbacks() { + void resolveByTransferProcess_whenNoRefresh() { - when(edrManager.initiateEdrNegotiation(any())).thenReturn(StatusResult.success(getContractNegotiation())); + var transferProcess = "tp"; + when(edrStore.resolveByTransferProcess(transferProcess)).thenReturn(StoreResult.success(edr())); - var negotiateEdrRequest = getNegotiateEdrRequest(); + var result = edrService.resolveByTransferProcess(transferProcess, NO_REFRESH); - var result = transferService.initiateEdrNegotiation(negotiateEdrRequest); + assertThat(result).isSucceeded(); - assertThat(result.succeeded()).isTrue(); - assertThat(result.getContent()).isNotNull(); + verify(edrStore).resolveByTransferProcess(transferProcess); + verifyNoMoreInteractions(edrStore); + verifyNoInteractions(tokenRefreshHandler); } @Test - void findByTransferProcessId_shouldReturnTheEdr_whenFoundInCache() { + void resolveByTransferProcess_whenRefreshNotExpired() { - var transferProcessId = "tpId"; + var transferProcess = "tp"; + var assetId = "assetId"; + when(edrStore.resolveByTransferProcess(transferProcess)).thenReturn(StoreResult.success(edr("1000"))); + when(edrStore.findById(transferProcess)).thenReturn(edrEntry(assetId, transferProcess)); - when(endpointDataReferenceCache.resolveReference(eq(transferProcessId))) - .thenReturn(EndpointDataReference.Builder.newInstance() - .id("test-id") - .contractId("test-contract") - .endpoint("test") - .build()); + var result = edrService.resolveByTransferProcess(transferProcess, AUTO_REFRESH); - var result = transferService.findByTransferProcessId(transferProcessId); + assertThat(result).isSucceeded(); - assertThat(result) - .isNotNull() - .extracting(ServiceResult::getContent) - .isNotNull(); - } + verify(edrStore).resolveByTransferProcess(transferProcess); + verify(edrStore).findById(transferProcess); + verifyNoMoreInteractions(edrStore); + verifyNoInteractions(tokenRefreshHandler); + } @Test - void findByTransferProcessId_shouldNotFound_whenNotPresentInCache() { - var transferProcessId = "tpId"; + void resolveByTransferProcess_whenRefreshExpired() { - when(endpointDataReferenceCache.resolveReference(transferProcessId)).thenReturn(null); + var transferProcess = "tp"; + var assetId = "assetId"; + var entry = edrEntry(assetId, transferProcess); + var refreshedEdr = edr(); - var result = transferService.findByTransferProcessId(transferProcessId); + when(edrStore.resolveByTransferProcess(transferProcess)).thenReturn(StoreResult.success(edr("-1000"))); + when(edrStore.findById(transferProcess)).thenReturn(entry); + when(tokenRefreshHandler.refreshToken(eq(transferProcess), any())).thenReturn(ServiceResult.success(refreshedEdr)); + when(edrStore.save(any(), eq(refreshedEdr))).thenReturn(StoreResult.success()); - assertThat(result) - .isNotNull() - .extracting(ServiceResult::getFailure) - .extracting(ServiceFailure::getReason) - .isEqualTo(ServiceFailure.Reason.NOT_FOUND); - } + var result = edrService.resolveByTransferProcess(transferProcess, AUTO_REFRESH); - @Test - void deleteByTransferProcessId() { - var transferProcessId = "tpId"; + assertThat(result).isSucceeded(); - when(endpointDataReferenceCache.deleteByTransferProcessId(transferProcessId)).thenReturn(StoreResult.success(null)); + var captor = ArgumentCaptor.forClass(EndpointDataReferenceEntry.class); + verify(edrStore).resolveByTransferProcess(transferProcess); + verify(edrStore).findById(transferProcess); + verify(edrStore).save(captor.capture(), eq(refreshedEdr)); + verify(tokenRefreshHandler).refreshToken(eq(transferProcess), any()); - var result = transferService.deleteByTransferProcessId(transferProcessId); + verifyNoMoreInteractions(edrStore, tokenRefreshHandler); - assertThat(result) - .isNotNull() - .extracting(ServiceResult::succeeded) - .isEqualTo(true); + Assertions.assertThat(captor.getValue()).usingRecursiveComparison().ignoringFields("createdAt").isEqualTo(entry); } @Test - void deleteByTransferProcessId_shouldNotFound_whenNotPresentInCache() { - var transferProcessId = "tpId"; + void resolveByTransferProcess_forceRefresh() { - when(endpointDataReferenceCache.deleteByTransferProcessId(eq(transferProcessId))).thenReturn(StoreResult.notFound("")); + var transferProcess = "tp"; + var assetId = "assetId"; + var entry = edrEntry(assetId, transferProcess); + var refreshedEdr = edr(); + when(edrStore.resolveByTransferProcess(transferProcess)).thenReturn(StoreResult.success(edr("1000"))); + when(edrStore.findById(transferProcess)).thenReturn(entry); + when(tokenRefreshHandler.refreshToken(eq(transferProcess), any())).thenReturn(ServiceResult.success(refreshedEdr)); + when(edrStore.save(any(), eq(refreshedEdr))).thenReturn(StoreResult.success()); - var result = transferService.deleteByTransferProcessId(transferProcessId); + var result = edrService.resolveByTransferProcess(transferProcess, FORCE_REFRESH); - assertThat(result) - .isNotNull() - .extracting(ServiceResult::getFailure) - .extracting(ServiceFailure::getReason) - .isEqualTo(ServiceFailure.Reason.NOT_FOUND); - } + assertThat(result).isSucceeded(); - @Test - void queryEdrs() { - when(endpointDataReferenceCache.queryForEntries(any())).thenReturn(Stream.empty()); + var captor = ArgumentCaptor.forClass(EndpointDataReferenceEntry.class); + verify(edrStore).resolveByTransferProcess(transferProcess); + verify(edrStore).findById(transferProcess); + verify(edrStore).save(captor.capture(), eq(refreshedEdr)); + verify(tokenRefreshHandler).refreshToken(eq(transferProcess), any()); - var result = transferService.findBy(QuerySpec.Builder.newInstance().build()); + verifyNoMoreInteractions(edrStore, tokenRefreshHandler); - assertThat(result) - .isNotNull() - .extracting(ServiceResult::getContent) - .extracting(List::size) - .isEqualTo(0); + Assertions.assertThat(captor.getValue()).usingRecursiveComparison().ignoringFields("createdAt").isEqualTo(entry); } - private NegotiateEdrRequest getNegotiateEdrRequest() { - return NegotiateEdrRequest.Builder.newInstance() - .protocol("protocol") - .connectorAddress("http://test") - .callbackAddresses(List.of(CallbackAddress.Builder.newInstance().uri("test").events(Set.of("test")).build())) - .offer(ContractOffer.Builder.newInstance() - .id("id") - .assetId("assetId") - .policy(Policy.Builder.newInstance().build()) - .build()) - .build(); + private DataAddress edr(String expireIn) { + return DataAddress.Builder.newInstance().type("test").property(TX_AUTH_NS + "expiresIn", expireIn).build(); + } + + private DataAddress edr() { + return edr(null); } - private ContractNegotiation getContractNegotiation() { - return ContractNegotiation.Builder.newInstance() - .id("id") - .counterPartyAddress("http://test") - .counterPartyId("provider") - .protocol("protocol") + private EndpointDataReferenceEntry edrEntry(String assetId, String transferProcessId) { + return EndpointDataReferenceEntry.Builder.newInstance() + .assetId(assetId) + .transferProcessId(transferProcessId) + .contractNegotiationId(UUID.randomUUID().toString()) + .agreementId(UUID.randomUUID().toString()) + .providerId(UUID.randomUUID().toString()) .build(); } } diff --git a/edc-controlplane/edc-controlplane-base/build.gradle.kts b/edc-controlplane/edc-controlplane-base/build.gradle.kts index fcd3ea7e0..ad2da35ba 100644 --- a/edc-controlplane/edc-controlplane-base/build.gradle.kts +++ b/edc-controlplane/edc-controlplane-base/build.gradle.kts @@ -23,7 +23,6 @@ plugins { } dependencies { - runtimeOnly(project(":core:edr-cache-core")) runtimeOnly(project(":core:edr-core")) runtimeOnly(project(":edc-extensions:dataplane:dataplane-selector-configuration")) diff --git a/edc-dataplane/edc-dataplane-base/build.gradle.kts b/edc-dataplane/edc-dataplane-base/build.gradle.kts index 9132e462b..41a73a75a 100644 --- a/edc-dataplane/edc-dataplane-base/build.gradle.kts +++ b/edc-dataplane/edc-dataplane-base/build.gradle.kts @@ -23,7 +23,9 @@ plugins { } dependencies { - runtimeOnly(project(":core:edr-cache-core")) + runtimeOnly(project(":core:edr-core")) + runtimeOnly(project(":edc-extensions:tokenrefresh-handler")) + runtimeOnly(project(":edc-extensions:iatp:tx-iatp-sts-dim")) runtimeOnly(project(":edc-extensions:dataplane:dataplane-proxy:edc-dataplane-proxy-consumer-api")) runtimeOnly(project(":edc-extensions:dataplane:dataplane-token-refresh:token-refresh-core")) runtimeOnly(project(":edc-extensions:dataplane:dataplane-token-refresh:token-refresh-api")) @@ -46,6 +48,7 @@ dependencies { runtimeOnly(libs.edc.dpf.api.public.v2) runtimeOnly(libs.edc.core.connector) runtimeOnly(libs.edc.boot) + runtimeOnly(libs.edc.core.edrstore) runtimeOnly(libs.bundles.edc.monitoring) runtimeOnly(libs.edc.ext.http) diff --git a/edc-extensions/bpn-validation/business-partner-store-sql/src/test/java/org/eclipse/tractusx/edc/validation/businesspartner/store/sql/SqlBusinessPartnerStoreTest.java b/edc-extensions/bpn-validation/business-partner-store-sql/src/test/java/org/eclipse/tractusx/edc/validation/businesspartner/store/sql/SqlBusinessPartnerStoreTest.java index c8af6d7fe..cd3e83c1d 100644 --- a/edc-extensions/bpn-validation/business-partner-store-sql/src/test/java/org/eclipse/tractusx/edc/validation/businesspartner/store/sql/SqlBusinessPartnerStoreTest.java +++ b/edc-extensions/bpn-validation/business-partner-store-sql/src/test/java/org/eclipse/tractusx/edc/validation/businesspartner/store/sql/SqlBusinessPartnerStoreTest.java @@ -19,6 +19,7 @@ package org.eclipse.tractusx.edc.validation.businesspartner.store.sql; +import org.eclipse.edc.junit.annotations.PostgresqlIntegrationTest; import org.eclipse.edc.spi.types.TypeManager; import org.eclipse.edc.sql.QueryExecutor; import org.eclipse.edc.sql.testfixtures.PostgresqlStoreSetupExtension; @@ -32,6 +33,7 @@ import java.nio.file.Files; import java.nio.file.Paths; +@PostgresqlIntegrationTest @ExtendWith(PostgresqlStoreSetupExtension.class) class SqlBusinessPartnerStoreTest extends BusinessPartnerStoreTestBase { private final TypeManager typeManager = new TypeManager(); diff --git a/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-consumer-api/build.gradle.kts b/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-consumer-api/build.gradle.kts index ebc229f52..d76a0fe64 100644 --- a/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-consumer-api/build.gradle.kts +++ b/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-consumer-api/build.gradle.kts @@ -32,6 +32,7 @@ dependencies { implementation(libs.edc.dpf.util) implementation(libs.edc.ext.http) implementation(libs.edc.spi.auth) + implementation(libs.edc.spi.edrstore) implementation(project(":spi:edr-spi")) diff --git a/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-consumer-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/consumer/api/DataPlaneProxyConsumerApiExtension.java b/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-consumer-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/consumer/api/DataPlaneProxyConsumerApiExtension.java index abbecdd02..39ee2fe18 100644 --- a/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-consumer-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/consumer/api/DataPlaneProxyConsumerApiExtension.java +++ b/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-consumer-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/consumer/api/DataPlaneProxyConsumerApiExtension.java @@ -34,7 +34,7 @@ import org.eclipse.edc.web.spi.configuration.WebServiceSettings; import org.eclipse.tractusx.edc.dataplane.proxy.consumer.api.asset.ClientErrorExceptionMapper; import org.eclipse.tractusx.edc.dataplane.proxy.consumer.api.asset.ConsumerAssetRequestController; -import org.eclipse.tractusx.edc.edr.spi.store.EndpointDataReferenceCache; +import org.eclipse.tractusx.edc.edr.spi.service.EdrService; import java.util.concurrent.ExecutorService; @@ -65,7 +65,7 @@ public class DataPlaneProxyConsumerApiExtension implements ServiceExtension { private PipelineService pipelineService; @Inject - private EndpointDataReferenceCache edrCache; + private EdrService edrService; @Inject private WebServiceConfigurer configurer; @@ -92,7 +92,7 @@ public void initialize(ServiceExtensionContext context) { webService.registerResource(CONSUMER_API_ALIAS, new AuthenticationRequestFilter(authenticationService)); webService.registerResource(CONSUMER_API_ALIAS, new ClientErrorExceptionMapper()); - webService.registerResource(CONSUMER_API_ALIAS, new ConsumerAssetRequestController(edrCache, pipelineService, executorService, monitor)); + webService.registerResource(CONSUMER_API_ALIAS, new ConsumerAssetRequestController(edrService, pipelineService, executorService, monitor)); } @Override diff --git a/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-consumer-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/consumer/api/asset/ConsumerAssetRequestController.java b/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-consumer-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/consumer/api/asset/ConsumerAssetRequestController.java index f2a22de1f..42ba2f807 100644 --- a/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-consumer-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/consumer/api/asset/ConsumerAssetRequestController.java +++ b/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-consumer-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/consumer/api/asset/ConsumerAssetRequestController.java @@ -33,16 +33,18 @@ import org.eclipse.edc.connector.dataplane.spi.pipeline.TransferService; import org.eclipse.edc.connector.dataplane.util.sink.AsyncStreamingDataSink; import org.eclipse.edc.spi.monitor.Monitor; +import org.eclipse.edc.spi.query.Criterion; +import org.eclipse.edc.spi.query.QuerySpec; import org.eclipse.edc.spi.types.domain.DataAddress; -import org.eclipse.edc.spi.types.domain.edr.EndpointDataReference; import org.eclipse.edc.spi.types.domain.transfer.DataFlowStartMessage; import org.eclipse.tractusx.edc.dataplane.proxy.consumer.api.asset.model.AssetRequest; -import org.eclipse.tractusx.edc.edr.spi.store.EndpointDataReferenceCache; +import org.eclipse.tractusx.edc.edr.spi.service.EdrService; import java.util.HashMap; import java.util.Map; import java.util.Optional; import java.util.concurrent.ExecutorService; +import java.util.function.Function; import static jakarta.ws.rs.core.MediaType.APPLICATION_JSON; import static jakarta.ws.rs.core.Response.Status.BAD_GATEWAY; @@ -55,6 +57,7 @@ import static org.eclipse.edc.connector.dataplane.spi.schema.DataFlowRequestSchema.PATH; import static org.eclipse.edc.connector.dataplane.spi.schema.DataFlowRequestSchema.QUERY_PARAMS; import static org.eclipse.edc.spi.CoreConstants.EDC_NAMESPACE; +import static org.eclipse.tractusx.edc.edr.spi.types.RefreshMode.AUTO_REFRESH; /** * Implements the HTTP proxy API. @@ -62,22 +65,28 @@ @Path("/aas") @Produces(MediaType.APPLICATION_JSON) public class ConsumerAssetRequestController implements ConsumerAssetRequestApi { - public static final String BASE_URL = EDC_NAMESPACE + "baseUrl"; + public static final String BASE_URL = EDC_NAMESPACE + "endpoint"; + public static final String EDR_ERROR_MESSAGE = "No EDR for transfer process: %s : %s"; private static final String ASYNC_TYPE = "async"; private static final String HEADER_AUTHORIZATION = "header:authorization"; private static final String BEARER_PREFIX = "Bearer "; - - private final EndpointDataReferenceCache edrCache; + private final EdrService edrService; private final TransferService transferService; private final Monitor monitor; private final ExecutorService executorService; - public ConsumerAssetRequestController(EndpointDataReferenceCache edrCache, + + private final Map> mappers = Map.of( + "provider", AssetRequest::getProviderId, + "transferProcessId", AssetRequest::getTransferProcessId, + "assetId", AssetRequest::getAssetId); + + public ConsumerAssetRequestController(EdrService edrService, TransferService transferService, ExecutorService executorService, Monitor monitor) { - this.edrCache = edrCache; + this.edrService = edrService; this.transferService = transferService; this.executorService = executorService; this.monitor = monitor; @@ -90,20 +99,14 @@ public void requestAsset(AssetRequest request, @Suspended AsyncResponse response // resolve the EDR and add it to the request var edr = resolveEdr(request); - var sourceAddress = Optional.ofNullable(request.getEndpointUrl()) - .map(url -> gatewayAddress(url, edr)) - .orElseGet(() -> dataPlaneAddress(edr)); - + var sourceAddress = dataPlaneAddress(edr); + var properties = dataPlaneProperties(request); var destinationAddress = DataAddress.Builder.newInstance() .type(ASYNC_TYPE) .build(); - var properties = Optional.ofNullable(request.getEndpointUrl()) - .map((url) -> Map.of()) - .orElseGet(() -> dataPlaneProperties(request)); - var flowRequest = DataFlowStartMessage.Builder.newInstance() .processId(randomUUID().toString()) .sourceDataAddress(sourceAddress) @@ -136,38 +139,65 @@ private Map dataPlaneProperties(AssetRequest request) { return props; } - private DataAddress gatewayAddress(String url, EndpointDataReference edr) { - return HttpDataAddress.Builder.newInstance() - .baseUrl(url) - .property(HEADER_AUTHORIZATION, BEARER_PREFIX + edr.getAuthCode()) - .build(); - } - private DataAddress dataPlaneAddress(EndpointDataReference edr) { + private DataAddress dataPlaneAddress(DataAddress edr) { + // TODO the header scheme should be dynamic based on the `authType` + // https://github.com/eclipse-edc/Connector/blob/main/docs/developer/data-plane-signaling/data-plane-signaling-token-handling.md + var endpoint = edr.getStringProperty("endpoint"); + var token = edr.getStringProperty("authorization"); return HttpDataAddress.Builder.newInstance() - .baseUrl(edr.getEndpoint()) + .baseUrl(endpoint) .proxyQueryParams("true") .proxyPath("true") - .property(HEADER_AUTHORIZATION, edr.getAuthCode()) + .property(HEADER_AUTHORIZATION, BEARER_PREFIX + token) .build(); } - private EndpointDataReference resolveEdr(AssetRequest request) { + private DataAddress resolveEdr(AssetRequest request) { if (request.getTransferProcessId() != null) { - var edr = edrCache.resolveReference(request.getTransferProcessId()); - if (edr == null) { - throw new BadRequestException("No EDR for transfer process: " + request.getTransferProcessId()); + var edr = edrService.resolveByTransferProcess(request.getTransferProcessId(), AUTO_REFRESH); + if (edr.failed()) { + throw new BadRequestException(EDR_ERROR_MESSAGE.formatted(request.getTransferProcessId(), edr.getFailureDetail())); } - return edr; + return edr.getContent(); } else { - var resolvedEdrs = edrCache.referencesForAsset(request.getAssetId(), request.getProviderId()); - if (resolvedEdrs.isEmpty()) { + var resolvedEdrs = edrService.query(toQuery(request)); + + if (resolvedEdrs.failed()) { + throw new BadRequestException(EDR_ERROR_MESSAGE.formatted(request.getTransferProcessId(), resolvedEdrs.getFailureDetail())); + } + + var edrs = resolvedEdrs.getContent(); + if (edrs.isEmpty()) { throw new BadRequestException("No EDR for asset: " + request.getAssetId()); - } else if (resolvedEdrs.size() > 1) { + } else if (edrs.size() > 1) { throw new PreconditionFailedException("More than one EDR for asset: " + request.getAssetId()); } - return resolvedEdrs.get(0); + + var edrEntry = edrs.get(0); + + var edr = edrService.resolveByTransferProcess(edrEntry.getTransferProcessId(), AUTO_REFRESH); + if (edr.failed()) { + throw new BadRequestException(EDR_ERROR_MESSAGE.formatted(edrEntry.getTransferProcessId(), edr.getFailureDetail())); + } + return edr.getContent(); + + } + } + + private QuerySpec toQuery(AssetRequest request) { + var specBuilder = QuerySpec.Builder.newInstance(); + mappers.entrySet() + .stream() + .filter(entry -> entry.getValue().apply(request) != null) + .forEach(entry -> specBuilder.filter(Criterion.criterion(entry.getKey(), "=", entry.getValue().apply(request)))); + + var spec = specBuilder.build(); + + if (spec.getFilterExpression().isEmpty()) { + throw new BadRequestException("No Filter provided in the request"); } + return spec; } /** diff --git a/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-consumer-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/consumer/api/asset/model/AssetRequest.java b/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-consumer-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/consumer/api/asset/model/AssetRequest.java index fb1bbd468..28c146c00 100644 --- a/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-consumer-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/consumer/api/asset/model/AssetRequest.java +++ b/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-consumer-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/consumer/api/asset/model/AssetRequest.java @@ -34,7 +34,6 @@ public class AssetRequest { private String assetId; private String providerId; - private String endpointUrl; private String queryParams; @@ -51,10 +50,6 @@ public String getAssetId() { return assetId; } - public String getEndpointUrl() { - return endpointUrl; - } - public String getProviderId() { return providerId; } @@ -89,12 +84,7 @@ public Builder assetId(String assetId) { request.assetId = assetId; return this; } - - public Builder endpointUrl(String endpointUrl) { - request.endpointUrl = endpointUrl; - return this; - } - + public Builder providerId(String providerId) { request.providerId = providerId; return this; diff --git a/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-consumer-api/src/test/java/org/eclipse/tractusx/edc/dataplane/proxy/consumer/api/asset/model/AssetRequestTest.java b/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-consumer-api/src/test/java/org/eclipse/tractusx/edc/dataplane/proxy/consumer/api/asset/model/AssetRequestTest.java index cb89f5aa1..17e79270e 100644 --- a/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-consumer-api/src/test/java/org/eclipse/tractusx/edc/dataplane/proxy/consumer/api/asset/model/AssetRequestTest.java +++ b/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-consumer-api/src/test/java/org/eclipse/tractusx/edc/dataplane/proxy/consumer/api/asset/model/AssetRequestTest.java @@ -34,7 +34,6 @@ void verify_SerializeDeserialize() throws JsonProcessingException { var request = AssetRequest.Builder.newInstance() .assetId("asset1") - .endpointUrl("https://test.com") .providerId("providerId") .transferProcessId("tp1") .queryParams("params") @@ -47,7 +46,6 @@ void verify_SerializeDeserialize() throws JsonProcessingException { assertThat(deserialized.getAssetId()).isEqualTo(request.getAssetId()); assertThat(deserialized.getTransferProcessId()).isEqualTo(request.getTransferProcessId()); - assertThat(deserialized.getEndpointUrl()).isEqualTo(request.getEndpointUrl()); assertThat(deserialized.getProviderId()).isEqualTo(request.getProviderId()); assertThat(deserialized.getPathSegments()).isEqualTo(request.getPathSegments()); assertThat(deserialized.getQueryParams()).isEqualTo(request.getQueryParams()); @@ -61,7 +59,7 @@ void verify_NullArguments() { @Test void verify_AssetIdOrTransferProcessId() { - AssetRequest.Builder.newInstance().assetId("asset1").endpointUrl("https://test.com").build(); - AssetRequest.Builder.newInstance().transferProcessId("tp1").endpointUrl("https://test.com").build(); + AssetRequest.Builder.newInstance().assetId("asset1").build(); + AssetRequest.Builder.newInstance().transferProcessId("tp1").build(); } } diff --git a/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-consumer-api/src/test/java/org/eclipse/tractusx/edc/dataplane/proxy/consumer/api/asset/model/ConsumerAssetRequestControllerTest.java b/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-consumer-api/src/test/java/org/eclipse/tractusx/edc/dataplane/proxy/consumer/api/asset/model/ConsumerAssetRequestControllerTest.java index e8709749a..9a383d5aa 100644 --- a/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-consumer-api/src/test/java/org/eclipse/tractusx/edc/dataplane/proxy/consumer/api/asset/model/ConsumerAssetRequestControllerTest.java +++ b/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-consumer-api/src/test/java/org/eclipse/tractusx/edc/dataplane/proxy/consumer/api/asset/model/ConsumerAssetRequestControllerTest.java @@ -26,14 +26,16 @@ import org.eclipse.edc.connector.dataplane.spi.pipeline.DataSource; import org.eclipse.edc.connector.dataplane.spi.pipeline.PipelineService; import org.eclipse.edc.connector.dataplane.spi.pipeline.StreamResult; +import org.eclipse.edc.edr.spi.types.EndpointDataReferenceEntry; import org.eclipse.edc.junit.annotations.ApiTest; import org.eclipse.edc.spi.monitor.Monitor; -import org.eclipse.edc.spi.types.domain.edr.EndpointDataReference; +import org.eclipse.edc.spi.result.ServiceResult; +import org.eclipse.edc.spi.types.domain.DataAddress; import org.eclipse.edc.spi.types.domain.transfer.DataFlowStartMessage; import org.eclipse.edc.web.jersey.testfixtures.RestControllerTestBase; import org.eclipse.tractusx.edc.dataplane.proxy.consumer.api.asset.ClientErrorExceptionMapper; import org.eclipse.tractusx.edc.dataplane.proxy.consumer.api.asset.ConsumerAssetRequestController; -import org.eclipse.tractusx.edc.edr.spi.store.EndpointDataReferenceCache; +import org.eclipse.tractusx.edc.edr.spi.service.EdrService; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; @@ -57,6 +59,7 @@ import static org.eclipse.edc.connector.dataplane.spi.schema.DataFlowRequestSchema.PATH; import static org.eclipse.edc.connector.dataplane.spi.schema.DataFlowRequestSchema.QUERY_PARAMS; import static org.eclipse.tractusx.edc.dataplane.proxy.consumer.api.asset.ConsumerAssetRequestController.BASE_URL; +import static org.eclipse.tractusx.edc.edr.spi.types.RefreshMode.AUTO_REFRESH; import static org.hamcrest.Matchers.notNullValue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; @@ -67,7 +70,7 @@ public class ConsumerAssetRequestControllerTest extends RestControllerTestBase { public static final String ASSET_REQUEST_PATH = "/aas/request"; - private final EndpointDataReferenceCache cache = mock(EndpointDataReferenceCache.class); + private final EdrService edrService = mock(EdrService.class); private final PipelineService pipelineService = mock(); private final ObjectMapper mapper = new ObjectMapper(); @@ -83,15 +86,7 @@ void requestAsset_shouldReturnData_withAssetId() throws IOException { var assetId = "assetId"; var transferProcessId = "tp"; - var url = "http://localhost:8080/test"; - var request = Map.of("assetId", assetId, "endpointUrl", url); - var edr = EndpointDataReference.Builder.newInstance() - .id(transferProcessId) - .authKey("authKey") - .authCode("authCode") - .contractId("contract-id") - .endpoint(url) - .build(); + var request = Map.of("assetId", assetId); var response = Map.of("response", "ok"); var responseBytes = mapper.writeValueAsBytes(response); @@ -102,7 +97,8 @@ void requestAsset_shouldReturnData_withAssetId() throws IOException { when(datasource.openPartStream()).thenReturn(StreamResult.success(Stream.of(partStream))); when(partStream.openStream()).thenReturn(new ByteArrayInputStream(responseBytes)); - when(cache.referencesForAsset(assetId, null)).thenReturn(List.of(edr)); + when(edrService.query(any())).thenReturn(ServiceResult.success(List.of(edrEntry(assetId, transferProcessId)))); + when(edrService.resolveByTransferProcess(transferProcessId, AUTO_REFRESH)).thenReturn(ServiceResult.success(edr())); when(pipelineService.transfer(any(), any())) .thenAnswer(a -> CompletableFuture.completedFuture(StreamResult.success(response))); @@ -126,17 +122,10 @@ void requestAsset_shouldReturnError_WhenProxyCallFails(StreamResult resu var assetId = "assetId"; var transferProcessId = "tp"; - var url = "http://localhost:8080/test"; - var request = Map.of("assetId", assetId, "endpointUrl", url); - var edr = EndpointDataReference.Builder.newInstance() - .id(transferProcessId) - .authKey("authKey") - .authCode("authCode") - .endpoint(url) - .contractId("contract-id") - .build(); + var request = Map.of("assetId", assetId); - when(cache.referencesForAsset(assetId, null)).thenReturn(List.of(edr)); + when(edrService.query(any())).thenReturn(ServiceResult.success(List.of(edrEntry(assetId, transferProcessId)))); + when(edrService.resolveByTransferProcess(transferProcessId, AUTO_REFRESH)).thenReturn(ServiceResult.success(edr())); when(pipelineService.transfer(any(), any())) .thenReturn(CompletableFuture.completedFuture(result)); @@ -154,9 +143,9 @@ void requestAsset_shouldReturnError_whenEdrByAssetIdNotFound() { var assetId = "assetId"; var url = "http://localhost:8080/test"; - var request = Map.of("assetId", assetId, "endpointUrl", url); + var request = Map.of("assetId", assetId); - when(cache.referencesForAsset(assetId, null)).thenReturn(List.of()); + when(edrService.query(any())).thenReturn(ServiceResult.success(List.of())); baseRequest() .contentType(MediaType.APPLICATION_JSON) @@ -172,18 +161,9 @@ void requestAsset_shouldReturnError_whenEdrByAssetIdNotFound() { void requestAsset_shouldReturnError_whenMultipleEdrsByAssetIdFound() { var assetId = "assetId"; - var url = "http://localhost:8080/test"; - var request = Map.of("assetId", assetId, "endpointUrl", url); - - var edr = EndpointDataReference.Builder.newInstance() - .id(UUID.randomUUID().toString()) - .authKey("authKey") - .authCode("authCode") - .contractId("contract-id") - .endpoint(url) - .build(); + var request = Map.of("assetId", assetId); - when(cache.referencesForAsset(assetId, null)).thenReturn(List.of(edr, edr)); + when(edrService.query(any())).thenReturn(ServiceResult.success(List.of(edrEntry(assetId), edrEntry(assetId)))); baseRequest() .contentType(MediaType.APPLICATION_JSON) @@ -199,15 +179,7 @@ void requestAsset_shouldReturnError_whenMultipleEdrsByAssetIdFound() { void requestAsset_shouldReturnData_withTransferProcessId() throws IOException { var transferProcessId = "tp"; - var url = "http://localhost:8080/test"; - var request = Map.of("transferProcessId", transferProcessId, "endpointUrl", url); - var edr = EndpointDataReference.Builder.newInstance() - .id(transferProcessId) - .authKey("authKey") - .authCode("authCode") - .contractId("contract-id") - .endpoint(url) - .build(); + var request = Map.of("transferProcessId", transferProcessId); var response = Map.of("response", "ok"); var responseBytes = mapper.writeValueAsBytes(response); @@ -218,7 +190,7 @@ void requestAsset_shouldReturnData_withTransferProcessId() throws IOException { when(datasource.openPartStream()).thenReturn(StreamResult.success(Stream.of(partStream))); when(partStream.openStream()).thenReturn(new ByteArrayInputStream(responseBytes)); - when(cache.resolveReference(transferProcessId)).thenReturn(edr); + when(edrService.resolveByTransferProcess(transferProcessId, AUTO_REFRESH)).thenReturn(ServiceResult.success(edr())); when(pipelineService.transfer(any(), any())) .thenAnswer(a -> CompletableFuture.completedFuture(StreamResult.success(response))); @@ -240,10 +212,9 @@ void requestAsset_shouldReturnData_withTransferProcessId() throws IOException { void requestAsset_shouldReturnError_whenEdrByTransferProcessIdNotFound() { var tp = "tp"; - var url = "http://localhost:8080/test"; - var request = Map.of("transferProcessId", tp, "endpointUrl", url); + var request = Map.of("transferProcessId", tp); - when(cache.resolveReference(tp)).thenReturn(null); + when(edrService.resolveByTransferProcess(tp, AUTO_REFRESH)).thenReturn(ServiceResult.notFound("Not found")); baseRequest() .contentType(MediaType.APPLICATION_JSON) @@ -261,13 +232,7 @@ void requestAsset_shouldReturnData_withDataPlaneUrl() throws IOException { var transferProcessId = "tp"; var url = "http://localhost:8080/test"; var request = Map.of("transferProcessId", transferProcessId, PATH, "/path", QUERY_PARAMS, "test=10&foo=bar"); - var edr = EndpointDataReference.Builder.newInstance() - .id(transferProcessId) - .authKey("authKey") - .authCode("authCode") - .contractId("contract-id") - .endpoint(url) - .build(); + var response = Map.of("response", "ok"); var responseBytes = mapper.writeValueAsBytes(response); @@ -278,7 +243,7 @@ void requestAsset_shouldReturnData_withDataPlaneUrl() throws IOException { when(datasource.openPartStream()).thenReturn(StreamResult.success(Stream.of(partStream))); when(partStream.openStream()).thenReturn(new ByteArrayInputStream(responseBytes)); - when(cache.resolveReference(transferProcessId)).thenReturn(edr); + when(edrService.resolveByTransferProcess(transferProcessId, AUTO_REFRESH)).thenReturn(ServiceResult.success(edr(url))); when(pipelineService.transfer(any(), any())) .thenAnswer(a -> CompletableFuture.completedFuture(StreamResult.success(response))); @@ -301,7 +266,7 @@ void requestAsset_shouldReturnData_withDataPlaneUrl() throws IOException { var flowRequest = captor.getValue(); - assertThat(flowRequest.getSourceDataAddress().getStringProperty(BASE_URL)).isEqualTo(edr.getEndpoint()); + assertThat(flowRequest.getSourceDataAddress().getStringProperty("baseUrl")).isEqualTo(url); assertThat(flowRequest.getProperties().get(QUERY_PARAMS)).isEqualTo(request.get(QUERY_PARAMS)); assertThat(flowRequest.getProperties().get(PATH)).isEqualTo(request.get(PATH)); @@ -310,7 +275,7 @@ void requestAsset_shouldReturnData_withDataPlaneUrl() throws IOException { @Override protected Object controller() { - return new ConsumerAssetRequestController(cache, pipelineService, Executors.newSingleThreadExecutor(), mock(Monitor.class)); + return new ConsumerAssetRequestController(edrService, pipelineService, Executors.newSingleThreadExecutor(), mock(Monitor.class)); } @Override @@ -318,6 +283,29 @@ protected Object additionalResource() { return new ClientErrorExceptionMapper(); } + private DataAddress edr() { + return edr(null); + } + + private DataAddress edr(String baseUrl) { + return DataAddress.Builder.newInstance().type("test").property(BASE_URL, baseUrl).build(); + } + + + private EndpointDataReferenceEntry edrEntry(String assetId) { + return edrEntry(assetId, UUID.randomUUID().toString()); + } + + private EndpointDataReferenceEntry edrEntry(String assetId, String transferProcessId) { + return EndpointDataReferenceEntry.Builder.newInstance() + .assetId(assetId) + .transferProcessId(transferProcessId) + .contractNegotiationId(UUID.randomUUID().toString()) + .agreementId(UUID.randomUUID().toString()) + .providerId(UUID.randomUUID().toString()) + .build(); + } + private RequestSpecification baseRequest() { return given() .baseUri("http://localhost:" + port) diff --git a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImpl.java b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImpl.java index 3a81c74cd..b52317258 100644 --- a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImpl.java +++ b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImpl.java @@ -157,7 +157,7 @@ public Result refreshToken(String refreshToken, String authentica // 2. extract access token and validate it var accessToken = authTokenRes.getContent().getStringClaim("token"); - var accessTokenDataResult = tokenValidationService.validate(accessToken, publicKeyResolver, new RefreshTokenValidationRule(vault, refreshToken, objectMapper)) + var accessTokenDataResult = tokenValidationService.validate(accessToken, localPublicKeyService, new RefreshTokenValidationRule(vault, refreshToken, objectMapper)) .map(accessTokenClaims -> accessTokenDataStore.getById(accessTokenClaims.getStringClaim(JwtRegisteredClaimNames.JWT_ID))); if (accessTokenDataResult.failed()) { diff --git a/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/EdrCacheApi.java b/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/EdrCacheApi.java index 994f7709e..19ee52186 100644 --- a/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/EdrCacheApi.java +++ b/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/EdrCacheApi.java @@ -32,9 +32,9 @@ import jakarta.json.JsonObject; import org.eclipse.edc.api.model.ApiCoreSchema; import org.eclipse.edc.connector.api.management.configuration.ManagementApiSchema; +import org.eclipse.edc.edr.spi.types.EndpointDataReferenceEntry; import org.eclipse.edc.web.spi.ApiErrorDetail; import org.eclipse.tractusx.edc.api.edr.v2.schema.EdrSchema; -import org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntry; import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.ID; import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.TYPE; diff --git a/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/EdrCacheApiController.java b/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/EdrCacheApiController.java index 76c98c946..17df78c59 100644 --- a/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/EdrCacheApiController.java +++ b/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/EdrCacheApiController.java @@ -31,54 +31,65 @@ import jakarta.ws.rs.QueryParam; import jakarta.ws.rs.core.MediaType; import org.eclipse.edc.api.model.IdResponse; +import org.eclipse.edc.connector.contract.spi.types.negotiation.ContractRequest; +import org.eclipse.edc.connector.spi.contractnegotiation.ContractNegotiationService; import org.eclipse.edc.edr.spi.store.EndpointDataReferenceStore; +import org.eclipse.edc.edr.spi.types.EndpointDataReferenceEntry; import org.eclipse.edc.spi.EdcException; import org.eclipse.edc.spi.monitor.Monitor; import org.eclipse.edc.spi.query.QuerySpec; import org.eclipse.edc.spi.result.Result; import org.eclipse.edc.spi.result.ServiceResult; -import org.eclipse.edc.spi.types.domain.DataAddress; +import org.eclipse.edc.spi.types.domain.callback.CallbackAddress; import org.eclipse.edc.transform.spi.TypeTransformerRegistry; import org.eclipse.edc.validator.spi.JsonObjectValidatorRegistry; import org.eclipse.edc.web.spi.exception.InvalidRequestException; import org.eclipse.edc.web.spi.exception.ValidationFailureException; import org.eclipse.tractusx.edc.api.edr.v2.dto.NegotiateEdrRequestDto; import org.eclipse.tractusx.edc.edr.spi.service.EdrService; -import org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntry; import org.eclipse.tractusx.edc.edr.spi.types.NegotiateEdrRequest; -import org.eclipse.tractusx.edc.spi.tokenrefresh.common.TokenRefreshHandler; -import java.time.Instant; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; import static jakarta.json.stream.JsonCollectors.toJsonArray; import static org.eclipse.edc.spi.query.QuerySpec.EDC_QUERY_SPEC_TYPE; -import static org.eclipse.edc.spi.result.ServiceResult.success; import static org.eclipse.edc.web.spi.exception.ServiceResultHandler.exceptionMapper; -import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.EDR_PROPERTY_EXPIRES_IN; +import static org.eclipse.tractusx.edc.edr.spi.types.RefreshMode.AUTO_REFRESH; +import static org.eclipse.tractusx.edc.edr.spi.types.RefreshMode.FORCE_REFRESH; +import static org.eclipse.tractusx.edc.edr.spi.types.RefreshMode.NO_REFRESH; @Consumes({ MediaType.APPLICATION_JSON }) @Produces({ MediaType.APPLICATION_JSON }) @Path("/v2/edrs") public class EdrCacheApiController implements EdrCacheApi { + public static final String LOCAL_ADAPTER_URI = "local://adapter"; + public static final Set LOCAL_EVENTS = Set.of("contract.negotiation", "transfer.process"); + public static final CallbackAddress LOCAL_CALLBACK = CallbackAddress.Builder.newInstance() + .transactional(true) + .uri(LOCAL_ADAPTER_URI) + .events(LOCAL_EVENTS) + .build(); private final EndpointDataReferenceStore edrStore; private final TypeTransformerRegistry transformerRegistry; private final JsonObjectValidatorRegistry validator; private final Monitor monitor; private final EdrService edrService; - private final TokenRefreshHandler tokenRefreshHandler; + + private final ContractNegotiationService contractNegotiationService; public EdrCacheApiController(EndpointDataReferenceStore edrStore, TypeTransformerRegistry transformerRegistry, JsonObjectValidatorRegistry validator, Monitor monitor, - EdrService edrService, - TokenRefreshHandler tokenRefreshHandler) { + EdrService edrService, ContractNegotiationService contractNegotiationService) { this.edrStore = edrStore; this.transformerRegistry = transformerRegistry; this.validator = validator; this.monitor = monitor; this.edrService = edrService; - this.tokenRefreshHandler = tokenRefreshHandler; + this.contractNegotiationService = contractNegotiationService; } @POST @@ -90,7 +101,7 @@ public JsonObject initiateEdrNegotiation(JsonObject requestObject) { .compose(dto -> transformerRegistry.transform(dto, NegotiateEdrRequest.class)) .orElseThrow(InvalidRequestException::new); - var contractNegotiation = edrService.initiateEdrNegotiation(edrNegotiationRequest).orElseThrow(exceptionMapper(NegotiateEdrRequest.class)); + var contractNegotiation = contractNegotiationService.initiateNegotiation(createContractRequest(edrNegotiationRequest)); var idResponse = IdResponse.Builder.newInstance() .id(contractNegotiation.getId()) @@ -129,10 +140,8 @@ public JsonArray requestEdrEntries(JsonObject querySpecJson) { @Path("{transferProcessId}/dataaddress") @Override public JsonObject getEdrEntryDataAddress(@PathParam("transferProcessId") String transferProcessId, @QueryParam("auto_refresh") boolean autoRefresh) { - - var dataAddress = edrStore.resolveByTransferProcess(transferProcessId) - .flatMap(ServiceResult::from) - .compose(edr -> autoRefresh ? refreshAndUpdateToken(edr, transferProcessId) : success(edr)) + var mode = autoRefresh ? AUTO_REFRESH : NO_REFRESH; + var dataAddress = edrService.resolveByTransferProcess(transferProcessId, mode) .orElseThrow(exceptionMapper(EndpointDataReferenceEntry.class, transferProcessId)); return transformerRegistry.transform(dataAddress, JsonObject.class) @@ -154,41 +163,21 @@ public void removeEdrEntry(@PathParam("transferProcessId") String transferProces @Path("{transferProcessId}/refresh") @Override public JsonObject refreshEdr(@PathParam("transferProcessId") String transferProcessId) { - var updatedEdr = tokenRefreshHandler.refreshToken(transferProcessId) - .orElseThrow(exceptionMapper(DataAddress.class, transferProcessId)); + var updatedEdr = edrService.resolveByTransferProcess(transferProcessId, FORCE_REFRESH) + .orElseThrow(exceptionMapper(EndpointDataReferenceEntry.class, transferProcessId)); return transformerRegistry.transform(updatedEdr, JsonObject.class) .orElseThrow(f -> new EdcException(f.getFailureDetail())); } - // todo: move this method into a service once the "old" EDR api,service,etc. is removed - private ServiceResult refreshAndUpdateToken(DataAddress edr, String id) { - - var edrEntry = edrStore.findById(id); - if (edrEntry == null) { - return ServiceResult.notFound("An EndpointDataReferenceEntry with ID '%s' does not exist".formatted(id)); - } - - if (isExpired(edr, edrEntry)) { - monitor.debug("Token expired, need to refresh."); - return tokenRefreshHandler.refreshToken(id, edr); - } - return ServiceResult.success(edr); - } - - // todo: move this method into a service once the "old" EDR api,service,etc. is removed - private boolean isExpired(DataAddress edr, org.eclipse.edc.edr.spi.types.EndpointDataReferenceEntry metadata) { - var expiresInString = edr.getStringProperty(EDR_PROPERTY_EXPIRES_IN); - if (expiresInString == null) { - return false; - } - - var expiresIn = Long.parseLong(expiresInString); - // createdAt is in millis, expires-in is in seconds - var expiresAt = metadata.getCreatedAt() / 1000L + expiresIn; - var expiresAtInstant = Instant.ofEpochSecond(expiresAt); + private ContractRequest createContractRequest(NegotiateEdrRequest request) { + var callbacks = Stream.concat(request.getCallbackAddresses().stream(), Stream.of(LOCAL_CALLBACK)).collect(Collectors.toList()); - return expiresAtInstant.isBefore(Instant.now()); + return ContractRequest.Builder.newInstance() + .counterPartyAddress(request.getConnectorAddress()) + .contractOffer(request.getOffer()) + .protocol(request.getProtocol()) + .callbackAddresses(callbacks).build(); } } diff --git a/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/EdrCacheApiExtension.java b/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/EdrCacheApiExtension.java index 6f5a428c6..c9b482e58 100644 --- a/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/EdrCacheApiExtension.java +++ b/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/EdrCacheApiExtension.java @@ -21,6 +21,7 @@ import jakarta.json.Json; import org.eclipse.edc.connector.api.management.configuration.ManagementApiConfiguration; +import org.eclipse.edc.connector.spi.contractnegotiation.ContractNegotiationService; import org.eclipse.edc.edr.spi.store.EndpointDataReferenceStore; import org.eclipse.edc.jsonld.spi.JsonLd; import org.eclipse.edc.runtime.metamodel.annotation.Inject; @@ -31,13 +32,11 @@ import org.eclipse.edc.validator.spi.JsonObjectValidatorRegistry; import org.eclipse.edc.web.spi.WebService; import org.eclipse.tractusx.edc.api.edr.v2.dto.NegotiateEdrRequestDto; -import org.eclipse.tractusx.edc.api.edr.v2.transform.EndpointDataReferenceToDataAddressTransformer; import org.eclipse.tractusx.edc.api.edr.v2.transform.JsonObjectFromEndpointDataReferenceEntryTransformer; import org.eclipse.tractusx.edc.api.edr.v2.transform.JsonObjectToNegotiateEdrRequestDtoTransformer; import org.eclipse.tractusx.edc.api.edr.v2.transform.NegotiateEdrRequestDtoToNegotiatedEdrRequestTransformer; import org.eclipse.tractusx.edc.api.edr.v2.validation.NegotiateEdrRequestDtoValidator; import org.eclipse.tractusx.edc.edr.spi.service.EdrService; -import org.eclipse.tractusx.edc.spi.tokenrefresh.common.TokenRefreshHandler; import java.util.Map; @@ -63,12 +62,13 @@ public class EdrCacheApiExtension implements ServiceExtension { @Inject private JsonObjectValidatorRegistry validatorRegistry; + @Inject + private ContractNegotiationService contractNegotiationService; + @Inject private Monitor monitor; @Inject private EndpointDataReferenceStore edrStore; - @Inject - private TokenRefreshHandler tokenRefreshHandler; @Override public void initialize(ServiceExtensionContext context) { @@ -77,8 +77,7 @@ public void initialize(ServiceExtensionContext context) { mgmtApiTransformerRegistry.register(new NegotiateEdrRequestDtoToNegotiatedEdrRequestTransformer()); mgmtApiTransformerRegistry.register(new JsonObjectToNegotiateEdrRequestDtoTransformer()); mgmtApiTransformerRegistry.register(new JsonObjectFromEndpointDataReferenceEntryTransformer(Json.createBuilderFactory(Map.of()))); - mgmtApiTransformerRegistry.register(new EndpointDataReferenceToDataAddressTransformer()); validatorRegistry.register(NegotiateEdrRequestDto.EDR_REQUEST_DTO_TYPE, NegotiateEdrRequestDtoValidator.instance()); - webService.registerResource(apiConfig.getContextAlias(), new EdrCacheApiController(edrStore, mgmtApiTransformerRegistry, validatorRegistry, monitor, edrService, tokenRefreshHandler)); + webService.registerResource(apiConfig.getContextAlias(), new EdrCacheApiController(edrStore, mgmtApiTransformerRegistry, validatorRegistry, monitor, edrService, contractNegotiationService)); } } diff --git a/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/schema/EdrSchema.java b/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/schema/EdrSchema.java index ae337815b..0f022452c 100644 --- a/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/schema/EdrSchema.java +++ b/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/schema/EdrSchema.java @@ -22,8 +22,8 @@ import io.swagger.v3.oas.annotations.media.Schema; import org.eclipse.edc.connector.api.management.configuration.ManagementApiSchema; import org.eclipse.edc.connector.api.management.contractnegotiation.ContractNegotiationApi; +import org.eclipse.edc.edr.spi.types.EndpointDataReferenceEntry; import org.eclipse.tractusx.edc.api.edr.v2.dto.NegotiateEdrRequestDto; -import org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntry; import java.util.List; diff --git a/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/transform/EndpointDataReferenceToDataAddressTransformer.java b/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/transform/EndpointDataReferenceToDataAddressTransformer.java deleted file mode 100644 index bfe73fe19..000000000 --- a/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/transform/EndpointDataReferenceToDataAddressTransformer.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -package org.eclipse.tractusx.edc.api.edr.v2.transform; - -import org.eclipse.edc.spi.types.domain.DataAddress; -import org.eclipse.edc.spi.types.domain.edr.EndpointDataReference; -import org.eclipse.edc.transform.spi.TransformerContext; -import org.eclipse.edc.transform.spi.TypeTransformer; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import static org.eclipse.edc.spi.types.domain.edr.EndpointDataReference.AUTH_CODE; -import static org.eclipse.edc.spi.types.domain.edr.EndpointDataReference.AUTH_KEY; -import static org.eclipse.edc.spi.types.domain.edr.EndpointDataReference.EDR_SIMPLE_TYPE; -import static org.eclipse.edc.spi.types.domain.edr.EndpointDataReference.ENDPOINT; -import static org.eclipse.edc.spi.types.domain.edr.EndpointDataReference.ID; - -public class EndpointDataReferenceToDataAddressTransformer implements TypeTransformer { - @Override - public Class getInputType() { - return EndpointDataReference.class; - } - - @Override - public Class getOutputType() { - return DataAddress.class; - } - - @Override - public @Nullable DataAddress transform(@NotNull EndpointDataReference edr, @NotNull TransformerContext context) { - return DataAddress.Builder.newInstance() - .type(EDR_SIMPLE_TYPE) - .property(ID, edr.getId()) - .property(AUTH_CODE, edr.getAuthCode()) - .property(AUTH_KEY, edr.getAuthKey()) - .property(ENDPOINT, edr.getEndpoint()) - .properties(edr.getProperties()) - .build(); - } -} diff --git a/edc-extensions/edr/edr-api-v2/src/test/java/org/eclipse/tractusx/edc/api/edr/v2/EdrCacheApiControllerTest.java b/edc-extensions/edr/edr-api-v2/src/test/java/org/eclipse/tractusx/edc/api/edr/v2/EdrCacheApiControllerTest.java index bc62d0511..4c7dd8982 100644 --- a/edc-extensions/edr/edr-api-v2/src/test/java/org/eclipse/tractusx/edc/api/edr/v2/EdrCacheApiControllerTest.java +++ b/edc-extensions/edr/edr-api-v2/src/test/java/org/eclipse/tractusx/edc/api/edr/v2/EdrCacheApiControllerTest.java @@ -20,21 +20,26 @@ package org.eclipse.tractusx.edc.api.edr.v2; import io.restassured.specification.RequestSpecification; +import jakarta.json.Json; import jakarta.json.JsonObject; import jakarta.json.JsonObjectBuilder; +import org.eclipse.edc.api.model.IdResponse; +import org.eclipse.edc.connector.spi.contractnegotiation.ContractNegotiationService; import org.eclipse.edc.edr.spi.store.EndpointDataReferenceStore; import org.eclipse.edc.edr.spi.types.EndpointDataReferenceEntry; import org.eclipse.edc.junit.annotations.ApiTest; import org.eclipse.edc.spi.query.QuerySpec; import org.eclipse.edc.spi.result.Result; +import org.eclipse.edc.spi.result.ServiceResult; import org.eclipse.edc.spi.result.StoreResult; import org.eclipse.edc.spi.types.domain.DataAddress; import org.eclipse.edc.transform.spi.TypeTransformerRegistry; import org.eclipse.edc.validator.spi.JsonObjectValidatorRegistry; import org.eclipse.edc.validator.spi.ValidationResult; import org.eclipse.edc.web.jersey.testfixtures.RestControllerTestBase; +import org.eclipse.tractusx.edc.api.edr.v2.dto.NegotiateEdrRequestDto; import org.eclipse.tractusx.edc.edr.spi.service.EdrService; -import org.eclipse.tractusx.edc.spi.tokenrefresh.common.TokenRefreshHandler; +import org.eclipse.tractusx.edc.edr.spi.types.NegotiateEdrRequest; import org.junit.jupiter.api.Test; import java.util.List; @@ -42,6 +47,7 @@ import static io.restassured.RestAssured.given; import static io.restassured.http.ContentType.JSON; import static jakarta.json.Json.createObjectBuilder; +import static org.eclipse.edc.api.model.IdResponse.ID_RESPONSE_TYPE; import static org.eclipse.edc.edr.spi.types.EndpointDataReferenceEntry.EDR_ENTRY_AGREEMENT_ID; import static org.eclipse.edc.edr.spi.types.EndpointDataReferenceEntry.EDR_ENTRY_ASSET_ID; import static org.eclipse.edc.edr.spi.types.EndpointDataReferenceEntry.EDR_ENTRY_CONTRACT_NEGOTIATION_ID; @@ -54,6 +60,11 @@ import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.VOCAB; import static org.eclipse.edc.spi.CoreConstants.EDC_NAMESPACE; import static org.eclipse.edc.spi.CoreConstants.EDC_PREFIX; +import static org.eclipse.tractusx.edc.api.edr.v2.TestFunctions.createContractNegotiation; +import static org.eclipse.tractusx.edc.api.edr.v2.TestFunctions.negotiationRequest; +import static org.eclipse.tractusx.edc.api.edr.v2.TestFunctions.openRequest; +import static org.eclipse.tractusx.edc.edr.spi.types.RefreshMode.AUTO_REFRESH; +import static org.eclipse.tractusx.edc.edr.spi.types.RefreshMode.NO_REFRESH; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.is; import static org.mockito.ArgumentMatchers.any; @@ -78,7 +89,49 @@ public class EdrCacheApiControllerTest extends RestControllerTestBase { private final JsonObjectValidatorRegistry validator = mock(); private final EndpointDataReferenceStore edrStore = mock(); private final EdrService edrService = mock(); - private final TokenRefreshHandler tokenRefreshHandler = mock(); + private final ContractNegotiationService contractNegotiationService = mock(); + + + @Test + void initEdrNegotiation_shouldWork_whenValidRequest() { + when(validator.validate(any(), any())).thenReturn(ValidationResult.success()); + + var openRequest = openRequest(); + var contractNegotiation = createContractNegotiation(); + var responseBody = Json.createObjectBuilder().add(TYPE, ID_RESPONSE_TYPE).add(ID, contractNegotiation.getId()).build(); + + when(transformerRegistry.transform(any(JsonObject.class), eq(NegotiateEdrRequestDto.class))).thenReturn(Result.success(NegotiateEdrRequestDto.Builder.newInstance().build())); + when(transformerRegistry.transform(any(), eq(NegotiateEdrRequest.class))).thenReturn(Result.success(openRequest)); + when(contractNegotiationService.initiateNegotiation(any())).thenReturn(contractNegotiation); + when(transformerRegistry.transform(any(IdResponse.class), eq(JsonObject.class))).thenReturn(Result.success(responseBody)); + + var request = negotiationRequest(); + + baseRequest() + .contentType(JSON) + .body(request) + .post("/v2/edrs") + .then() + .statusCode(200) + .body(ID, is(contractNegotiation.getId())); + + } + + @Test + void initEdrNegotiation_shouldReturnBadRequest_whenValidInvalidRequest() { + when(validator.validate(any(), any())).thenReturn(ValidationResult.success()); + + var request = NegotiateEdrRequestDto.Builder.newInstance().build(); + when(transformerRegistry.transform(any(JsonObject.class), eq(NegotiateEdrRequestDto.class))).thenReturn(Result.failure("fail")); + + baseRequest() + .contentType(JSON) + .body(request) + .post("/v2/edrs") + .then() + .statusCode(400); + + } @Test void requestEdrEntries() { @@ -110,8 +163,8 @@ void getEdrEntryDataAddress() { var dataAddressType = "type"; var dataAddress = DataAddress.Builder.newInstance().type(dataAddressType).build(); - when(edrStore.resolveByTransferProcess("transferProcessId")) - .thenReturn(StoreResult.success(dataAddress)); + when(edrService.resolveByTransferProcess("transferProcessId", NO_REFRESH)) + .thenReturn(ServiceResult.success(dataAddress)); when(transformerRegistry.transform(isA(DataAddress.class), eq(JsonObject.class))) .thenReturn(Result.success(createDataAddress(dataAddressType).build())); @@ -125,16 +178,42 @@ void getEdrEntryDataAddress() { .contentType(JSON) .body("'%s'".formatted(DataAddress.EDC_DATA_ADDRESS_TYPE_PROPERTY), equalTo(dataAddressType)); - verify(edrStore).resolveByTransferProcess("transferProcessId"); + verify(edrService).resolveByTransferProcess("transferProcessId", NO_REFRESH); + verify(transformerRegistry).transform(isA(DataAddress.class), eq(JsonObject.class)); + verifyNoMoreInteractions(transformerRegistry); + } + + @Test + void getEdrEntryDataAddress_withAutorefresh() { + + var dataAddressType = "type"; + var dataAddress = DataAddress.Builder.newInstance().type(dataAddressType).build(); + when(edrService.resolveByTransferProcess("transferProcessId", AUTO_REFRESH)) + .thenReturn(ServiceResult.success(dataAddress)); + + when(transformerRegistry.transform(isA(DataAddress.class), eq(JsonObject.class))) + .thenReturn(Result.success(createDataAddress(dataAddressType).build())); + + baseRequest() + .contentType(JSON) + .get("/v2/edrs/transferProcessId/dataaddress?auto_refresh=true") + .then() + .log().ifError() + .statusCode(200) + .contentType(JSON) + .body("'%s'".formatted(DataAddress.EDC_DATA_ADDRESS_TYPE_PROPERTY), equalTo(dataAddressType)); + + verify(edrService).resolveByTransferProcess("transferProcessId", AUTO_REFRESH); verify(transformerRegistry).transform(isA(DataAddress.class), eq(JsonObject.class)); verifyNoMoreInteractions(transformerRegistry); } + @Test void getEdrEntryDataAddress_whenNotFound() { - when(edrStore.resolveByTransferProcess("transferProcessId")) - .thenReturn(StoreResult.notFound("notFound")); + when(edrService.resolveByTransferProcess("transferProcessId", NO_REFRESH)) + .thenReturn(ServiceResult.notFound("notFound")); baseRequest() @@ -145,7 +224,7 @@ void getEdrEntryDataAddress_whenNotFound() { .statusCode(404) .contentType(JSON); - verify(edrStore).resolveByTransferProcess("transferProcessId"); + verify(edrService).resolveByTransferProcess("transferProcessId", NO_REFRESH); verifyNoMoreInteractions(transformerRegistry); } @@ -178,7 +257,7 @@ void removeEdrEntry_whenNotFound() { @Override protected Object controller() { - return new EdrCacheApiController(edrStore, transformerRegistry, validator, mock(), edrService, tokenRefreshHandler); + return new EdrCacheApiController(edrStore, transformerRegistry, validator, mock(), edrService, contractNegotiationService); } private JsonObjectBuilder createEdrEntryJson() { diff --git a/edc-extensions/edr/edr-api-v2/src/test/java/org/eclipse/tractusx/edc/api/edr/v2/TestFunctions.java b/edc-extensions/edr/edr-api-v2/src/test/java/org/eclipse/tractusx/edc/api/edr/v2/TestFunctions.java index 9fdaf6f98..96a2e9b27 100644 --- a/edc-extensions/edr/edr-api-v2/src/test/java/org/eclipse/tractusx/edc/api/edr/v2/TestFunctions.java +++ b/edc-extensions/edr/edr-api-v2/src/test/java/org/eclipse/tractusx/edc/api/edr/v2/TestFunctions.java @@ -22,6 +22,7 @@ import jakarta.json.Json; import jakarta.json.JsonObject; import org.eclipse.edc.connector.api.management.contractnegotiation.model.ContractOfferDescription; +import org.eclipse.edc.connector.contract.spi.types.negotiation.ContractNegotiation; import org.eclipse.edc.policy.model.Policy; import org.eclipse.edc.spi.types.domain.offer.ContractOffer; import org.eclipse.tractusx.edc.api.edr.v2.dto.NegotiateEdrRequestDto; @@ -84,4 +85,13 @@ public static NegotiateEdrRequest openRequest() { .policy(Policy.Builder.newInstance().build()).build()) .build(); } + + public static ContractNegotiation createContractNegotiation() { + return ContractNegotiation.Builder.newInstance() + .id("id") + .counterPartyAddress("http://test") + .counterPartyId("provider") + .protocol("protocol") + .build(); + } } diff --git a/edc-extensions/edr/edr-api-v2/src/test/java/org/eclipse/tractusx/edc/api/edr/v2/transform/EndpointDataReferenceToDataAddressTransformerTest.java b/edc-extensions/edr/edr-api-v2/src/test/java/org/eclipse/tractusx/edc/api/edr/v2/transform/EndpointDataReferenceToDataAddressTransformerTest.java deleted file mode 100644 index 4bad43e38..000000000 --- a/edc-extensions/edr/edr-api-v2/src/test/java/org/eclipse/tractusx/edc/api/edr/v2/transform/EndpointDataReferenceToDataAddressTransformerTest.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -package org.eclipse.tractusx.edc.api.edr.v2.transform; - -import org.eclipse.edc.transform.spi.TransformerContext; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.eclipse.edc.spi.types.domain.edr.EndpointDataReference.AUTH_CODE; -import static org.eclipse.edc.spi.types.domain.edr.EndpointDataReference.AUTH_KEY; -import static org.eclipse.edc.spi.types.domain.edr.EndpointDataReference.Builder; -import static org.eclipse.edc.spi.types.domain.edr.EndpointDataReference.EDR_SIMPLE_TYPE; -import static org.eclipse.edc.spi.types.domain.edr.EndpointDataReference.ENDPOINT; -import static org.eclipse.edc.spi.types.domain.edr.EndpointDataReference.ID; -import static org.mockito.Mockito.mock; - -public class EndpointDataReferenceToDataAddressTransformerTest { - - private final TransformerContext context = mock(TransformerContext.class); - private EndpointDataReferenceToDataAddressTransformer transformer; - - @BeforeEach - void setUp() { - transformer = new EndpointDataReferenceToDataAddressTransformer(); - } - - @Test - void transform() { - - var dto = Builder.newInstance() - .id("dataRequestId") - .authCode("authCode") - .authKey("authKey") - .contractId("test-contract-id") - .endpoint("http://endpoint") - .build(); - - var dataAddress = transformer.transform(dto, context); - - assertThat(dataAddress).isNotNull(); - assertThat(dataAddress.getType()).isEqualTo(EDR_SIMPLE_TYPE); - assertThat(dataAddress.getStringProperty(ID)).isEqualTo(dto.getId()); - assertThat(dataAddress.getStringProperty(ENDPOINT)).isEqualTo(dto.getEndpoint()); - assertThat(dataAddress.getStringProperty(AUTH_KEY)).isEqualTo(dto.getAuthKey()); - assertThat(dataAddress.getStringProperty(AUTH_CODE)).isEqualTo(dto.getAuthCode()); - - } -} diff --git a/edc-extensions/edr/edr-api-v2/src/test/java/org/eclipse/tractusx/edc/api/edr/v2/transform/JsonObjectFromEndpointDataReferenceEntryTransformerTest.java b/edc-extensions/edr/edr-api-v2/src/test/java/org/eclipse/tractusx/edc/api/edr/v2/transform/JsonObjectFromEndpointDataReferenceEntryTransformerTest.java index df15e3971..80aceda85 100644 --- a/edc-extensions/edr/edr-api-v2/src/test/java/org/eclipse/tractusx/edc/api/edr/v2/transform/JsonObjectFromEndpointDataReferenceEntryTransformerTest.java +++ b/edc-extensions/edr/edr-api-v2/src/test/java/org/eclipse/tractusx/edc/api/edr/v2/transform/JsonObjectFromEndpointDataReferenceEntryTransformerTest.java @@ -28,11 +28,11 @@ import java.util.Map; import static org.assertj.core.api.Assertions.assertThat; -import static org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntry.EDR_ENTRY_AGREEMENT_ID; -import static org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntry.EDR_ENTRY_ASSET_ID; -import static org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntry.EDR_ENTRY_CONTRACT_NEGOTIATION_ID; -import static org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntry.EDR_ENTRY_PROVIDER_ID; -import static org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntry.EDR_ENTRY_TRANSFER_PROCESS_ID; +import static org.eclipse.edc.edr.spi.types.EndpointDataReferenceEntry.EDR_ENTRY_AGREEMENT_ID; +import static org.eclipse.edc.edr.spi.types.EndpointDataReferenceEntry.EDR_ENTRY_ASSET_ID; +import static org.eclipse.edc.edr.spi.types.EndpointDataReferenceEntry.EDR_ENTRY_CONTRACT_NEGOTIATION_ID; +import static org.eclipse.edc.edr.spi.types.EndpointDataReferenceEntry.EDR_ENTRY_PROVIDER_ID; +import static org.eclipse.edc.edr.spi.types.EndpointDataReferenceEntry.EDR_ENTRY_TRANSFER_PROCESS_ID; import static org.mockito.Mockito.mock; class JsonObjectFromEndpointDataReferenceEntryTransformerTest { diff --git a/edc-extensions/edr/edr-api/README.md b/edc-extensions/edr/edr-api/README.md deleted file mode 100644 index 084715dcc..000000000 --- a/edc-extensions/edr/edr-api/README.md +++ /dev/null @@ -1,20 +0,0 @@ -# Control Plane EDR API - -This module provides extensions to the EDC management API for dealing with EDR tokens. - -The extensions are added to the same context as the management APIs, so no additional configuration is required. - -The base path of the API will be `/edrs` - -This module for now provides three APIs: - -- Initiating an EDR negotiation token -- Fetching the available EDRs -- Fetching the single EDR - -The initiate negotiation EDR leverage the callbacks mechanism introduced in the latest EDC, and it handles -the contract negotiation and the transfer request in one API call. Once the transfer has been completed -the provider will return the EDR that will be stored into the consumer EDR store/cache. Users can interact -with the EDR store/cache for fetching the EDR and then requesting the data, or can use the `proxy` API described [here](../../dataplane-proxy/edc-dataplane-proxy-consumer-api/README.md) - -An overview on how to use the EDR APIs is available [here](../../../docs/samples/edr-api-overview/edr-api-overview.md) diff --git a/edc-extensions/edr/edr-api/build.gradle.kts b/edc-extensions/edr/edr-api/build.gradle.kts deleted file mode 100644 index 3ed761fa7..000000000 --- a/edc-extensions/edr/edr-api/build.gradle.kts +++ /dev/null @@ -1,40 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -plugins { - `java-library` - `maven-publish` - id("io.swagger.core.v3.swagger-gradle-plugin") -} - -dependencies { - implementation(project(":spi:callback-spi")) - implementation(project(":spi:edr-spi")) - implementation(project(":spi:core-spi")) - - implementation(libs.edc.api.management) - implementation(libs.edc.core.validator) - implementation(libs.jakarta.rsApi) - - testImplementation(testFixtures(libs.edc.core.jersey)) - testImplementation(libs.restAssured) - testImplementation(libs.edc.junit) - testImplementation(libs.edc.lib.jersey.providers) - testImplementation(libs.edc.core.transform) -} diff --git a/edc-extensions/edr/edr-api/src/main/java/org/eclipse/tractusx/edc/api/edr/EdrApi.java b/edc-extensions/edr/edr-api/src/main/java/org/eclipse/tractusx/edc/api/edr/EdrApi.java deleted file mode 100644 index 3042ab67d..000000000 --- a/edc-extensions/edr/edr-api/src/main/java/org/eclipse/tractusx/edc/api/edr/EdrApi.java +++ /dev/null @@ -1,81 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.api.edr; - -import io.swagger.v3.oas.annotations.OpenAPIDefinition; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.media.ArraySchema; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.Schema; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.json.JsonArray; -import jakarta.json.JsonObject; -import org.eclipse.edc.api.model.ApiCoreSchema; -import org.eclipse.edc.connector.api.management.configuration.ManagementApiSchema; -import org.eclipse.edc.web.spi.ApiErrorDetail; -import org.eclipse.tractusx.edc.api.edr.schema.EdrSchema; - -@OpenAPIDefinition -@Tag(name = "Control Plane EDR Api") -public interface EdrApi { - - @Operation(description = "Initiates an EDR negotiation by handling a contract negotiation first and then a transfer process for a given offer and with the given counter part. Please note that successfully invoking this endpoint " + - "only means that the negotiation was initiated.", - responses = { - @ApiResponse(responseCode = "200", description = "The negotiation was successfully initiated.", - content = @Content(schema = @Schema(implementation = ApiCoreSchema.IdResponseSchema.class))), - @ApiResponse(responseCode = "400", description = "Request body was malformed", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = ApiErrorDetail.class)))), - }) - JsonObject initiateEdrNegotiation(@Schema(implementation = EdrSchema.NegotiateEdrRequestSchema.class) JsonObject dto); - - @Operation(description = "Returns all EndpointDataReference entry according to a query", - responses = { - @ApiResponse(responseCode = "200", description = "The ERD cache was retrieved", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = EdrSchema.EndpointDataReferenceEntrySchema.class)))), - @ApiResponse(responseCode = "400", description = "Request was malformed", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = ApiErrorDetail.class)))) } - ) - JsonArray queryEdrs(String assetId, String agreementId, String contractNegotiationId, String providerId); - - @Operation(description = "Gets an EDR with the given transfer process ID", - responses = { - @ApiResponse(responseCode = "200", description = "The EDR cached", - content = @Content(schema = @Schema(implementation = ManagementApiSchema.DataAddressSchema.class))), - @ApiResponse(responseCode = "400", description = "Request was malformed, e.g. id was null", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = ApiErrorDetail.class)))), - @ApiResponse(responseCode = "404", description = "An EDR with the given ID does not exist", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = ApiErrorDetail.class)))) - } - ) - JsonObject getEdr(String transferProcessId); - - @Operation(description = "Delete an EDR with the given transfer process ID", - responses = { - @ApiResponse(responseCode = "200", description = "The EDR cached was deleted successfully"), - @ApiResponse(responseCode = "400", description = "Request was malformed, e.g. id was null", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = ApiErrorDetail.class)))), - @ApiResponse(responseCode = "404", description = "An EDR with the given ID does not exist", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = ApiErrorDetail.class)))) - } - ) - void deleteEdr(String transferProcessId); -} diff --git a/edc-extensions/edr/edr-api/src/main/java/org/eclipse/tractusx/edc/api/edr/EdrApiExtension.java b/edc-extensions/edr/edr-api/src/main/java/org/eclipse/tractusx/edc/api/edr/EdrApiExtension.java deleted file mode 100644 index d4127a778..000000000 --- a/edc-extensions/edr/edr-api/src/main/java/org/eclipse/tractusx/edc/api/edr/EdrApiExtension.java +++ /dev/null @@ -1,77 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.api.edr; - -import org.eclipse.edc.connector.api.management.configuration.ManagementApiConfiguration; -import org.eclipse.edc.connector.api.management.contractnegotiation.transform.JsonObjectToContractOfferTransformer; -import org.eclipse.edc.jsonld.spi.JsonLd; -import org.eclipse.edc.runtime.metamodel.annotation.Inject; -import org.eclipse.edc.spi.monitor.Monitor; -import org.eclipse.edc.spi.system.ServiceExtension; -import org.eclipse.edc.spi.system.ServiceExtensionContext; -import org.eclipse.edc.transform.spi.TypeTransformerRegistry; -import org.eclipse.edc.validator.spi.JsonObjectValidatorRegistry; -import org.eclipse.edc.web.spi.WebService; -import org.eclipse.tractusx.edc.api.edr.transform.EndpointDataReferenceToDataAddressTransformer; -import org.eclipse.tractusx.edc.api.edr.transform.JsonObjectFromEndpointDataReferenceEntryTransformer; -import org.eclipse.tractusx.edc.api.edr.transform.JsonObjectToNegotiateEdrRequestDtoTransformer; -import org.eclipse.tractusx.edc.api.edr.transform.NegotiateEdrRequestDtoToNegotiatedEdrRequestTransformer; -import org.eclipse.tractusx.edc.api.edr.validation.NegotiateEdrRequestDtoValidator; -import org.eclipse.tractusx.edc.edr.spi.service.EdrService; - -import static org.eclipse.tractusx.edc.api.edr.dto.NegotiateEdrRequestDto.EDR_REQUEST_DTO_TYPE; -import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.TX_NAMESPACE; -import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.TX_PREFIX; - -public class EdrApiExtension implements ServiceExtension { - - @Inject - private WebService webService; - @Inject - private ManagementApiConfiguration apiConfig; - - @Inject - private EdrService edrService; - - @Inject - private TypeTransformerRegistry transformerRegistry; - - @Inject - private JsonLd jsonLdService; - - @Inject - private JsonObjectValidatorRegistry validatorRegistry; - - @Inject - private Monitor monitor; - - @Override - public void initialize(ServiceExtensionContext context) { - jsonLdService.registerNamespace(TX_PREFIX, TX_NAMESPACE); - var mgmtApiTransformerRegistry = transformerRegistry.forContext("management-api"); - mgmtApiTransformerRegistry.register(new NegotiateEdrRequestDtoToNegotiatedEdrRequestTransformer()); - mgmtApiTransformerRegistry.register(new JsonObjectToNegotiateEdrRequestDtoTransformer()); - mgmtApiTransformerRegistry.register(new JsonObjectToContractOfferTransformer()); - mgmtApiTransformerRegistry.register(new JsonObjectFromEndpointDataReferenceEntryTransformer()); - mgmtApiTransformerRegistry.register(new EndpointDataReferenceToDataAddressTransformer()); - validatorRegistry.register(EDR_REQUEST_DTO_TYPE, NegotiateEdrRequestDtoValidator.instance(context.getMonitor())); - webService.registerResource(apiConfig.getContextAlias(), new EdrController(edrService, mgmtApiTransformerRegistry, validatorRegistry, monitor)); - } -} diff --git a/edc-extensions/edr/edr-api/src/main/java/org/eclipse/tractusx/edc/api/edr/EdrController.java b/edc-extensions/edr/edr-api/src/main/java/org/eclipse/tractusx/edc/api/edr/EdrController.java deleted file mode 100644 index c3a270393..000000000 --- a/edc-extensions/edr/edr-api/src/main/java/org/eclipse/tractusx/edc/api/edr/EdrController.java +++ /dev/null @@ -1,161 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.api.edr; - -import jakarta.json.JsonArray; -import jakarta.json.JsonObject; -import jakarta.ws.rs.Consumes; -import jakarta.ws.rs.DELETE; -import jakarta.ws.rs.GET; -import jakarta.ws.rs.POST; -import jakarta.ws.rs.Path; -import jakarta.ws.rs.PathParam; -import jakarta.ws.rs.Produces; -import jakarta.ws.rs.QueryParam; -import jakarta.ws.rs.core.MediaType; -import org.eclipse.edc.api.model.IdResponse; -import org.eclipse.edc.spi.EdcException; -import org.eclipse.edc.spi.monitor.Monitor; -import org.eclipse.edc.spi.query.Criterion; -import org.eclipse.edc.spi.query.QuerySpec; -import org.eclipse.edc.spi.result.Result; -import org.eclipse.edc.spi.types.domain.DataAddress; -import org.eclipse.edc.spi.types.domain.edr.EndpointDataReference; -import org.eclipse.edc.transform.spi.TypeTransformerRegistry; -import org.eclipse.edc.validator.spi.JsonObjectValidatorRegistry; -import org.eclipse.edc.web.spi.exception.InvalidRequestException; -import org.eclipse.edc.web.spi.exception.ValidationFailureException; -import org.eclipse.tractusx.edc.api.edr.dto.NegotiateEdrRequestDto; -import org.eclipse.tractusx.edc.edr.spi.service.EdrService; -import org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntry; -import org.eclipse.tractusx.edc.edr.spi.types.NegotiateEdrRequest; - -import static jakarta.json.stream.JsonCollectors.toJsonArray; -import static org.eclipse.edc.web.spi.exception.ServiceResultHandler.exceptionMapper; -import static org.eclipse.tractusx.edc.api.edr.dto.NegotiateEdrRequestDto.EDR_REQUEST_DTO_TYPE; -import static org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntry.AGREEMENT_ID; -import static org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntry.ASSET_ID; -import static org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntry.CONTRACT_NEGOTIATION_ID; -import static org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntry.PROVIDER_ID; - -@Consumes({ MediaType.APPLICATION_JSON }) -@Produces({ MediaType.APPLICATION_JSON }) -@Path("/edrs") -public class EdrController implements EdrApi { - - private final EdrService edrService; - private final TypeTransformerRegistry transformerRegistry; - private final JsonObjectValidatorRegistry validatorRegistry; - private final Monitor monitor; - - public EdrController(EdrService edrService, TypeTransformerRegistry transformerRegistry, - JsonObjectValidatorRegistry validatorRegistry, Monitor monitor) { - this.edrService = edrService; - this.transformerRegistry = transformerRegistry; - this.validatorRegistry = validatorRegistry; - this.monitor = monitor; - } - - @POST - @Override - public JsonObject initiateEdrNegotiation(JsonObject requestObject) { - validatorRegistry.validate(EDR_REQUEST_DTO_TYPE, requestObject).orElseThrow(ValidationFailureException::new); - - var edrNegotiationRequest = transformerRegistry.transform(requestObject, NegotiateEdrRequestDto.class) - .compose(dto -> transformerRegistry.transform(dto, NegotiateEdrRequest.class)) - .orElseThrow(InvalidRequestException::new); - - var contractNegotiation = edrService.initiateEdrNegotiation(edrNegotiationRequest).orElseThrow(exceptionMapper(NegotiateEdrRequest.class)); - - var idResponse = IdResponse.Builder.newInstance() - .id(contractNegotiation.getId()) - .createdAt(contractNegotiation.getCreatedAt()) - .build(); - - return transformerRegistry.transform(idResponse, JsonObject.class) - .orElseThrow(f -> new EdcException("Error creating response body: " + f.getFailureDetail())); - } - - @GET - @Override - public JsonArray queryEdrs(@QueryParam("assetId") String assetId, - @QueryParam("agreementId") String agreementId, - @QueryParam("contractNegotiationId") String contractNegotiationId, - @QueryParam("providerId") String providerId) { - if (assetId == null && agreementId == null && contractNegotiationId == null) { - throw new InvalidRequestException("At least one of this query parameter is required [assetId, agreementId, contractNegotiationId]"); - } - return edrService.findBy(querySpec(assetId, agreementId, contractNegotiationId, providerId)) - .orElseThrow(exceptionMapper(EndpointDataReferenceEntry.class)) - .stream() - .map(edrCached -> transformerRegistry.transform(edrCached, JsonObject.class)) - .peek(this::logIfError) - .filter(Result::succeeded) - .map(Result::getContent) - .collect(toJsonArray()); - } - - @GET - @Path("/{id}") - @Override - public JsonObject getEdr(@PathParam("id") String transferProcessId) { - var edr = edrService.findByTransferProcessId(transferProcessId).orElseThrow(exceptionMapper(EndpointDataReference.class, transferProcessId)); - return transformerRegistry.transform(edr, DataAddress.class) - .compose(dataAddress -> transformerRegistry.transform(dataAddress, JsonObject.class)) - .orElseThrow(f -> new EdcException("Error creating response body: " + f.getFailureDetail())); - } - - @DELETE - @Path("/{id}") - @Override - public void deleteEdr(@PathParam("id") String transferProcessId) { - edrService.deleteByTransferProcessId(transferProcessId).orElseThrow(exceptionMapper(EndpointDataReference.class, transferProcessId)); - } - - private void logIfError(Result result) { - result.onFailure(f -> monitor.warning(f.getFailureDetail())); - } - - private QuerySpec querySpec(String assetId, String agreementId, String contractNegotiationId, String providerId) { - var queryBuilder = QuerySpec.Builder.newInstance(); - if (assetId != null) { - queryBuilder.filter(fieldFilter(ASSET_ID, assetId)); - } - if (agreementId != null) { - queryBuilder.filter(fieldFilter(AGREEMENT_ID, agreementId)); - } - if (contractNegotiationId != null) { - queryBuilder.filter(fieldFilter(CONTRACT_NEGOTIATION_ID, contractNegotiationId)); - } - if (providerId != null) { - queryBuilder.filter(fieldFilter(PROVIDER_ID, providerId)); - } - return queryBuilder.build(); - } - - - private Criterion fieldFilter(String field, String value) { - return Criterion.Builder.newInstance() - .operandLeft(field) - .operator("=") - .operandRight(value) - .build(); - } -} diff --git a/edc-extensions/edr/edr-api/src/main/java/org/eclipse/tractusx/edc/api/edr/dto/NegotiateEdrRequestDto.java b/edc-extensions/edr/edr-api/src/main/java/org/eclipse/tractusx/edc/api/edr/dto/NegotiateEdrRequestDto.java deleted file mode 100644 index 36032948c..000000000 --- a/edc-extensions/edr/edr-api/src/main/java/org/eclipse/tractusx/edc/api/edr/dto/NegotiateEdrRequestDto.java +++ /dev/null @@ -1,139 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.api.edr.dto; - -import org.eclipse.edc.connector.api.management.contractnegotiation.model.ContractOfferDescription; -import org.eclipse.edc.spi.types.domain.callback.CallbackAddress; -import org.eclipse.edc.spi.types.domain.offer.ContractOffer; - -import java.util.ArrayList; -import java.util.List; - -import static org.eclipse.edc.spi.CoreConstants.EDC_NAMESPACE; -import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.TX_NAMESPACE; - -public class NegotiateEdrRequestDto { - - public static final String EDR_REQUEST_SIMPLE_DTO_TYPE = "NegotiateEdrRequestDto"; - public static final String EDR_REQUEST_DTO_TYPE = TX_NAMESPACE + EDR_REQUEST_SIMPLE_DTO_TYPE; - public static final String EDR_REQUEST_DTO_COUNTERPARTY_ADDRESS = EDC_NAMESPACE + "counterPartyAddress"; - public static final String EDR_REQUEST_DTO_PROTOCOL = EDC_NAMESPACE + "protocol"; - public static final String EDR_REQUEST_DTO_COUNTERPARTY_ID = EDC_NAMESPACE + "counterPartyId"; - public static final String EDR_REQUEST_DTO_PROVIDER_ID = EDC_NAMESPACE + "providerId"; - public static final String EDR_REQUEST_DTO_OFFER = EDC_NAMESPACE + "offer"; - public static final String EDR_REQUEST_DTO_POLICY = EDC_NAMESPACE + "policy"; - public static final String EDR_REQUEST_DTO_CALLBACK_ADDRESSES = EDC_NAMESPACE + "callbackAddresses"; - - private String counterPartyAddress; - private String protocol = "ids-multipart"; - private String counterPartyId; - - private String providerId; - - @Deprecated(since = "0.6.1") - private ContractOfferDescription offer; - private ContractOffer contractOffer; - private List callbackAddresses = new ArrayList<>(); - - private NegotiateEdrRequestDto() { - - } - - public String getCounterPartyAddress() { - return counterPartyAddress; - } - - public String getProtocol() { - return protocol; - } - - public String getCounterPartyId() { - return counterPartyId; - } - - public String getProviderId() { - return providerId; - } - - public List getCallbackAddresses() { - return callbackAddresses; - } - - @Deprecated(since = "0.6.1") - public ContractOfferDescription getOffer() { - return offer; - } - - public ContractOffer getContractOffer() { - return contractOffer; - } - - public static final class Builder { - private final NegotiateEdrRequestDto dto; - - private Builder() { - dto = new NegotiateEdrRequestDto(); - } - - public Builder connectorAddress(String connectorAddress) { - dto.counterPartyAddress = connectorAddress; - return this; - } - - public Builder protocol(String protocol) { - dto.protocol = protocol; - return this; - } - - public Builder counterPartyId(String connectorId) { - dto.counterPartyId = connectorId; - return this; - } - - @Deprecated(since = "0.6.1") - public Builder offer(ContractOfferDescription offer) { - dto.offer = offer; - return this; - } - - public Builder contractOffer(ContractOffer contractOffer) { - dto.contractOffer = contractOffer; - return this; - } - - public Builder providerId(String providerId) { - dto.providerId = providerId; - return this; - } - - public Builder callbackAddresses(List callbackAddresses) { - dto.callbackAddresses = callbackAddresses; - return this; - } - - public NegotiateEdrRequestDto build() { - return dto; - } - - public static Builder newInstance() { - return new Builder(); - } - } -} diff --git a/edc-extensions/edr/edr-api/src/main/java/org/eclipse/tractusx/edc/api/edr/schema/EdrSchema.java b/edc-extensions/edr/edr-api/src/main/java/org/eclipse/tractusx/edc/api/edr/schema/EdrSchema.java deleted file mode 100644 index aaf158007..000000000 --- a/edc-extensions/edr/edr-api/src/main/java/org/eclipse/tractusx/edc/api/edr/schema/EdrSchema.java +++ /dev/null @@ -1,137 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.api.edr.schema; - -import io.swagger.v3.oas.annotations.media.Schema; -import org.eclipse.edc.connector.api.management.configuration.ManagementApiSchema; -import org.eclipse.edc.connector.api.management.contractnegotiation.ContractNegotiationApi; -import org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntry; - -import java.util.List; - -import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.TYPE; -import static org.eclipse.tractusx.edc.api.edr.dto.NegotiateEdrRequestDto.EDR_REQUEST_DTO_TYPE; -import static org.eclipse.tractusx.edc.api.edr.schema.EdrSchema.EndpointDataReferenceEntrySchema.ENDPOINT_DATA_REFERENCE_ENTRY_EXAMPLE; -import static org.eclipse.tractusx.edc.api.edr.schema.EdrSchema.NegotiateEdrRequestSchema.NEGOTIATE_EDR_REQUEST_EXAMPLE; - -public class EdrSchema { - - @Schema(name = "NegotiateEdrRequest", example = NEGOTIATE_EDR_REQUEST_EXAMPLE) - public record NegotiateEdrRequestSchema( - @Schema(name = TYPE, example = EDR_REQUEST_DTO_TYPE) - String type, - String protocol, - String connectorAddress, - @Deprecated(since = "0.1.3") - @Schema(deprecated = true, description = "please use providerId instead") - String connectorId, - String providerId, - @Deprecated(since = "0.6.1") - @Schema(deprecated = true, description = "please use policy instead") - ContractNegotiationApi.ContractOfferDescriptionSchema offer, - ManagementApiSchema.PolicySchema policy, - List callbackAddresses) { - - public static final String NEGOTIATE_EDR_REQUEST_EXAMPLE = """ - { - "@context": { "edc": "https://w3id.org/edc/v0.0.1/ns/" }, - "@type": "NegotiateEdrRequestDto", - "counterPartyAddress": "http://provider-address", - "protocol": "dataspace-protocol-http", - "providerId": "provider-id", - "policy": { - "@context": "http://www.w3.org/ns/odrl.jsonld", - "@type": "Set", - "@id": "policy-id", - "target": "asset-id", - "permission": [{ - "action": "display" - }] - }, - "callbackAddresses": [{ - "transactional": false, - "uri": "http://callback/url", - "events": ["contract.negotiation", "transfer.process"] - }] - } - """; - - @Deprecated(since = "0.6.1") - public static final String NEGOTIATE_EDR_REQUEST_DEPRECATED_EXAMPLE = """ - { - "@context": { "edc": "https://w3id.org/edc/v0.0.1/ns/" }, - "@type": "NegotiateEdrRequestDto", - "counterPartyAddress": "http://provider-address", - "protocol": "dataspace-protocol-http", - "providerId": "provider-id", - "offer": { - "offerId": "offer-id", - "assetId": "asset-id", - "policy": { - "@context": "http://www.w3.org/ns/odrl.jsonld", - "@type": "Set", - "@id": "offer-id", - "permission": [{ - "target": "asset-id", - "action": "display" - }] - } - }, - "callbackAddresses": [{ - "transactional": false, - "uri": "http://callback/url", - "events": ["contract.negotiation", "transfer.process"] - }] - } - """; - } - - @Schema(name = "EndpointDataReferenceEntry", example = ENDPOINT_DATA_REFERENCE_ENTRY_EXAMPLE) - public record EndpointDataReferenceEntrySchema( - @Schema(name = TYPE, example = EndpointDataReferenceEntry.SIMPLE_TYPE) - String type, - String agreementId, - String assetId, - String providerId, - String edrState, - Long expirationDate - ) { - public static final String ENDPOINT_DATA_REFERENCE_ENTRY_EXAMPLE = """ - { - "@type": "tx:EndpointDataReferenceEntry", - "agreementId": "MQ==:MQ==:ZTY3MzQ4YWEtNTdmZC00YzA0LTg2ZmQtMGMxNzk0MWM3OTkw", - "transferProcessId": "78a66945-d638-4c0a-be71-b35a0318a410", - "assetId": "1", - "providerId": "BPNL00DATAP00001", - "tx:edrState": "NEGOTIATED", - "tx:expirationDate": 1690811364000, - "@context": { - "dct": "https://purl.org/dc/terms/", - "tx": "https://w3id.org/tractusx/v0.0.1/ns/", - "edc": "https://w3id.org/edc/v0.0.1/ns/", - "dcat": "https://www.w3.org/ns/dcat/", - "odrl": "http://www.w3.org/ns/odrl/2/", - "dspace": "https://w3id.org/dspace/v0.8/" - } - } - """; - } - -} diff --git a/edc-extensions/edr/edr-api/src/main/java/org/eclipse/tractusx/edc/api/edr/transform/EndpointDataReferenceToDataAddressTransformer.java b/edc-extensions/edr/edr-api/src/main/java/org/eclipse/tractusx/edc/api/edr/transform/EndpointDataReferenceToDataAddressTransformer.java deleted file mode 100644 index 369acc9a0..000000000 --- a/edc-extensions/edr/edr-api/src/main/java/org/eclipse/tractusx/edc/api/edr/transform/EndpointDataReferenceToDataAddressTransformer.java +++ /dev/null @@ -1,57 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.api.edr.transform; - -import org.eclipse.edc.spi.types.domain.DataAddress; -import org.eclipse.edc.spi.types.domain.edr.EndpointDataReference; -import org.eclipse.edc.transform.spi.TransformerContext; -import org.eclipse.edc.transform.spi.TypeTransformer; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import static org.eclipse.edc.spi.types.domain.edr.EndpointDataReference.AUTH_CODE; -import static org.eclipse.edc.spi.types.domain.edr.EndpointDataReference.AUTH_KEY; -import static org.eclipse.edc.spi.types.domain.edr.EndpointDataReference.EDR_SIMPLE_TYPE; -import static org.eclipse.edc.spi.types.domain.edr.EndpointDataReference.ENDPOINT; -import static org.eclipse.edc.spi.types.domain.edr.EndpointDataReference.ID; - -public class EndpointDataReferenceToDataAddressTransformer implements TypeTransformer { - @Override - public Class getInputType() { - return EndpointDataReference.class; - } - - @Override - public Class getOutputType() { - return DataAddress.class; - } - - @Override - public @Nullable DataAddress transform(@NotNull EndpointDataReference edr, @NotNull TransformerContext context) { - return DataAddress.Builder.newInstance() - .type(EDR_SIMPLE_TYPE) - .property(ID, edr.getId()) - .property(AUTH_CODE, edr.getAuthCode()) - .property(AUTH_KEY, edr.getAuthKey()) - .property(ENDPOINT, edr.getEndpoint()) - .properties(edr.getProperties()) - .build(); - } -} diff --git a/edc-extensions/edr/edr-api/src/main/java/org/eclipse/tractusx/edc/api/edr/transform/JsonObjectFromEndpointDataReferenceEntryTransformer.java b/edc-extensions/edr/edr-api/src/main/java/org/eclipse/tractusx/edc/api/edr/transform/JsonObjectFromEndpointDataReferenceEntryTransformer.java deleted file mode 100644 index dc67473d8..000000000 --- a/edc-extensions/edr/edr-api/src/main/java/org/eclipse/tractusx/edc/api/edr/transform/JsonObjectFromEndpointDataReferenceEntryTransformer.java +++ /dev/null @@ -1,70 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.api.edr.transform; - -import jakarta.json.Json; -import jakarta.json.JsonObject; -import org.eclipse.edc.jsonld.spi.transformer.AbstractJsonLdTransformer; -import org.eclipse.edc.transform.spi.TransformerContext; -import org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntry; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.TYPE; -import static org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntry.EDR_ENTRY_AGREEMENT_ID; -import static org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntry.EDR_ENTRY_ASSET_ID; -import static org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntry.EDR_ENTRY_CONTRACT_NEGOTIATION_ID; -import static org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntry.EDR_ENTRY_EXPIRATION_DATE; -import static org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntry.EDR_ENTRY_PROVIDER_ID; -import static org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntry.EDR_ENTRY_STATE; -import static org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntry.EDR_ENTRY_TRANSFER_PROCESS_ID; -import static org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntry.EDR_ENTRY_TYPE; - - -public class JsonObjectFromEndpointDataReferenceEntryTransformer extends AbstractJsonLdTransformer { - - public JsonObjectFromEndpointDataReferenceEntryTransformer() { - super(EndpointDataReferenceEntry.class, JsonObject.class); - } - - @Override - public @Nullable JsonObject transform(@NotNull EndpointDataReferenceEntry dto, @NotNull TransformerContext context) { - - var builder = Json.createObjectBuilder() - .add(TYPE, EDR_ENTRY_TYPE) - .add(EDR_ENTRY_AGREEMENT_ID, dto.getAgreementId()) - .add(EDR_ENTRY_TRANSFER_PROCESS_ID, dto.getTransferProcessId()) - .add(EDR_ENTRY_ASSET_ID, dto.getAssetId()) - .add(EDR_ENTRY_STATE, dto.getEdrState()) - .add(EDR_ENTRY_EXPIRATION_DATE, dto.getExpirationTimestamp()); - - if (dto.getProviderId() != null) { - builder.add(EDR_ENTRY_PROVIDER_ID, dto.getProviderId()); - } - - if (dto.getContractNegotiationId() != null) { - builder.add(EDR_ENTRY_CONTRACT_NEGOTIATION_ID, dto.getContractNegotiationId()); - } - - return builder.build(); - } - - -} diff --git a/edc-extensions/edr/edr-api/src/main/java/org/eclipse/tractusx/edc/api/edr/transform/JsonObjectToNegotiateEdrRequestDtoTransformer.java b/edc-extensions/edr/edr-api/src/main/java/org/eclipse/tractusx/edc/api/edr/transform/JsonObjectToNegotiateEdrRequestDtoTransformer.java deleted file mode 100644 index 2ab415eeb..000000000 --- a/edc-extensions/edr/edr-api/src/main/java/org/eclipse/tractusx/edc/api/edr/transform/JsonObjectToNegotiateEdrRequestDtoTransformer.java +++ /dev/null @@ -1,101 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.api.edr.transform; - -import jakarta.json.JsonObject; -import jakarta.json.JsonValue; -import org.eclipse.edc.connector.api.management.contractnegotiation.model.ContractOfferDescription; -import org.eclipse.edc.jsonld.spi.transformer.AbstractJsonLdTransformer; -import org.eclipse.edc.spi.types.domain.callback.CallbackAddress; -import org.eclipse.edc.spi.types.domain.offer.ContractOffer; -import org.eclipse.edc.transform.spi.TransformerContext; -import org.eclipse.tractusx.edc.api.edr.dto.NegotiateEdrRequestDto; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.ArrayList; - -import static org.eclipse.tractusx.edc.api.edr.dto.NegotiateEdrRequestDto.EDR_REQUEST_DTO_CALLBACK_ADDRESSES; -import static org.eclipse.tractusx.edc.api.edr.dto.NegotiateEdrRequestDto.EDR_REQUEST_DTO_COUNTERPARTY_ADDRESS; -import static org.eclipse.tractusx.edc.api.edr.dto.NegotiateEdrRequestDto.EDR_REQUEST_DTO_COUNTERPARTY_ID; -import static org.eclipse.tractusx.edc.api.edr.dto.NegotiateEdrRequestDto.EDR_REQUEST_DTO_OFFER; -import static org.eclipse.tractusx.edc.api.edr.dto.NegotiateEdrRequestDto.EDR_REQUEST_DTO_POLICY; -import static org.eclipse.tractusx.edc.api.edr.dto.NegotiateEdrRequestDto.EDR_REQUEST_DTO_PROTOCOL; -import static org.eclipse.tractusx.edc.api.edr.dto.NegotiateEdrRequestDto.EDR_REQUEST_DTO_PROVIDER_ID; -import static org.eclipse.tractusx.edc.api.edr.dto.NegotiateEdrRequestDto.EDR_REQUEST_DTO_TYPE; - - -public class JsonObjectToNegotiateEdrRequestDtoTransformer extends AbstractJsonLdTransformer { - - public JsonObjectToNegotiateEdrRequestDtoTransformer() { - super(JsonObject.class, NegotiateEdrRequestDto.class); - } - - @Override - public @Nullable NegotiateEdrRequestDto transform(@NotNull JsonObject jsonObject, @NotNull TransformerContext context) { - var builder = NegotiateEdrRequestDto.Builder.newInstance(); - - visitProperties(jsonObject, (k, v) -> setProperties(k, v, builder, context)); - return builder.build(); - } - - private void setProperties(String key, JsonValue value, NegotiateEdrRequestDto.Builder builder, TransformerContext context) { - switch (key) { - case EDR_REQUEST_DTO_COUNTERPARTY_ADDRESS: - transformString(value, builder::connectorAddress, context); - break; - case EDR_REQUEST_DTO_PROTOCOL: - transformString(value, builder::protocol, context); - break; - case EDR_REQUEST_DTO_COUNTERPARTY_ID: - transformString(value, builder::counterPartyId, context); - break; - case EDR_REQUEST_DTO_PROVIDER_ID: - transformString(value, builder::providerId, context); - break; - case EDR_REQUEST_DTO_CALLBACK_ADDRESSES: - var addresses = new ArrayList(); - transformArrayOrObject(value, CallbackAddress.class, addresses::add, context); - builder.callbackAddresses(addresses); - break; - case EDR_REQUEST_DTO_OFFER: - transformArrayOrObject(value, ContractOfferDescription.class, builder::offer, context); - break; - case EDR_REQUEST_DTO_POLICY: - transformArrayOrObject(value, ContractOffer.class, builder::contractOffer, context); - break; - default: - context.problem() - .unexpectedType() - .type(EDR_REQUEST_DTO_TYPE) - .property(key) - .actual(key) - .expected(EDR_REQUEST_DTO_COUNTERPARTY_ADDRESS) - .expected(EDR_REQUEST_DTO_PROTOCOL) - .expected(EDR_REQUEST_DTO_COUNTERPARTY_ID) - .expected(EDR_REQUEST_DTO_PROVIDER_ID) - .expected(EDR_REQUEST_DTO_CALLBACK_ADDRESSES) - .expected(EDR_REQUEST_DTO_OFFER) - .expected(EDR_REQUEST_DTO_POLICY) - .report(); - break; - } - } -} diff --git a/edc-extensions/edr/edr-api/src/main/java/org/eclipse/tractusx/edc/api/edr/transform/NegotiateEdrRequestDtoToNegotiatedEdrRequestTransformer.java b/edc-extensions/edr/edr-api/src/main/java/org/eclipse/tractusx/edc/api/edr/transform/NegotiateEdrRequestDtoToNegotiatedEdrRequestTransformer.java deleted file mode 100644 index fbed87095..000000000 --- a/edc-extensions/edr/edr-api/src/main/java/org/eclipse/tractusx/edc/api/edr/transform/NegotiateEdrRequestDtoToNegotiatedEdrRequestTransformer.java +++ /dev/null @@ -1,65 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.api.edr.transform; - -import org.eclipse.edc.spi.types.domain.offer.ContractOffer; -import org.eclipse.edc.transform.spi.TransformerContext; -import org.eclipse.edc.transform.spi.TypeTransformer; -import org.eclipse.tractusx.edc.api.edr.dto.NegotiateEdrRequestDto; -import org.eclipse.tractusx.edc.edr.spi.types.NegotiateEdrRequest; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -public class NegotiateEdrRequestDtoToNegotiatedEdrRequestTransformer implements TypeTransformer { - - @Override - public Class getInputType() { - return NegotiateEdrRequestDto.class; - } - - @Override - public Class getOutputType() { - return NegotiateEdrRequest.class; - } - - @Override - public @Nullable NegotiateEdrRequest transform(@NotNull NegotiateEdrRequestDto object, @NotNull TransformerContext context) { - ContractOffer contractOffer = null; - - if (object.getContractOffer() != null) { - contractOffer = object.getContractOffer(); - } else if (object.getOffer() != null) { - contractOffer = ContractOffer.Builder.newInstance() - .id(object.getOffer().getOfferId()) - .assetId(object.getOffer().getAssetId()) - .policy(object.getOffer().getPolicy()) - .build(); - } - - return NegotiateEdrRequest.Builder.newInstance() - .connectorId(object.getCounterPartyId()) - .connectorAddress(object.getCounterPartyAddress()) - .protocol(object.getProtocol()) - .offer(contractOffer) - .callbackAddresses(object.getCallbackAddresses()) - .build(); - } - -} diff --git a/edc-extensions/edr/edr-api/src/main/java/org/eclipse/tractusx/edc/api/edr/validation/NegotiateEdrRequestDtoValidator.java b/edc-extensions/edr/edr-api/src/main/java/org/eclipse/tractusx/edc/api/edr/validation/NegotiateEdrRequestDtoValidator.java deleted file mode 100644 index 75fa1960d..000000000 --- a/edc-extensions/edr/edr-api/src/main/java/org/eclipse/tractusx/edc/api/edr/validation/NegotiateEdrRequestDtoValidator.java +++ /dev/null @@ -1,84 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.api.edr.validation; - -import jakarta.json.JsonObject; -import org.eclipse.edc.spi.monitor.Monitor; -import org.eclipse.edc.validator.jsonobject.JsonLdPath; -import org.eclipse.edc.validator.jsonobject.JsonObjectValidator; -import org.eclipse.edc.validator.jsonobject.validators.LogDeprecatedValue; -import org.eclipse.edc.validator.jsonobject.validators.MandatoryObject; -import org.eclipse.edc.validator.jsonobject.validators.MandatoryValue; -import org.eclipse.edc.validator.spi.ValidationResult; -import org.eclipse.edc.validator.spi.Validator; - -import static org.eclipse.edc.connector.api.management.contractnegotiation.model.ContractOfferDescription.ASSET_ID; -import static org.eclipse.edc.connector.api.management.contractnegotiation.model.ContractOfferDescription.OFFER_ID; -import static org.eclipse.tractusx.edc.api.edr.dto.NegotiateEdrRequestDto.EDR_REQUEST_DTO_COUNTERPARTY_ADDRESS; -import static org.eclipse.tractusx.edc.api.edr.dto.NegotiateEdrRequestDto.EDR_REQUEST_DTO_OFFER; -import static org.eclipse.tractusx.edc.api.edr.dto.NegotiateEdrRequestDto.EDR_REQUEST_DTO_POLICY; -import static org.eclipse.tractusx.edc.api.edr.dto.NegotiateEdrRequestDto.EDR_REQUEST_DTO_PROTOCOL; -import static org.eclipse.tractusx.edc.api.edr.dto.NegotiateEdrRequestDto.EDR_REQUEST_DTO_TYPE; - - -public class NegotiateEdrRequestDtoValidator { - - private NegotiateEdrRequestDtoValidator() { - } - - public static Validator instance(Monitor monitor) { - return JsonObjectValidator.newValidator() - .verify(EDR_REQUEST_DTO_COUNTERPARTY_ADDRESS, MandatoryValue::new) - .verify(EDR_REQUEST_DTO_PROTOCOL, MandatoryValue::new) - .verify(EDR_REQUEST_DTO_OFFER, path -> new LogDeprecatedValue(path, EDR_REQUEST_DTO_TYPE, EDR_REQUEST_DTO_POLICY, monitor)) - .verify(MandatoryOfferOrPolicy::new) - .build(); - } - - private record MandatoryOfferOrPolicy(JsonLdPath path) implements Validator { - @Override - public ValidationResult validate(JsonObject input) { - if (input.containsKey(EDR_REQUEST_DTO_OFFER)) { - return new OfferValidator(path.append(EDR_REQUEST_DTO_OFFER)).validate(input); - } - return new EdrPolicyValidator(path).validate(input); - } - } - - private record OfferValidator(JsonLdPath path) implements Validator { - @Override - public ValidationResult validate(JsonObject input) { - return JsonObjectValidator.newValidator() - .verifyObject(EDR_REQUEST_DTO_OFFER, v -> v - .verify(OFFER_ID, MandatoryValue::new) - .verify(ASSET_ID, MandatoryValue::new) - .verify(EDR_REQUEST_DTO_POLICY, MandatoryObject::new) - ).build().validate(input); - } - } - - private record EdrPolicyValidator(JsonLdPath path) implements Validator { - @Override - public ValidationResult validate(JsonObject input) { - return JsonObjectValidator.newValidator() - .verify(EDR_REQUEST_DTO_POLICY, MandatoryObject::new).build().validate(input); - } - } -} diff --git a/edc-extensions/edr/edr-api/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension b/edc-extensions/edr/edr-api/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension deleted file mode 100644 index 3443e55a6..000000000 --- a/edc-extensions/edr/edr-api/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension +++ /dev/null @@ -1,20 +0,0 @@ -################################################################################# -# Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) -# -# See the NOTICE file(s) distributed with this work for additional -# information regarding copyright ownership. -# -# This program and the accompanying materials are made available under the -# terms of the Apache License, Version 2.0 which is available at -# https://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. -# -# SPDX-License-Identifier: Apache-2.0 -################################################################################# - -org.eclipse.tractusx.edc.api.edr.EdrApiExtension diff --git a/edc-extensions/edr/edr-api/src/test/java/org/eclipse/tractusx/edc/api/edr/EdrApiExtensionTest.java b/edc-extensions/edr/edr-api/src/test/java/org/eclipse/tractusx/edc/api/edr/EdrApiExtensionTest.java deleted file mode 100644 index 69dfde64b..000000000 --- a/edc-extensions/edr/edr-api/src/test/java/org/eclipse/tractusx/edc/api/edr/EdrApiExtensionTest.java +++ /dev/null @@ -1,70 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.api.edr; - -import org.eclipse.edc.connector.api.management.configuration.ManagementApiConfiguration; -import org.eclipse.edc.junit.extensions.DependencyInjectionExtension; -import org.eclipse.edc.spi.system.ServiceExtensionContext; -import org.eclipse.edc.spi.system.injection.ObjectFactory; -import org.eclipse.edc.transform.spi.TypeTransformerRegistry; -import org.eclipse.edc.web.spi.WebService; -import org.eclipse.tractusx.edc.api.edr.transform.JsonObjectFromEndpointDataReferenceEntryTransformer; -import org.eclipse.tractusx.edc.api.edr.transform.JsonObjectToNegotiateEdrRequestDtoTransformer; -import org.eclipse.tractusx.edc.api.edr.transform.NegotiateEdrRequestDtoToNegotiatedEdrRequestTransformer; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; - -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.ArgumentMatchers.isA; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -@ExtendWith(DependencyInjectionExtension.class) -public class EdrApiExtensionTest { - - private final TypeTransformerRegistry transformerRegistry = mock(); - private final WebService webService = mock(WebService.class); - private final ManagementApiConfiguration configuration = mock(ManagementApiConfiguration.class); - - @BeforeEach - void setUp(ObjectFactory factory, ServiceExtensionContext context) { - context.registerService(WebService.class, webService); - var rootRegistry = mock(TypeTransformerRegistry.class); - when(rootRegistry.forContext(eq("management-api"))).thenReturn(transformerRegistry); - context.registerService(TypeTransformerRegistry.class, rootRegistry); - context.registerService(ManagementApiConfiguration.class, configuration); - } - - @Test - void initialize_ShouldConfigureTheController(ServiceExtensionContext context, EdrApiExtension extension) { - var alias = "context"; - - when(configuration.getContextAlias()).thenReturn(alias); - extension.initialize(context); - - verify(webService).registerResource(eq(alias), isA(EdrController.class)); - verify(transformerRegistry).register(isA(NegotiateEdrRequestDtoToNegotiatedEdrRequestTransformer.class)); - verify(transformerRegistry).register(isA(JsonObjectToNegotiateEdrRequestDtoTransformer.class)); - verify(transformerRegistry).register(isA(JsonObjectFromEndpointDataReferenceEntryTransformer.class)); - - } -} diff --git a/edc-extensions/edr/edr-api/src/test/java/org/eclipse/tractusx/edc/api/edr/EdrApiTest.java b/edc-extensions/edr/edr-api/src/test/java/org/eclipse/tractusx/edc/api/edr/EdrApiTest.java deleted file mode 100644 index ebbd44f5a..000000000 --- a/edc-extensions/edr/edr-api/src/test/java/org/eclipse/tractusx/edc/api/edr/EdrApiTest.java +++ /dev/null @@ -1,152 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.api.edr; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import jakarta.json.JsonObject; -import org.eclipse.edc.api.transformer.JsonObjectToCallbackAddressTransformer; -import org.eclipse.edc.connector.api.management.contractnegotiation.transform.JsonObjectToContractOfferDescriptionTransformer; -import org.eclipse.edc.connector.api.management.contractnegotiation.transform.JsonObjectToContractOfferTransformer; -import org.eclipse.edc.connector.api.management.contractnegotiation.transform.JsonObjectToContractRequestTransformer; -import org.eclipse.edc.core.transform.TypeTransformerRegistryImpl; -import org.eclipse.edc.core.transform.transformer.odrl.OdrlTransformersFactory; -import org.eclipse.edc.jsonld.JsonLdExtension; -import org.eclipse.edc.jsonld.spi.JsonLd; -import org.eclipse.edc.jsonld.util.JacksonJsonLd; -import org.eclipse.edc.junit.assertions.AbstractResultAssert; -import org.eclipse.edc.spi.agent.ParticipantIdMapper; -import org.eclipse.edc.transform.spi.TypeTransformerRegistry; -import org.eclipse.tractusx.edc.api.edr.dto.NegotiateEdrRequestDto; -import org.eclipse.tractusx.edc.api.edr.transform.JsonObjectToNegotiateEdrRequestDtoTransformer; -import org.eclipse.tractusx.edc.api.edr.validation.NegotiateEdrRequestDtoValidator; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import static org.assertj.core.api.AssertionsForClassTypes.assertThat; -import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.VALUE; -import static org.eclipse.edc.junit.extensions.TestServiceExtensionContext.testServiceExtensionContext; -import static org.eclipse.tractusx.edc.api.edr.schema.EdrSchema.EndpointDataReferenceEntrySchema.ENDPOINT_DATA_REFERENCE_ENTRY_EXAMPLE; -import static org.eclipse.tractusx.edc.api.edr.schema.EdrSchema.NegotiateEdrRequestSchema.NEGOTIATE_EDR_REQUEST_DEPRECATED_EXAMPLE; -import static org.eclipse.tractusx.edc.api.edr.schema.EdrSchema.NegotiateEdrRequestSchema.NEGOTIATE_EDR_REQUEST_EXAMPLE; -import static org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntry.EDR_ENTRY_AGREEMENT_ID; -import static org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntry.EDR_ENTRY_ASSET_ID; -import static org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntry.EDR_ENTRY_EXPIRATION_DATE; -import static org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntry.EDR_ENTRY_PROVIDER_ID; -import static org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntry.EDR_ENTRY_STATE; -import static org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntry.EDR_ENTRY_TRANSFER_PROCESS_ID; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -public class EdrApiTest { - - private final ObjectMapper objectMapper = JacksonJsonLd.createObjectMapper(); - private final JsonLd jsonLd = new JsonLdExtension().createJsonLdService(testServiceExtensionContext()); - - private final TypeTransformerRegistry transformer = new TypeTransformerRegistryImpl(); - - - @BeforeEach - void setUp() { - transformer.register(new JsonObjectToContractRequestTransformer()); - transformer.register(new JsonObjectToContractOfferDescriptionTransformer()); - transformer.register(new JsonObjectToContractOfferTransformer()); - transformer.register(new JsonObjectToCallbackAddressTransformer()); - transformer.register(new JsonObjectToNegotiateEdrRequestDtoTransformer()); - var mapper = mock(ParticipantIdMapper.class); - - when(mapper.fromIri(any())).thenAnswer(a -> a.getArgument(0)); - when(mapper.toIri(any())).thenAnswer(a -> a.getArgument(0)); - OdrlTransformersFactory.jsonObjectToOdrlTransformers(mapper).forEach(transformer::register); - } - - @Test - void edrRequestExample() throws JsonProcessingException { - var validator = NegotiateEdrRequestDtoValidator.instance(testServiceExtensionContext().getMonitor()); - - var jsonObject = objectMapper.readValue(NEGOTIATE_EDR_REQUEST_EXAMPLE, JsonObject.class); - assertThat(jsonObject).isNotNull(); - - var expanded = jsonLd.expand(jsonObject); - AbstractResultAssert.assertThat(expanded).isSucceeded() - .satisfies(exp -> AbstractResultAssert.assertThat(validator.validate(exp)).isSucceeded()) - .extracting(e -> transformer.transform(e, NegotiateEdrRequestDto.class)) - .satisfies(transformResult -> AbstractResultAssert.assertThat(transformResult).isSucceeded() - .satisfies(transformed -> { - assertThat(transformed.getContractOffer()).isNotNull(); - assertThat(transformed.getCallbackAddresses()).asList().hasSize(1); - assertThat(transformed.getProviderId()).isNotBlank(); - })); - } - - @Test - void edrDeprecatedRequestExample() throws JsonProcessingException { - var validator = NegotiateEdrRequestDtoValidator.instance(testServiceExtensionContext().getMonitor()); - - var jsonObject = objectMapper.readValue(NEGOTIATE_EDR_REQUEST_DEPRECATED_EXAMPLE, JsonObject.class); - assertThat(jsonObject).isNotNull(); - - var expanded = jsonLd.expand(jsonObject); - AbstractResultAssert.assertThat(expanded).isSucceeded() - .satisfies(exp -> AbstractResultAssert.assertThat(validator.validate(exp)).isSucceeded()) - .extracting(e -> transformer.transform(e, NegotiateEdrRequestDto.class)) - .satisfies(transformResult -> AbstractResultAssert.assertThat(transformResult).isSucceeded() - .satisfies(transformed -> { - assertThat(transformed.getOffer()).isNotNull(); - assertThat(transformed.getCallbackAddresses()).asList().hasSize(1); - assertThat(transformed.getProviderId()).isNotBlank(); - })); - } - - @Test - void edrEntryExample() throws JsonProcessingException { - - var jsonObject = objectMapper.readValue(ENDPOINT_DATA_REFERENCE_ENTRY_EXAMPLE, JsonObject.class); - assertThat(jsonObject).isNotNull(); - - var expanded = jsonLd.expand(jsonObject); - - AbstractResultAssert.assertThat(expanded).isSucceeded().satisfies(content -> { - - assertThat(first(content, EDR_ENTRY_STATE).getJsonString(VALUE).getString()) - .isEqualTo(jsonObject.getString("tx:edrState")); - - assertThat(first(content, EDR_ENTRY_ASSET_ID).getJsonString(VALUE).getString()) - .isEqualTo(jsonObject.getString("assetId")); - - assertThat(first(content, EDR_ENTRY_AGREEMENT_ID).getJsonString(VALUE).getString()) - .isEqualTo(jsonObject.getString("agreementId")); - - assertThat(first(content, EDR_ENTRY_TRANSFER_PROCESS_ID).getJsonString(VALUE).getString()) - .isEqualTo(jsonObject.getString("transferProcessId")); - - assertThat(first(content, EDR_ENTRY_PROVIDER_ID).getJsonString(VALUE).getString()) - .isEqualTo(jsonObject.getString("providerId")); - - assertThat(first(content, EDR_ENTRY_EXPIRATION_DATE).getJsonNumber(VALUE).longValue()) - .isEqualTo(jsonObject.getJsonNumber("tx:expirationDate").longValue()); - }); - } - - private JsonObject first(JsonObject content, String name) { - return content.getJsonArray(name).getJsonObject(0); - } -} diff --git a/edc-extensions/edr/edr-api/src/test/java/org/eclipse/tractusx/edc/api/edr/EdrControllerTest.java b/edc-extensions/edr/edr-api/src/test/java/org/eclipse/tractusx/edc/api/edr/EdrControllerTest.java deleted file mode 100644 index 90c815e4b..000000000 --- a/edc-extensions/edr/edr-api/src/test/java/org/eclipse/tractusx/edc/api/edr/EdrControllerTest.java +++ /dev/null @@ -1,397 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.api.edr; - -import com.fasterxml.jackson.databind.ObjectMapper; -import io.restassured.specification.RequestSpecification; -import jakarta.json.Json; -import jakarta.json.JsonObject; -import jakarta.ws.rs.core.MediaType; -import org.eclipse.edc.api.model.IdResponse; -import org.eclipse.edc.connector.contract.spi.types.negotiation.ContractNegotiation; -import org.eclipse.edc.jsonld.TitaniumJsonLd; -import org.eclipse.edc.jsonld.spi.JsonLd; -import org.eclipse.edc.jsonld.util.JacksonJsonLd; -import org.eclipse.edc.junit.annotations.ApiTest; -import org.eclipse.edc.spi.query.Criterion; -import org.eclipse.edc.spi.query.QuerySpec; -import org.eclipse.edc.spi.result.Result; -import org.eclipse.edc.spi.result.ServiceResult; -import org.eclipse.edc.spi.types.domain.DataAddress; -import org.eclipse.edc.spi.types.domain.edr.EndpointDataReference; -import org.eclipse.edc.transform.spi.TypeTransformerRegistry; -import org.eclipse.edc.validator.spi.JsonObjectValidatorRegistry; -import org.eclipse.edc.validator.spi.ValidationResult; -import org.eclipse.edc.validator.spi.Violation; -import org.eclipse.edc.web.jersey.jsonld.JerseyJsonLdInterceptor; -import org.eclipse.edc.web.jersey.testfixtures.RestControllerTestBase; -import org.eclipse.tractusx.edc.api.edr.dto.NegotiateEdrRequestDto; -import org.eclipse.tractusx.edc.edr.spi.service.EdrService; -import org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntry; -import org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntryStates; -import org.eclipse.tractusx.edc.edr.spi.types.NegotiateEdrRequest; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import java.util.List; - -import static io.restassured.RestAssured.given; -import static java.lang.String.format; -import static org.eclipse.edc.api.model.IdResponse.ID_RESPONSE_TYPE; -import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.ID; -import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.TYPE; -import static org.eclipse.edc.spi.CoreConstants.EDC_NAMESPACE; -import static org.eclipse.tractusx.edc.api.edr.TestFunctions.negotiationRequest; -import static org.eclipse.tractusx.edc.api.edr.TestFunctions.openRequest; -import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.TX_NAMESPACE; -import static org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntry.AGREEMENT_ID; -import static org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntry.ASSET_ID; -import static org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntry.CONTRACT_NEGOTIATION_ID; -import static org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntry.EDR_ENTRY_AGREEMENT_ID; -import static org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntry.EDR_ENTRY_ASSET_ID; -import static org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntry.EDR_ENTRY_CONTRACT_NEGOTIATION_ID; -import static org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntry.EDR_ENTRY_PROVIDER_ID; -import static org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntry.EDR_ENTRY_STATE; -import static org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntry.EDR_ENTRY_TRANSFER_PROCESS_ID; -import static org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntry.EDR_ENTRY_TYPE; -import static org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntry.PROVIDER_ID; -import static org.hamcrest.Matchers.is; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verifyNoInteractions; -import static org.mockito.Mockito.when; - -@ApiTest -public class EdrControllerTest extends RestControllerTestBase { - - public static final String EDR_PATH = "/edrs"; - private final JsonLd jsonLdService = new TitaniumJsonLd(monitor); - EdrService edrService = mock(EdrService.class); - TypeTransformerRegistry transformerRegistry = mock(); - JsonObjectValidatorRegistry validatorRegistry = mock(); - - @BeforeEach - void setup() { - jsonLdService.registerNamespace("edc", EDC_NAMESPACE); - jsonLdService.registerNamespace("tx", TX_NAMESPACE); - } - - @Test - void initEdrNegotiation_shouldWork_whenValidRequest() { - when(validatorRegistry.validate(any(), any())).thenReturn(ValidationResult.success()); - - var openRequest = openRequest(); - var contractNegotiation = getContractNegotiation(); - var responseBody = Json.createObjectBuilder().add(TYPE, ID_RESPONSE_TYPE).add(ID, contractNegotiation.getId()).build(); - - when(transformerRegistry.transform(any(JsonObject.class), eq(NegotiateEdrRequestDto.class))).thenReturn(Result.success(NegotiateEdrRequestDto.Builder.newInstance().build())); - when(transformerRegistry.transform(any(), eq(NegotiateEdrRequest.class))).thenReturn(Result.success(openRequest)); - when(edrService.initiateEdrNegotiation(openRequest)).thenReturn(ServiceResult.success(contractNegotiation)); - when(transformerRegistry.transform(any(IdResponse.class), eq(JsonObject.class))).thenReturn(Result.success(responseBody)); - - var request = negotiationRequest(); - - baseRequest() - .contentType(MediaType.APPLICATION_JSON) - .body(request) - .post(EDR_PATH) - .then() - .statusCode(200) - .body(ID, is(contractNegotiation.getId())); - - } - - @Test - void initEdrNegotiation_shouldReturnBadRequest_whenValidInvalidRequest() { - when(validatorRegistry.validate(any(), any())).thenReturn(ValidationResult.success()); - - var request = NegotiateEdrRequestDto.Builder.newInstance().build(); - when(transformerRegistry.transform(any(JsonObject.class), eq(NegotiateEdrRequestDto.class))).thenReturn(Result.failure("fail")); - - baseRequest() - .contentType(MediaType.APPLICATION_JSON) - .body(request) - .post(EDR_PATH) - .then() - .statusCode(400); - - } - - @Test - void initEdrNegotiation_shouldReturnBadRequest_whenValidationFails() { - when(validatorRegistry.validate(any(), any())).thenReturn(ValidationResult.failure(Violation.violation("failure", "failure path"))); - var request = negotiationRequest(); - - given() - .port(port) - .body(request) - .contentType(MediaType.APPLICATION_JSON) - .post(EDR_PATH) - .then() - .statusCode(400) - .contentType(MediaType.APPLICATION_JSON); - - verifyNoInteractions(transformerRegistry); - } - - @Test - void initEdrNegotiation_shouldReturnError_whenNotFound() { - var transferProcessId = "id"; - - when(edrService.findByTransferProcessId(transferProcessId)).thenReturn(ServiceResult.notFound("")); - - baseRequest() - .contentType(MediaType.APPLICATION_JSON) - .get(EDR_PATH + "/" + transferProcessId) - .then() - .statusCode(404); - } - - @Test - void getEdr_shouldReturnDataAddress_whenFound() { - var transferProcessId = "id"; - var edr = EndpointDataReference.Builder.newInstance().endpoint("test") - .contractId("test-contract-id") - .id(transferProcessId).build(); - var response = Json.createObjectBuilder() - .add(DataAddress.EDC_DATA_ADDRESS_TYPE_PROPERTY, EndpointDataReference.EDR_SIMPLE_TYPE) - .add(EndpointDataReference.ENDPOINT, edr.getEndpoint()) - .add(EndpointDataReference.ID, edr.getId()) - .build(); - - var dataAddress = DataAddress.Builder.newInstance().type("HttpData").build(); - when(edrService.findByTransferProcessId(transferProcessId)).thenReturn(ServiceResult.success(edr)); - when(transformerRegistry.transform(any(EndpointDataReference.class), eq(DataAddress.class))).thenReturn(Result.success(dataAddress)); - when(transformerRegistry.transform(any(DataAddress.class), eq(JsonObject.class))).thenReturn(Result.success(response)); - - baseRequest() - .contentType(MediaType.APPLICATION_JSON) - .get(EDR_PATH + "/" + transferProcessId) - .then() - .statusCode(200) - .body("'edc:endpoint'", is(edr.getEndpoint())) - .body("'edc:id'", is(edr.getId())) - .body("'edc:type'", is(EndpointDataReference.EDR_SIMPLE_TYPE)); - - } - - @Test - void queryEdrs_shouldReturnCachedEntries_whenAssetIdIsProvided() { - var assetId = "assetId"; - var transferProcessId = "transferProcessId"; - var agreementId = "agreementId"; - var providerId = "providerId"; - - - var entry = EndpointDataReferenceEntry.Builder.newInstance() - .transferProcessId(transferProcessId) - .agreementId(agreementId) - .assetId(assetId) - .providerId(providerId) - .state(EndpointDataReferenceEntryStates.NEGOTIATED.code()) - .build(); - - var response = Json.createObjectBuilder() - .add(TYPE, EDR_ENTRY_TYPE) - .add(EDR_ENTRY_ASSET_ID, entry.getAssetId()) - .add(EDR_ENTRY_TRANSFER_PROCESS_ID, entry.getTransferProcessId()) - .add(EDR_ENTRY_AGREEMENT_ID, entry.getAgreementId()) - .add(EDR_ENTRY_PROVIDER_ID, entry.getProviderId()) - .add(EDR_ENTRY_STATE, entry.getEdrState()) - .build(); - - var filter = QuerySpec.Builder.newInstance().filter(fieldFilter(ASSET_ID, assetId)).build(); - - when(edrService.findBy(eq(filter))).thenReturn(ServiceResult.success(List.of(entry))); - when(transformerRegistry.transform(any(EndpointDataReferenceEntry.class), eq(JsonObject.class))).thenReturn(Result.success(response)); - - baseRequest() - .contentType(MediaType.APPLICATION_JSON) - .get(EDR_PATH + format("?=assetId=%s", assetId)) - .then() - .statusCode(200) - .body("[0].'edc:transferProcessId'", is(entry.getTransferProcessId())) - .body("[0].'edc:agreementId'", is(entry.getAgreementId())) - .body("[0].'edc:assetId'", is(entry.getAssetId())) - .body("[0].'edc:providerId'", is(entry.getProviderId())) - .body("[0].'tx:edrState'", is(entry.getEdrState())); - - } - - @Test - void queryEdrs_shouldReturnCachedEntries_whenAgreementIdIsProvided() { - var assetId = "assetId"; - var transferProcessId = "transferProcessId"; - var agreementId = "agreementId"; - var providerId = "providerId"; - - var entry = EndpointDataReferenceEntry.Builder.newInstance() - .transferProcessId(transferProcessId) - .agreementId(agreementId) - .assetId(assetId) - .providerId(providerId) - .build(); - - - var response = Json.createObjectBuilder() - .add(TYPE, EDR_ENTRY_TYPE) - .add(EDR_ENTRY_ASSET_ID, entry.getAssetId()) - .add(EDR_ENTRY_TRANSFER_PROCESS_ID, entry.getTransferProcessId()) - .add(EDR_ENTRY_AGREEMENT_ID, entry.getAgreementId()) - .add(EDR_ENTRY_PROVIDER_ID, entry.getProviderId()) - .build(); - - var filter = QuerySpec.Builder.newInstance() - .filter(fieldFilter(AGREEMENT_ID, agreementId)) - .filter(fieldFilter(PROVIDER_ID, entry.getProviderId())) - .build(); - - when(edrService.findBy(eq(filter))).thenReturn(ServiceResult.success(List.of(entry))); - when(transformerRegistry.transform(any(EndpointDataReferenceEntry.class), eq(JsonObject.class))).thenReturn(Result.success(response)); - - baseRequest() - .contentType(MediaType.APPLICATION_JSON) - .get(EDR_PATH + format("?=agreementId=%s&providerId=%s", entry.getAgreementId(), entry.getProviderId())) - .then() - .statusCode(200) - .body("[0].'edc:transferProcessId'", is(entry.getTransferProcessId())) - .body("[0].'edc:agreementId'", is(entry.getAgreementId())) - .body("[0].'edc:assetId'", is(entry.getAssetId())) - .body("[0].'edc:providerId'", is(entry.getProviderId())); - } - - @Test - void queryEdrs_shouldReturnCachedEntries_whenContractNegotiationIdIsProvided() { - var assetId = "assetId"; - var transferProcessId = "transferProcessId"; - var agreementId = "agreementId"; - var providerId = "providerId"; - var contractNegotiationId = "contractNegotiationId"; - - var entry = EndpointDataReferenceEntry.Builder.newInstance() - .transferProcessId(transferProcessId) - .agreementId(agreementId) - .assetId(assetId) - .providerId(providerId) - .contractNegotiationId(contractNegotiationId) - .build(); - - - var response = Json.createObjectBuilder() - .add(TYPE, EDR_ENTRY_TYPE) - .add(EDR_ENTRY_ASSET_ID, entry.getAssetId()) - .add(EDR_ENTRY_TRANSFER_PROCESS_ID, entry.getTransferProcessId()) - .add(EDR_ENTRY_AGREEMENT_ID, entry.getAgreementId()) - .add(EDR_ENTRY_CONTRACT_NEGOTIATION_ID, entry.getContractNegotiationId()) - .add(EDR_ENTRY_PROVIDER_ID, entry.getProviderId()) - .build(); - - var filter = QuerySpec.Builder.newInstance() - .filter(fieldFilter(CONTRACT_NEGOTIATION_ID, contractNegotiationId)) - .filter(fieldFilter(PROVIDER_ID, entry.getProviderId())) - .build(); - - when(edrService.findBy(eq(filter))).thenReturn(ServiceResult.success(List.of(entry))); - when(transformerRegistry.transform(any(EndpointDataReferenceEntry.class), eq(JsonObject.class))).thenReturn(Result.success(response)); - - baseRequest() - .contentType(MediaType.APPLICATION_JSON) - .get(EDR_PATH + format("?=contractNegotiationId=%s&providerId=%s", entry.getContractNegotiationId(), entry.getProviderId())) - .then() - .log().all(true) - .statusCode(200) - .body("[0].'edc:transferProcessId'", is(entry.getTransferProcessId())) - .body("[0].'edc:agreementId'", is(entry.getAgreementId())) - .body("[0].'edc:contractNegotiationId'", is(entry.getContractNegotiationId())) - .body("[0].'edc:assetId'", is(entry.getAssetId())) - .body("[0].'edc:providerId'", is(entry.getProviderId())); - } - - @Test - void deleteEdr() { - var transferProcessId = "id"; - - when(edrService.deleteByTransferProcessId(transferProcessId)).thenReturn(ServiceResult.success(null)); - - baseRequest() - .contentType(MediaType.APPLICATION_JSON) - .delete(EDR_PATH + "/" + transferProcessId) - .then() - .statusCode(204); - } - - @Test - void deleteEdr_shouldReturnNotFound_whenNotInCache() { - var transferProcessId = "id"; - - when(edrService.deleteByTransferProcessId(transferProcessId)).thenReturn(ServiceResult.notFound("")); - - baseRequest() - .contentType(MediaType.APPLICATION_JSON) - .delete(EDR_PATH + "/" + transferProcessId) - .then() - .statusCode(404); - } - - @Test - void queryEdrs_shouldFail_whenNoQueryParameter() { - baseRequest() - .contentType(MediaType.APPLICATION_JSON) - .get(EDR_PATH) - .then() - .statusCode(400); - } - - @Override - protected Object controller() { - return new EdrController(edrService, transformerRegistry, validatorRegistry, monitor); - } - - @Override - protected Object additionalResource() { - final ObjectMapper objectMapper = JacksonJsonLd.createObjectMapper(); - return new JerseyJsonLdInterceptor(this.jsonLdService, objectMapper, "edr"); - } - - private RequestSpecification baseRequest() { - return given() - .baseUri("http://localhost:" + port) - .basePath("/") - .when(); - } - - private ContractNegotiation getContractNegotiation() { - return ContractNegotiation.Builder.newInstance() - .id("id") - .counterPartyAddress("http://test") - .counterPartyId("provider") - .protocol("protocol") - .build(); - } - - private Criterion fieldFilter(String field, String value) { - return Criterion.Builder.newInstance() - .operandLeft(field) - .operator("=") - .operandRight(value) - .build(); - } -} diff --git a/edc-extensions/edr/edr-api/src/test/java/org/eclipse/tractusx/edc/api/edr/TestFunctions.java b/edc-extensions/edr/edr-api/src/test/java/org/eclipse/tractusx/edc/api/edr/TestFunctions.java deleted file mode 100644 index 8b05acae7..000000000 --- a/edc-extensions/edr/edr-api/src/test/java/org/eclipse/tractusx/edc/api/edr/TestFunctions.java +++ /dev/null @@ -1,94 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.api.edr; - -import jakarta.json.Json; -import jakarta.json.JsonObject; -import org.eclipse.edc.connector.api.management.contractnegotiation.model.ContractOfferDescription; -import org.eclipse.edc.policy.model.Policy; -import org.eclipse.edc.spi.types.domain.offer.ContractOffer; -import org.eclipse.tractusx.edc.api.edr.dto.NegotiateEdrRequestDto; -import org.eclipse.tractusx.edc.edr.spi.types.NegotiateEdrRequest; - -import java.util.UUID; - -import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.TYPE; -import static org.eclipse.edc.spi.CoreConstants.EDC_NAMESPACE; - -public class TestFunctions { - - public static ContractOfferDescription createOffer(String offerId, String assetId) { - return ContractOfferDescription.Builder.newInstance() - .offerId(offerId) - .assetId(assetId) - .policy(Policy.Builder.newInstance().build()) - .build(); - } - - public static ContractOfferDescription createOffer(Policy policy) { - return ContractOfferDescription.Builder.newInstance() - .offerId(UUID.randomUUID().toString()) - .assetId(UUID.randomUUID().toString()) - .policy(policy) - .build(); - } - - public static ContractOfferDescription createOffer(String offerId) { - return createOffer(offerId, UUID.randomUUID().toString()); - } - - public static ContractOfferDescription createOffer() { - return createOffer(UUID.randomUUID().toString(), UUID.randomUUID().toString()); - } - - public static ContractOffer createContractOffer() { - return ContractOffer.Builder.newInstance() - .id("offerId") - .assetId("assetId") - .policy(Policy.Builder.newInstance().build()).build(); - } - - public static JsonObject negotiationRequest() { - return Json.createObjectBuilder() - .add(TYPE, NegotiateEdrRequestDto.EDR_REQUEST_DTO_TYPE) - .add(EDC_NAMESPACE + "connectorId", "test") - .add(EDC_NAMESPACE + "providerId", "test") - .add(EDC_NAMESPACE + "connectorAddress", "test") - .add(EDC_NAMESPACE + "protocol", "dataspace-protocol-http") - .add(EDC_NAMESPACE + "offer", Json.createObjectBuilder() - .add(EDC_NAMESPACE + "offerId", "offerId") - .add(EDC_NAMESPACE + "assetId", "assetId") - .add(EDC_NAMESPACE + "policy", Json.createObjectBuilder().build()) - ) - .build(); - } - - public static NegotiateEdrRequest openRequest() { - return NegotiateEdrRequest.Builder.newInstance() - .connectorAddress("test") - .connectorId("id") - .protocol("test-protocol") - .offer(ContractOffer.Builder.newInstance() - .id("offerId") - .assetId("assetId") - .policy(Policy.Builder.newInstance().build()).build()) - .build(); - } -} diff --git a/edc-extensions/edr/edr-api/src/test/java/org/eclipse/tractusx/edc/api/edr/transform/EndpointDataReferenceToDataAddressTransformerTest.java b/edc-extensions/edr/edr-api/src/test/java/org/eclipse/tractusx/edc/api/edr/transform/EndpointDataReferenceToDataAddressTransformerTest.java deleted file mode 100644 index d7c0e7db0..000000000 --- a/edc-extensions/edr/edr-api/src/test/java/org/eclipse/tractusx/edc/api/edr/transform/EndpointDataReferenceToDataAddressTransformerTest.java +++ /dev/null @@ -1,66 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.api.edr.transform; - -import org.eclipse.edc.transform.spi.TransformerContext; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.eclipse.edc.spi.types.domain.edr.EndpointDataReference.AUTH_CODE; -import static org.eclipse.edc.spi.types.domain.edr.EndpointDataReference.AUTH_KEY; -import static org.eclipse.edc.spi.types.domain.edr.EndpointDataReference.Builder; -import static org.eclipse.edc.spi.types.domain.edr.EndpointDataReference.EDR_SIMPLE_TYPE; -import static org.eclipse.edc.spi.types.domain.edr.EndpointDataReference.ENDPOINT; -import static org.eclipse.edc.spi.types.domain.edr.EndpointDataReference.ID; -import static org.mockito.Mockito.mock; - -public class EndpointDataReferenceToDataAddressTransformerTest { - - private final TransformerContext context = mock(TransformerContext.class); - private EndpointDataReferenceToDataAddressTransformer transformer; - - @BeforeEach - void setUp() { - transformer = new EndpointDataReferenceToDataAddressTransformer(); - } - - @Test - void transform() { - - var dto = Builder.newInstance() - .id("dataRequestId") - .authCode("authCode") - .authKey("authKey") - .contractId("test-contract-id") - .endpoint("http://endpoint") - .build(); - - var dataAddress = transformer.transform(dto, context); - - assertThat(dataAddress).isNotNull(); - assertThat(dataAddress.getType()).isEqualTo(EDR_SIMPLE_TYPE); - assertThat(dataAddress.getStringProperty(ID)).isEqualTo(dto.getId()); - assertThat(dataAddress.getStringProperty(ENDPOINT)).isEqualTo(dto.getEndpoint()); - assertThat(dataAddress.getStringProperty(AUTH_KEY)).isEqualTo(dto.getAuthKey()); - assertThat(dataAddress.getStringProperty(AUTH_CODE)).isEqualTo(dto.getAuthCode()); - - } -} diff --git a/edc-extensions/edr/edr-api/src/test/java/org/eclipse/tractusx/edc/api/edr/transform/JsonObjectFromEndpointDataReferenceEntryTransformerTest.java b/edc-extensions/edr/edr-api/src/test/java/org/eclipse/tractusx/edc/api/edr/transform/JsonObjectFromEndpointDataReferenceEntryTransformerTest.java deleted file mode 100644 index a0474eb60..000000000 --- a/edc-extensions/edr/edr-api/src/test/java/org/eclipse/tractusx/edc/api/edr/transform/JsonObjectFromEndpointDataReferenceEntryTransformerTest.java +++ /dev/null @@ -1,75 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.api.edr.transform; - -import org.eclipse.edc.transform.spi.TransformerContext; -import org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntry; -import org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntryStates; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import java.time.Instant; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntry.EDR_ENTRY_AGREEMENT_ID; -import static org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntry.EDR_ENTRY_ASSET_ID; -import static org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntry.EDR_ENTRY_CONTRACT_NEGOTIATION_ID; -import static org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntry.EDR_ENTRY_EXPIRATION_DATE; -import static org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntry.EDR_ENTRY_PROVIDER_ID; -import static org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntry.EDR_ENTRY_STATE; -import static org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntry.EDR_ENTRY_TRANSFER_PROCESS_ID; -import static org.mockito.Mockito.mock; - -class JsonObjectFromEndpointDataReferenceEntryTransformerTest { - - private final TransformerContext context = mock(TransformerContext.class); - private JsonObjectFromEndpointDataReferenceEntryTransformer transformer; - - @BeforeEach - void setUp() { - transformer = new JsonObjectFromEndpointDataReferenceEntryTransformer(); - } - - @Test - void transform() { - - var dto = EndpointDataReferenceEntry.Builder.newInstance() - .assetId("id") - .transferProcessId("tpId") - .agreementId("aId") - .providerId("providerId") - .contractNegotiationId("contractNegotiationId") - .state(EndpointDataReferenceEntryStates.NEGOTIATED.code()) - .expirationTimestamp(Instant.now().toEpochMilli()) - .build(); - - var jsonObject = transformer.transform(dto, context); - - assertThat(jsonObject).isNotNull(); - assertThat(jsonObject.getJsonString(EDR_ENTRY_AGREEMENT_ID).getString()).isNotNull().isEqualTo(dto.getAgreementId()); - assertThat(jsonObject.getJsonString(EDR_ENTRY_CONTRACT_NEGOTIATION_ID).getString()).isNotNull().isEqualTo(dto.getContractNegotiationId()); - assertThat(jsonObject.getJsonString(EDR_ENTRY_ASSET_ID).getString()).isNotNull().isEqualTo(dto.getAssetId()); - assertThat(jsonObject.getJsonString(EDR_ENTRY_TRANSFER_PROCESS_ID).getString()).isNotNull().isEqualTo(dto.getTransferProcessId()); - assertThat(jsonObject.getJsonString(EDR_ENTRY_PROVIDER_ID).getString()).isNotNull().isEqualTo(dto.getProviderId()); - assertThat(jsonObject.getJsonString(EDR_ENTRY_STATE).getString()).isNotNull().isEqualTo(dto.getEdrState()); - assertThat(jsonObject.getJsonNumber(EDR_ENTRY_EXPIRATION_DATE).longValue()).isNotNull().isEqualTo(dto.getExpirationTimestamp()); - - } -} diff --git a/edc-extensions/edr/edr-api/src/test/java/org/eclipse/tractusx/edc/api/edr/transform/JsonObjectToNegotiateEdrRequestDtoTransformerTest.java b/edc-extensions/edr/edr-api/src/test/java/org/eclipse/tractusx/edc/api/edr/transform/JsonObjectToNegotiateEdrRequestDtoTransformerTest.java deleted file mode 100644 index 459423c9d..000000000 --- a/edc-extensions/edr/edr-api/src/test/java/org/eclipse/tractusx/edc/api/edr/transform/JsonObjectToNegotiateEdrRequestDtoTransformerTest.java +++ /dev/null @@ -1,208 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.api.edr.transform; - -import jakarta.json.Json; -import jakarta.json.JsonArrayBuilder; -import jakarta.json.JsonObject; -import jakarta.json.JsonValue; -import org.eclipse.edc.connector.api.management.contractnegotiation.model.ContractOfferDescription; -import org.eclipse.edc.jsonld.TitaniumJsonLd; -import org.eclipse.edc.jsonld.spi.JsonLd; -import org.eclipse.edc.policy.model.Policy; -import org.eclipse.edc.spi.monitor.Monitor; -import org.eclipse.edc.spi.types.domain.callback.CallbackAddress; -import org.eclipse.edc.spi.types.domain.offer.ContractOffer; -import org.eclipse.edc.transform.spi.ProblemBuilder; -import org.eclipse.edc.transform.spi.TransformerContext; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import java.util.Set; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.eclipse.edc.connector.api.management.contractnegotiation.model.ContractOfferDescription.ASSET_ID; -import static org.eclipse.edc.connector.api.management.contractnegotiation.model.ContractOfferDescription.OFFER_ID; -import static org.eclipse.edc.connector.api.management.contractnegotiation.model.ContractOfferDescription.POLICY; -import static org.eclipse.edc.connector.contract.spi.types.negotiation.ContractRequest.CALLBACK_ADDRESSES; -import static org.eclipse.edc.connector.contract.spi.types.negotiation.ContractRequest.CONTRACT_REQUEST_TYPE; -import static org.eclipse.edc.connector.contract.spi.types.negotiation.ContractRequest.OFFER; -import static org.eclipse.edc.connector.contract.spi.types.negotiation.ContractRequest.PROTOCOL; -import static org.eclipse.edc.connector.contract.spi.types.negotiation.ContractRequest.PROVIDER_ID; -import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.ID; -import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.TYPE; -import static org.eclipse.edc.jsonld.spi.PropertyAndTypeNames.ODRL_OBLIGATION_ATTRIBUTE; -import static org.eclipse.edc.jsonld.spi.PropertyAndTypeNames.ODRL_PERMISSION_ATTRIBUTE; -import static org.eclipse.edc.jsonld.spi.PropertyAndTypeNames.ODRL_POLICY_TYPE_SET; -import static org.eclipse.edc.jsonld.spi.PropertyAndTypeNames.ODRL_PROHIBITION_ATTRIBUTE; -import static org.eclipse.edc.jsonld.spi.PropertyAndTypeNames.ODRL_TARGET_ATTRIBUTE; -import static org.eclipse.edc.spi.CoreConstants.EDC_NAMESPACE; -import static org.eclipse.edc.spi.types.domain.callback.CallbackAddress.EVENTS; -import static org.eclipse.edc.spi.types.domain.callback.CallbackAddress.IS_TRANSACTIONAL; -import static org.eclipse.edc.spi.types.domain.callback.CallbackAddress.URI; -import static org.eclipse.tractusx.edc.api.edr.dto.NegotiateEdrRequestDto.EDR_REQUEST_DTO_COUNTERPARTY_ADDRESS; -import static org.eclipse.tractusx.edc.api.edr.dto.NegotiateEdrRequestDto.EDR_REQUEST_DTO_COUNTERPARTY_ID; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -class JsonObjectToNegotiateEdrRequestDtoTransformerTest { - - private final JsonLd jsonLd = new TitaniumJsonLd(mock(Monitor.class)); - private final TransformerContext context = mock(TransformerContext.class); - private JsonObjectToNegotiateEdrRequestDtoTransformer transformer; - - @BeforeEach - void setUp() { - transformer = new JsonObjectToNegotiateEdrRequestDtoTransformer(); - } - - @Test - void transform() { - var jsonObject = Json.createObjectBuilder() - .add(TYPE, CONTRACT_REQUEST_TYPE) - .add(EDR_REQUEST_DTO_COUNTERPARTY_ADDRESS, "test-address") - .add(EDR_REQUEST_DTO_COUNTERPARTY_ID, "test-conn-id") - .add(PROTOCOL, "test-protocol") - .add(PROVIDER_ID, "test-provider-id") - .add(CALLBACK_ADDRESSES, createCallbackAddress()) - .add(POLICY, createPolicyJson()) - .build(); - - when(context.transform(any(JsonValue.class), eq(ContractOffer.class))).thenReturn(ContractOffer.Builder.newInstance() - .id("test-offer-id") - .assetId("test-asset-id") - .policy(createPolicyObject()) - .build()); - - when(context.transform(any(JsonObject.class), eq(CallbackAddress.class))).thenReturn(CallbackAddress.Builder.newInstance() - .uri("http://test.local") - .events(Set.of("foo", "bar")) - .transactional(true) - .build()); - when(context.transform(any(CallbackAddress.class), eq(CallbackAddress.class))).thenReturn(CallbackAddress.Builder.newInstance() - .uri("http://test.local") - .events(Set.of("foo", "bar")) - .transactional(true) - .build()); - var dto = transformer.transform(jsonLd.expand(jsonObject).getContent(), context); - - assertThat(dto).isNotNull(); - assertThat(dto.getCallbackAddresses()).isNotEmpty(); - assertThat(dto.getProtocol()).isEqualTo("test-protocol"); - assertThat(dto.getCounterPartyAddress()).isEqualTo("test-address"); - assertThat(dto.getCounterPartyId()).isEqualTo("test-conn-id"); - assertThat(dto.getProviderId()).isEqualTo("test-provider-id"); - assertThat(dto.getContractOffer()).isNotNull(); - - } - - @Test - void transformDeprecatedOffer() { - var jsonObject = Json.createObjectBuilder() - .add(TYPE, CONTRACT_REQUEST_TYPE) - .add(EDR_REQUEST_DTO_COUNTERPARTY_ADDRESS, "test-address") - .add(EDR_REQUEST_DTO_COUNTERPARTY_ID, "test-conn-id") - .add(PROTOCOL, "test-protocol") - .add(PROVIDER_ID, "test-provider-id") - .add(CALLBACK_ADDRESSES, createCallbackAddress()) - .add(OFFER, Json.createObjectBuilder() - .add(OFFER_ID, "test-offer-id") - .add(ASSET_ID, "test-asset") - .add(POLICY, createPolicyJson()) - .build()) - .build(); - - when(context.transform(any(JsonValue.class), eq(ContractOfferDescription.class))).thenReturn(ContractOfferDescription.Builder.newInstance().build()); - - when(context.transform(any(JsonObject.class), eq(CallbackAddress.class))).thenReturn(CallbackAddress.Builder.newInstance() - .uri("http://test.local") - .events(Set.of("foo", "bar")) - .transactional(true) - .build()); - when(context.transform(any(CallbackAddress.class), eq(CallbackAddress.class))).thenReturn(CallbackAddress.Builder.newInstance() - .uri("http://test.local") - .events(Set.of("foo", "bar")) - .transactional(true) - .build()); - var dto = transformer.transform(jsonLd.expand(jsonObject).getContent(), context); - - assertThat(dto).isNotNull(); - assertThat(dto.getCallbackAddresses()).isNotEmpty(); - assertThat(dto.getProtocol()).isEqualTo("test-protocol"); - assertThat(dto.getCounterPartyAddress()).isEqualTo("test-address"); - assertThat(dto.getCounterPartyId()).isEqualTo("test-conn-id"); - assertThat(dto.getProviderId()).isEqualTo("test-provider-id"); - assertThat(dto.getOffer()).isNotNull(); - - } - - @Test - void transform_reportErrors() { - - when(context.problem()).thenReturn(new ProblemBuilder(context)); - - var jsonObject = Json.createObjectBuilder() - .add(TYPE, CONTRACT_REQUEST_TYPE) - .add(EDC_NAMESPACE + "notFound", "test-address") - .build(); - - var dto = transformer.transform(jsonLd.expand(jsonObject).getContent(), context); - - assertThat(dto).isNotNull(); - verify(context, times(1)).reportProblem(anyString()); - } - - private JsonArrayBuilder createCallbackAddress() { - var builder = Json.createArrayBuilder(); - return builder.add(Json.createObjectBuilder() - .add(IS_TRANSACTIONAL, true) - .add(URI, "http://test.local/") - .add(EVENTS, Json.createArrayBuilder().build())); - } - - private JsonObject createPolicyJson() { - var permissionJson = getJsonObject("permission"); - var prohibitionJson = getJsonObject("prohibition"); - var dutyJson = getJsonObject("duty"); - return Json.createObjectBuilder() - .add(TYPE, ODRL_POLICY_TYPE_SET) - .add(ID, "test-offer-id") - .add(ODRL_PERMISSION_ATTRIBUTE, permissionJson) - .add(ODRL_PROHIBITION_ATTRIBUTE, prohibitionJson) - .add(ODRL_OBLIGATION_ATTRIBUTE, dutyJson) - .add(ODRL_TARGET_ATTRIBUTE, "test-asset-id") - .build(); - } - - private Policy createPolicyObject() { - return Policy.Builder.newInstance().build(); - } - - private JsonObject getJsonObject(String type) { - return Json.createObjectBuilder() - .add(TYPE, type) - .build(); - } -} diff --git a/edc-extensions/edr/edr-api/src/test/java/org/eclipse/tractusx/edc/api/edr/transform/NegotiateEdrRequestDtoToNegotiateEdrRequestTransformerTest.java b/edc-extensions/edr/edr-api/src/test/java/org/eclipse/tractusx/edc/api/edr/transform/NegotiateEdrRequestDtoToNegotiateEdrRequestTransformerTest.java deleted file mode 100644 index e271eac72..000000000 --- a/edc-extensions/edr/edr-api/src/test/java/org/eclipse/tractusx/edc/api/edr/transform/NegotiateEdrRequestDtoToNegotiateEdrRequestTransformerTest.java +++ /dev/null @@ -1,125 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.api.edr.transform; - -import org.eclipse.edc.spi.types.domain.callback.CallbackAddress; -import org.eclipse.edc.transform.spi.TransformerContext; -import org.eclipse.tractusx.edc.api.edr.dto.NegotiateEdrRequestDto; -import org.junit.jupiter.api.Test; - -import java.util.List; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.eclipse.tractusx.edc.api.edr.TestFunctions.createContractOffer; -import static org.eclipse.tractusx.edc.api.edr.TestFunctions.createOffer; -import static org.mockito.Mockito.mock; - -public class NegotiateEdrRequestDtoToNegotiateEdrRequestTransformerTest { - - private final NegotiateEdrRequestDtoToNegotiatedEdrRequestTransformer transformer = new NegotiateEdrRequestDtoToNegotiatedEdrRequestTransformer(); - - private final TransformerContext context = mock(TransformerContext.class); - - @Test - void inputOutputType() { - assertThat(transformer.getInputType()).isNotNull(); - assertThat(transformer.getOutputType()).isNotNull(); - } - - @Test - void verify_transform() { - var callback = CallbackAddress.Builder.newInstance() - .uri("local://test") - .build(); - var dto = NegotiateEdrRequestDto.Builder.newInstance() - .counterPartyId("connectorId") - .connectorAddress("address") - .protocol("protocol") - .providerId("test-provider") - .contractOffer(createContractOffer()) - .callbackAddresses(List.of(callback)) - .build(); - - var request = transformer.transform(dto, context); - - assertThat(request).isNotNull(); - assertThat(request.getConnectorId()).isEqualTo("connectorId"); - assertThat(request.getConnectorAddress()).isEqualTo("address"); - assertThat(request.getProtocol()).isEqualTo("protocol"); - assertThat(request.getOffer().getId()).isEqualTo("offerId"); - assertThat(request.getOffer().getPolicy()).isNotNull(); - assertThat(request.getCallbackAddresses()).hasSize(1); - } - - @Test - void verify_transformDeprecatedOffer() { - var callback = CallbackAddress.Builder.newInstance() - .uri("local://test") - .build(); - var dto = NegotiateEdrRequestDto.Builder.newInstance() - .counterPartyId("connectorId") - .connectorAddress("address") - .protocol("protocol") - .providerId("test-provider") - .offer(createOffer("offerId", "assetId")) - .callbackAddresses(List.of(callback)) - .build(); - - var request = transformer.transform(dto, context); - - assertThat(request).isNotNull(); - assertThat(request.getConnectorId()).isEqualTo("connectorId"); - assertThat(request.getConnectorAddress()).isEqualTo("address"); - assertThat(request.getProtocol()).isEqualTo("protocol"); - assertThat(request.getOffer().getId()).isEqualTo("offerId"); - assertThat(request.getOffer().getPolicy()).isNotNull(); - assertThat(request.getCallbackAddresses()).hasSize(1); - } - - @Test - void verify_transform_withNoProviderId() { - var dto = NegotiateEdrRequestDto.Builder.newInstance() - .counterPartyId("connectorId") - .connectorAddress("address") - .protocol("protocol") - // do not set provider ID - .contractOffer(createContractOffer()) - .build(); - - var request = transformer.transform(dto, context); - - assertThat(request).isNotNull(); - } - - @Test - void verify_transform_withNoConsumerId() { - var dto = NegotiateEdrRequestDto.Builder.newInstance() - .counterPartyId("connectorId") - .connectorAddress("address") - .protocol("protocol") - // do not set consumer ID - .providerId("urn:connector:test-provider") - .contractOffer(createContractOffer()) - .build(); - - var request = transformer.transform(dto, context); - assertThat(request).isNotNull(); - } -} diff --git a/edc-extensions/edr/edr-api/src/test/java/org/eclipse/tractusx/edc/api/edr/validation/NegotiateEdrRequestDtoValidatorTest.java b/edc-extensions/edr/edr-api/src/test/java/org/eclipse/tractusx/edc/api/edr/validation/NegotiateEdrRequestDtoValidatorTest.java deleted file mode 100644 index c6f82df80..000000000 --- a/edc-extensions/edr/edr-api/src/test/java/org/eclipse/tractusx/edc/api/edr/validation/NegotiateEdrRequestDtoValidatorTest.java +++ /dev/null @@ -1,117 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.api.edr.validation; - -import jakarta.json.Json; -import jakarta.json.JsonArrayBuilder; -import jakarta.json.JsonObject; -import org.eclipse.edc.spi.monitor.Monitor; -import org.eclipse.edc.validator.spi.ValidationFailure; -import org.eclipse.edc.validator.spi.Validator; -import org.eclipse.edc.validator.spi.Violation; -import org.junit.jupiter.api.Test; - -import static jakarta.json.Json.createArrayBuilder; -import static jakarta.json.Json.createObjectBuilder; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.InstanceOfAssertFactories.list; -import static org.eclipse.edc.connector.api.management.contractnegotiation.model.ContractOfferDescription.ASSET_ID; -import static org.eclipse.edc.connector.api.management.contractnegotiation.model.ContractOfferDescription.OFFER_ID; -import static org.eclipse.edc.connector.api.management.contractnegotiation.model.ContractOfferDescription.POLICY; -import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.VALUE; -import static org.eclipse.edc.junit.assertions.AbstractResultAssert.assertThat; -import static org.eclipse.tractusx.edc.api.edr.dto.NegotiateEdrRequestDto.EDR_REQUEST_DTO_COUNTERPARTY_ADDRESS; -import static org.eclipse.tractusx.edc.api.edr.dto.NegotiateEdrRequestDto.EDR_REQUEST_DTO_OFFER; -import static org.eclipse.tractusx.edc.api.edr.dto.NegotiateEdrRequestDto.EDR_REQUEST_DTO_POLICY; -import static org.eclipse.tractusx.edc.api.edr.dto.NegotiateEdrRequestDto.EDR_REQUEST_DTO_PROTOCOL; -import static org.eclipse.tractusx.edc.api.edr.dto.NegotiateEdrRequestDto.EDR_REQUEST_DTO_PROVIDER_ID; -import static org.mockito.Mockito.mock; - -public class NegotiateEdrRequestDtoValidatorTest { - - private final Validator validator = NegotiateEdrRequestDtoValidator.instance(mock(Monitor.class)); - - @Test - void shouldSucceed_whenObjectIsValid() { - var input = Json.createObjectBuilder() - .add(EDR_REQUEST_DTO_COUNTERPARTY_ADDRESS, value("http://connector-address")) - .add(EDR_REQUEST_DTO_PROTOCOL, value("protocol")) - .add(EDR_REQUEST_DTO_PROVIDER_ID, value("connector-id")) - .add(EDR_REQUEST_DTO_POLICY, createArrayBuilder().add(createObjectBuilder())) - .build(); - - var result = validator.validate(input); - - assertThat(result).isSucceeded(); - } - - @Test - void shouldSucceed_whenDeprecatedOfferIsUsed() { - var input = Json.createObjectBuilder() - .add(EDR_REQUEST_DTO_COUNTERPARTY_ADDRESS, value("http://connector-address")) - .add(EDR_REQUEST_DTO_PROTOCOL, value("protocol")) - .add(EDR_REQUEST_DTO_PROVIDER_ID, value("connector-id")) - .add(EDR_REQUEST_DTO_OFFER, createArrayBuilder().add(createObjectBuilder() - .add(OFFER_ID, value("offerId")) - .add(ASSET_ID, value("offerId")) - .add(EDR_REQUEST_DTO_POLICY, createArrayBuilder().add(createObjectBuilder())) - )) - .build(); - - var result = validator.validate(input); - - assertThat(result).isSucceeded(); - } - - @Test - void shouldFail_whenMandatoryPropertiesAreMissing() { - var input = Json.createObjectBuilder().build(); - - var result = validator.validate(input); - - assertThat(result).isFailed().extracting(ValidationFailure::getViolations).asInstanceOf(list(Violation.class)) - .isNotEmpty() - .anySatisfy(violation -> assertThat(violation.path()).isEqualTo(EDR_REQUEST_DTO_COUNTERPARTY_ADDRESS)) - .anySatisfy(violation -> assertThat(violation.path()).isEqualTo(EDR_REQUEST_DTO_PROTOCOL)) - .anySatisfy(violation -> assertThat(violation.path()).isEqualTo(EDR_REQUEST_DTO_POLICY)); - } - - @Test - void shouldFail_whenOfferMandatoryPropertiesAreMissing() { - var input = Json.createObjectBuilder() - .add(EDR_REQUEST_DTO_COUNTERPARTY_ADDRESS, value("http://connector-address")) - .add(EDR_REQUEST_DTO_PROTOCOL, value("protocol")) - .add(EDR_REQUEST_DTO_PROVIDER_ID, value("connector-id")) - .add(EDR_REQUEST_DTO_OFFER, createArrayBuilder().add(createObjectBuilder())) - .build(); - - var result = validator.validate(input); - - assertThat(result).isFailed().extracting(ValidationFailure::getViolations).asInstanceOf(list(Violation.class)) - .isNotEmpty() - .anySatisfy(violation -> assertThat(violation.path()).isEqualTo(EDR_REQUEST_DTO_OFFER + "/" + OFFER_ID)) - .anySatisfy(violation -> assertThat(violation.path()).isEqualTo(EDR_REQUEST_DTO_OFFER + "/" + ASSET_ID)) - .anySatisfy(violation -> assertThat(violation.path()).isEqualTo(EDR_REQUEST_DTO_OFFER + "/" + POLICY)); - } - - private JsonArrayBuilder value(String value) { - return createArrayBuilder().add(createObjectBuilder().add(VALUE, value)); - } -} diff --git a/edc-extensions/edr/edr-cache-sql/README.md b/edc-extensions/edr/edr-cache-sql/README.md deleted file mode 100644 index 6e88c4bb0..000000000 --- a/edc-extensions/edr/edr-cache-sql/README.md +++ /dev/null @@ -1,28 +0,0 @@ -# SQL-based `EndpointDataReferenceCache` extension - -This extension provide a persistent implementation of `EndpointDataReferenceCache`. - -It will store in the database this fields: - -- transferProcessId -- agreementId -- assetId -- edrId - -It represents a single EDR negotiation done with the new Control Plane EDR APIs. - -The EDR itself it is stored in the participant vault with a prefixed key `edr--`. - -**_Note that the SQL statements (DDL) are specific to and only tested with PostgreSQL. Using it with other RDBMS may -work but might have unexpected side effects!_** - -## 1. Table schema - -see [schema.sql](docs/schema.sql). - -## 2. Configuration - -| Key | Description | Mandatory | Default | -|:------------------------|:--------------------------------------------------------------------------------------------------|-----------|---------| -| edc.datasource.edr.name | Datasource used by this extension | | edr | -| edc.edr.vault.path | Directory/Path where to store EDRs in the vault for vaults that supports hierarchical structuring | | | diff --git a/edc-extensions/edr/edr-cache-sql/build.gradle.kts b/edc-extensions/edr/edr-cache-sql/build.gradle.kts deleted file mode 100644 index 8d1fde1e8..000000000 --- a/edc-extensions/edr/edr-cache-sql/build.gradle.kts +++ /dev/null @@ -1,42 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -plugins { - `java-library` - `maven-publish` -} - -dependencies { - implementation(project(":spi:edr-spi")) - - implementation(libs.edc.spi.core) - implementation(libs.edc.core.sql) - implementation(libs.edc.spi.transactionspi) - implementation(libs.edc.spi.transaction.datasource) - implementation(libs.edc.sql.lease) - - testImplementation(libs.edc.transaction.local) - - testImplementation(testFixtures(project(":spi:edr-spi"))) - testImplementation(testFixtures(libs.edc.core.sql)) - testImplementation(testFixtures(libs.edc.sql.lease)) - - testImplementation(testFixtures(libs.edc.junit)) - -} diff --git a/edc-extensions/edr/edr-cache-sql/docs/schema.sql b/edc-extensions/edr/edr-cache-sql/docs/schema.sql deleted file mode 100644 index 24a94045f..000000000 --- a/edc-extensions/edr/edr-cache-sql/docs/schema.sql +++ /dev/null @@ -1,56 +0,0 @@ --- --- Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) --- --- This program and the accompanying materials are made available under the --- terms of the Apache License, Version 2.0 which is available at --- https://www.apache.org/licenses/LICENSE-2.0 --- --- SPDX-License-Identifier: Apache-2.0 --- --- Contributors: --- Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - initial API and implementation --- - - -CREATE TABLE IF NOT EXISTS edc_lease -( - leased_by VARCHAR NOT NULL, - leased_at BIGINT, - lease_duration INTEGER DEFAULT 60000 NOT NULL, - lease_id VARCHAR NOT NULL - CONSTRAINT lease_pk - PRIMARY KEY -); - -COMMENT ON COLUMN edc_lease.leased_at IS 'posix timestamp of lease'; - -COMMENT ON COLUMN edc_lease.lease_duration IS 'duration of lease in milliseconds'; - - -CREATE UNIQUE INDEX IF NOT EXISTS lease_lease_id_uindex - ON edc_lease (lease_id); - -CREATE TABLE IF NOT EXISTS edc_edr_cache -( - transfer_process_id VARCHAR NOT NULL PRIMARY KEY, - agreement_id VARCHAR NOT NULL, - asset_id VARCHAR NOT NULL, - edr_id VARCHAR NOT NULL, - contract_negotiation_id VARCHAR, - provider_id VARCHAR, - expiration_timestamp BIGINT, - state INTEGER DEFAULT 0 NOT NULL, - state_count INTEGER DEFAULT 0, - state_timestamp BIGINT, - error_detail VARCHAR, - lease_id VARCHAR CONSTRAINT edc_edr_cache_lease_lease_id_fk REFERENCES edc_lease ON DELETE SET NULL, - created_at BIGINT NOT NULL, - updated_at BIGINT NOT NULL -); - -CREATE INDEX IF NOT EXISTS edc_edr_asset_id_index - ON edc_edr_cache (asset_id); - - -CREATE INDEX IF NOT EXISTS edc_edr_agreement_id_index - ON edc_edr_cache (agreement_id); diff --git a/edc-extensions/edr/edr-cache-sql/src/main/java/org/eclipse/tractusx/edc/edr/store/sql/SqlEndpointDataReferenceCache.java b/edc-extensions/edr/edr-cache-sql/src/main/java/org/eclipse/tractusx/edc/edr/store/sql/SqlEndpointDataReferenceCache.java deleted file mode 100644 index 38a115630..000000000 --- a/edc-extensions/edr/edr-cache-sql/src/main/java/org/eclipse/tractusx/edc/edr/store/sql/SqlEndpointDataReferenceCache.java +++ /dev/null @@ -1,315 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.edr.store.sql; - -import com.fasterxml.jackson.databind.ObjectMapper; -import org.eclipse.edc.spi.persistence.EdcPersistenceException; -import org.eclipse.edc.spi.query.Criterion; -import org.eclipse.edc.spi.query.QuerySpec; -import org.eclipse.edc.spi.result.StoreResult; -import org.eclipse.edc.spi.security.Vault; -import org.eclipse.edc.spi.types.domain.edr.EndpointDataReference; -import org.eclipse.edc.sql.QueryExecutor; -import org.eclipse.edc.sql.ResultSetMapper; -import org.eclipse.edc.sql.lease.SqlLeaseContextBuilder; -import org.eclipse.edc.sql.store.AbstractSqlStore; -import org.eclipse.edc.transaction.datasource.spi.DataSourceRegistry; -import org.eclipse.edc.transaction.spi.TransactionContext; -import org.eclipse.tractusx.edc.edr.spi.store.EndpointDataReferenceCache; -import org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntry; -import org.eclipse.tractusx.edc.edr.store.sql.schema.EdrStatements; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.sql.Connection; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.time.Clock; -import java.util.Arrays; -import java.util.List; -import java.util.Objects; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import static java.lang.String.format; -import static java.util.stream.Collectors.toList; -import static org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntry.ASSET_ID; -import static org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntry.PROVIDER_ID; - -public class SqlEndpointDataReferenceCache extends AbstractSqlStore implements EndpointDataReferenceCache { - - public static final String SEPARATOR = "--"; - public static final String VAULT_PREFIX = "edr" + SEPARATOR; - private final EdrStatements statements; - private final String vaultPath; - private final Clock clock; - private final Vault vault; - - private final SqlLeaseContextBuilder leaseContext; - - - public SqlEndpointDataReferenceCache(DataSourceRegistry dataSourceRegistry, String dataSourceName, - TransactionContext transactionContext, EdrStatements statements, - ObjectMapper objectMapper, Vault vault, String vaultPath, Clock clock, - QueryExecutor queryExecutor, String connectorId) { - super(dataSourceRegistry, dataSourceName, transactionContext, objectMapper, queryExecutor); - this.statements = statements; - this.vaultPath = vaultPath; - this.clock = clock; - this.vault = vault; - leaseContext = SqlLeaseContextBuilder.with(transactionContext, connectorId, statements, clock, queryExecutor); - } - - @Override - public @Nullable EndpointDataReference resolveReference(String transferProcessId) { - Objects.requireNonNull(transferProcessId); - return transactionContext.execute(() -> { - try (var connection = getConnection()) { - var edrId = findById(connection, transferProcessId, this::mapToEdrId); - if (edrId != null) { - return referenceFromEntry(edrId); - } - return null; - } catch (Exception exception) { - throw new EdcPersistenceException(exception); - } - }); - } - - @Override - public @Nullable StoreResult findByIdAndLease(String transferProcessId) { - return transactionContext.execute(() -> { - try (var connection = getConnection()) { - var entity = findById(connection, transferProcessId, this::mapResultSet); - if (entity == null) { - return StoreResult.notFound(format("EndpointDataReference %s not found", transferProcessId)); - } - leaseContext.withConnection(connection).acquireLease(entity.getId()); - return StoreResult.success(entity); - } catch (Exception exception) { - throw new EdcPersistenceException(exception); - } - }); - } - - @Override - public @NotNull List referencesForAsset(String assetId, String providerId) { - var querySpec = QuerySpec.Builder.newInstance(); - querySpec.filter(filterFor(ASSET_ID, assetId)); - - if (providerId != null) { - querySpec.filter(filterFor(PROVIDER_ID, providerId)); - } - - return internalQuery(querySpec.build(), this::mapToWrapper) - .filter(wrapper -> filterActive(wrapper.getEntry())) - .map(EndpointDataReferenceEntryWrapper::getEdrId) - .map(this::referenceFromEntry).collect(Collectors.toList()); - } - - @Override - public Stream queryForEntries(QuerySpec spec) { - return internalQuery(spec, this::mapResultSet); - } - - @Override - public void save(EndpointDataReferenceEntry entry, EndpointDataReference edr) { - transactionContext.execute(() -> { - try (var connection = getConnection()) { - var sql = statements.getInsertTemplate(); - queryExecutor.execute(connection, sql, - entry.getTransferProcessId(), - entry.getAssetId(), - entry.getAgreementId(), - edr.getId(), - entry.getProviderId(), - entry.getContractNegotiationId(), - entry.getExpirationTimestamp(), - entry.getState(), - entry.getStateCount(), - entry.getStateTimestamp(), - entry.getErrorDetail(), - entry.getCreatedAt(), - entry.getUpdatedAt()); - vault.storeSecret(vaultPath + VAULT_PREFIX + edr.getId(), toJson(edr)).orElseThrow((failure) -> new EdcPersistenceException(failure.getFailureDetail())); - } catch (Exception exception) { - throw new EdcPersistenceException(exception); - } - }); - } - - @Override - public void update(EndpointDataReferenceEntry entry) { - transactionContext.execute(() -> { - try (var connection = getConnection()) { - leaseContext.withConnection(connection).breakLease(entry.getTransferProcessId()); - var sql = statements.getUpdateTemplate(); - queryExecutor.execute(connection, sql, - entry.getState(), - entry.getStateCount(), - entry.getStateTimestamp(), - entry.getErrorDetail(), - entry.getUpdatedAt(), - entry.getTransferProcessId()); - } catch (SQLException exception) { - throw new EdcPersistenceException(exception); - } - }); - } - - @Override - public StoreResult deleteByTransferProcessId(String id) { - return transactionContext.execute(() -> { - try (var connection = getConnection()) { - var entryWrapper = findById(connection, id, this::mapToWrapper); - if (entryWrapper != null) { - leaseContext.withConnection(connection).acquireLease(id); - queryExecutor.execute(connection, statements.getDeleteByIdTemplate(), id); - leaseContext.withConnection(connection).breakLease(id); - vault.deleteSecret(vaultPath + VAULT_PREFIX + entryWrapper.getEdrId()).orElseThrow((failure) -> new EdcPersistenceException(failure.getFailureDetail())); - return StoreResult.success(entryWrapper.getEntry()); - } else { - return StoreResult.notFound(format("EDR with id %s not found", id)); - } - } catch (SQLException exception) { - throw new EdcPersistenceException(exception); - } - }); - } - - @Override - public @Nullable EndpointDataReferenceEntry findById(String id) { - return transactionContext.execute(() -> { - try (var connection = getConnection()) { - return findById(connection, id, this::mapResultSet); - } catch (Exception exception) { - throw new EdcPersistenceException(exception); - } - }); - } - - @Override - public @NotNull List nextNotLeased(int max, Criterion... criteria) { - return transactionContext.execute(() -> { - var filter = Arrays.stream(criteria).collect(toList()); - var querySpec = QuerySpec.Builder.newInstance().filter(filter).limit(max).build(); - var statement = statements.createQuery(querySpec); - statement.addWhereClause(statements.getNotLeasedFilter()); - statement.addParameter(clock.millis()); - - try ( - var connection = getConnection(); - var stream = queryExecutor.query(getConnection(), true, this::mapResultSet, statement.getQueryAsString(), statement.getParameters()) - ) { - var negotiations = stream.collect(toList()); - negotiations.forEach(cn -> leaseContext.withConnection(connection).acquireLease(cn.getId())); - return negotiations; - } catch (SQLException e) { - throw new EdcPersistenceException(e); - } - }); - } - - @Override - public void save(EndpointDataReferenceEntry entity) { - throw new UnsupportedOperationException("Please use save(EndpointDataReferenceEntry, EndpointDataReference) instead!"); - } - - private T findById(Connection connection, String id, ResultSetMapper resultSetMapper) { - var sql = statements.getFindByTransferProcessIdTemplate(); - return queryExecutor.single(connection, false, resultSetMapper, sql, id); - } - - @NotNull - private Stream internalQuery(QuerySpec spec, ResultSetMapper resultSetMapper) { - return transactionContext.execute(() -> { - try { - var queryStmt = statements.createQuery(spec); - return queryExecutor.query(getConnection(), true, resultSetMapper, queryStmt.getQueryAsString(), queryStmt.getParameters()); - } catch (SQLException exception) { - throw new EdcPersistenceException(exception); - } - }); - - } - - private EndpointDataReferenceEntry mapResultSet(ResultSet resultSet) throws SQLException { - Long expirationTimestamp = resultSet.getLong(statements.getExpirationTimestampColumn()); - if (resultSet.wasNull()) { - expirationTimestamp = null; - } - return EndpointDataReferenceEntry.Builder.newInstance() - .transferProcessId(resultSet.getString(statements.getTransferProcessIdColumn())) - .assetId(resultSet.getString(statements.getAssetIdColumn())) - .agreementId(resultSet.getString(statements.getAgreementIdColumn())) - .contractNegotiationId(resultSet.getString(statements.getContractNegotiationIdColumn())) - .providerId(resultSet.getString(statements.getProviderIdColumn())) - .state(resultSet.getInt(statements.getStateColumn())) - .stateTimestamp(resultSet.getLong(statements.getStateTimestampColumn())) - .stateCount(resultSet.getInt(statements.getStateCountColumn())) - .createdAt(resultSet.getLong(statements.getCreatedAtColumn())) - .updatedAt(resultSet.getLong(statements.getUpdatedAtColumn())) - .errorDetail(resultSet.getString(statements.getErrorDetailColumn())) - .expirationTimestamp(expirationTimestamp) - .build(); - } - - private String mapToEdrId(ResultSet resultSet) throws SQLException { - return resultSet.getString(statements.getEdrId()); - } - - private EndpointDataReferenceEntryWrapper mapToWrapper(ResultSet resultSet) throws SQLException { - return new EndpointDataReferenceEntryWrapper(mapResultSet(resultSet), mapToEdrId(resultSet)); - } - - private EndpointDataReference referenceFromEntry(String edrId) { - var edr = vault.resolveSecret(vaultPath + VAULT_PREFIX + edrId); - if (edr != null) { - return fromJson(edr, EndpointDataReference.class); - } - return null; - } - - private Criterion filterFor(String field, Object value) { - return Criterion.Builder.newInstance() - .operandLeft(field) - .operator("=") - .operandRight(value) - .build(); - } - - private static class EndpointDataReferenceEntryWrapper { - private final EndpointDataReferenceEntry entry; - private final String edrId; - - private EndpointDataReferenceEntryWrapper(EndpointDataReferenceEntry entry, String edrId) { - this.entry = Objects.requireNonNull(entry); - this.edrId = Objects.requireNonNull(edrId); - } - - public EndpointDataReferenceEntry getEntry() { - return entry; - } - - public String getEdrId() { - return edrId; - } - } -} diff --git a/edc-extensions/edr/edr-cache-sql/src/main/java/org/eclipse/tractusx/edc/edr/store/sql/SqlEndpointDataReferenceCacheExtension.java b/edc-extensions/edr/edr-cache-sql/src/main/java/org/eclipse/tractusx/edc/edr/store/sql/SqlEndpointDataReferenceCacheExtension.java deleted file mode 100644 index 769da1ca7..000000000 --- a/edc-extensions/edr/edr-cache-sql/src/main/java/org/eclipse/tractusx/edc/edr/store/sql/SqlEndpointDataReferenceCacheExtension.java +++ /dev/null @@ -1,83 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.edr.store.sql; - -import org.eclipse.edc.runtime.metamodel.annotation.Extension; -import org.eclipse.edc.runtime.metamodel.annotation.Inject; -import org.eclipse.edc.runtime.metamodel.annotation.Provider; -import org.eclipse.edc.runtime.metamodel.annotation.Setting; -import org.eclipse.edc.spi.security.Vault; -import org.eclipse.edc.spi.system.ServiceExtension; -import org.eclipse.edc.spi.system.ServiceExtensionContext; -import org.eclipse.edc.spi.types.TypeManager; -import org.eclipse.edc.sql.QueryExecutor; -import org.eclipse.edc.transaction.datasource.spi.DataSourceRegistry; -import org.eclipse.edc.transaction.spi.TransactionContext; -import org.eclipse.tractusx.edc.edr.spi.store.EndpointDataReferenceCache; -import org.eclipse.tractusx.edc.edr.store.sql.schema.EdrStatements; -import org.eclipse.tractusx.edc.edr.store.sql.schema.postgres.PostgresEdrStatements; - -import java.time.Clock; - -@Extension(value = SqlEndpointDataReferenceCacheExtension.NAME) -public class SqlEndpointDataReferenceCacheExtension implements ServiceExtension { - - public static final String NAME = "SQL EDR cache store"; - - @Setting(required = true, value = "Datasource name for EDR Cache SQL store", defaultValue = DataSourceRegistry.DEFAULT_DATASOURCE) - public static final String DATASOURCE_SETTING_NAME = "edc.datasource.edr.name"; - - private static final String DEFAULT_EDR_VAULT_PATH = ""; - @Setting(value = "Directory/Path where to store EDRs in the vault for vaults that supports hierarchical structuring.", defaultValue = DEFAULT_EDR_VAULT_PATH) - public static final String EDC_EDR_VAULT_PATH = "edc.edr.vault.path"; - - @Inject - private DataSourceRegistry dataSourceRegistry; - @Inject - private TransactionContext transactionContext; - @Inject(required = false) - private EdrStatements statements; - @Inject - private TypeManager typeManager; - @Inject - private Clock clock; - @Inject - private Vault vault; - - @Inject - private QueryExecutor queryExecutor; - - @Override - public String name() { - return NAME; - } - - @Provider - public EndpointDataReferenceCache edrCache(ServiceExtensionContext context) { - var dataSourceName = context.getConfig().getString(DATASOURCE_SETTING_NAME, DataSourceRegistry.DEFAULT_DATASOURCE); - var vaultDirectory = context.getConfig().getString(EDC_EDR_VAULT_PATH, DEFAULT_EDR_VAULT_PATH); - return new SqlEndpointDataReferenceCache(dataSourceRegistry, dataSourceName, transactionContext, getStatementImpl(), - typeManager.getMapper(), vault, vaultDirectory, clock, queryExecutor, context.getConnectorId()); - } - - private EdrStatements getStatementImpl() { - return statements == null ? new PostgresEdrStatements() : statements; - } -} diff --git a/edc-extensions/edr/edr-cache-sql/src/main/java/org/eclipse/tractusx/edc/edr/store/sql/schema/BaseSqlEdrStatements.java b/edc-extensions/edr/edr-cache-sql/src/main/java/org/eclipse/tractusx/edc/edr/store/sql/schema/BaseSqlEdrStatements.java deleted file mode 100644 index 168a21129..000000000 --- a/edc-extensions/edr/edr-cache-sql/src/main/java/org/eclipse/tractusx/edc/edr/store/sql/schema/BaseSqlEdrStatements.java +++ /dev/null @@ -1,102 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2020,2022 Microsoft Corporation - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.edr.store.sql.schema; - -import org.eclipse.edc.spi.query.QuerySpec; -import org.eclipse.edc.sql.translation.SqlOperatorTranslator; -import org.eclipse.edc.sql.translation.SqlQueryStatement; - -import static java.lang.String.format; - -public class BaseSqlEdrStatements implements EdrStatements { - - private final SqlOperatorTranslator sqlOperatorTranslator; - - public BaseSqlEdrStatements(SqlOperatorTranslator sqlOperatorTranslator) { - this.sqlOperatorTranslator = sqlOperatorTranslator; - } - - @Override - public String getFindByTransferProcessIdTemplate() { - return format("SELECT * FROM %s WHERE %s = ?", getEdrTable(), getTransferProcessIdColumn()); - } - - @Override - public SqlQueryStatement createQuery(QuerySpec querySpec) { - var select = format("SELECT * FROM %s", getEdrTable()); - return new SqlQueryStatement(select, querySpec, new EdrMapping(this), sqlOperatorTranslator); - } - - @Override - public String getInsertTemplate() { - return format("INSERT INTO %s (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", - getEdrTable(), - getTransferProcessIdColumn(), - getAssetIdColumn(), - getAgreementIdColumn(), - getEdrId(), - getProviderIdColumn(), - getContractNegotiationIdColumn(), - getExpirationTimestampColumn(), - getStateColumn(), - getStateCountColumn(), - getStateTimestampColumn(), - getErrorDetailColumn(), - getCreatedAtColumn(), - getUpdatedAtColumn() - ); - } - - @Override - public String getUpdateTemplate() { - return format("UPDATE %s SET %s=?, %s=?, %s=?, %s=?, %s=? WHERE %s = ?;", - getEdrTable(), getStateColumn(), getStateCountColumn(), getStateTimestampColumn(), - getErrorDetailColumn(), getUpdatedAtColumn(), getTransferProcessIdColumn()); - } - - @Override - public String getDeleteByIdTemplate() { - return format("DELETE FROM %s WHERE %s = ?", - getEdrTable(), - getTransferProcessIdColumn()); - } - - @Override - public String getDeleteLeaseTemplate() { - return format("DELETE FROM %s WHERE %s=?", getLeaseTableName(), getLeaseIdColumn()); - } - - @Override - public String getInsertLeaseTemplate() { - return format("INSERT INTO %s (%s, %s, %s, %s) VALUES (?, ?, ?, ?);", - getLeaseTableName(), getLeaseIdColumn(), getLeasedByColumn(), getLeasedAtColumn(), getLeaseDurationColumn()); - } - - @Override - public String getUpdateLeaseTemplate() { - return format("UPDATE %s SET %s=? WHERE %s = ?;", getEdrTable(), getLeaseIdColumn(), getTransferProcessIdColumn()); - } - - @Override - public String getFindLeaseByEntityTemplate() { - return format("SELECT * FROM %s WHERE %s = (SELECT lease_id FROM %s WHERE %s=? )", - getLeaseTableName(), getLeaseIdColumn(), getEdrTable(), getTransferProcessIdColumn()); - } -} diff --git a/edc-extensions/edr/edr-cache-sql/src/main/java/org/eclipse/tractusx/edc/edr/store/sql/schema/EdrMapping.java b/edc-extensions/edr/edr-cache-sql/src/main/java/org/eclipse/tractusx/edc/edr/store/sql/schema/EdrMapping.java deleted file mode 100644 index fbeb27f55..000000000 --- a/edc-extensions/edr/edr-cache-sql/src/main/java/org/eclipse/tractusx/edc/edr/store/sql/schema/EdrMapping.java +++ /dev/null @@ -1,37 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.edr.store.sql.schema; - -import org.eclipse.edc.sql.translation.TranslationMapping; -import org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntry; - -/** - * Maps fields of a {@link EndpointDataReferenceEntry} onto the - * corresponding SQL schema (= column names) - */ -public class EdrMapping extends TranslationMapping { - public EdrMapping(EdrStatements statements) { - add("assetId", statements.getAssetIdColumn()); - add("agreementId", statements.getAgreementIdColumn()); - add("providerId", statements.getProviderIdColumn()); - add("contractNegotiationId", statements.getContractNegotiationIdColumn()); - add("state", statements.getStateColumn()); - } -} diff --git a/edc-extensions/edr/edr-cache-sql/src/main/java/org/eclipse/tractusx/edc/edr/store/sql/schema/EdrStatements.java b/edc-extensions/edr/edr-cache-sql/src/main/java/org/eclipse/tractusx/edc/edr/store/sql/schema/EdrStatements.java deleted file mode 100644 index 9e49a9e1a..000000000 --- a/edc-extensions/edr/edr-cache-sql/src/main/java/org/eclipse/tractusx/edc/edr/store/sql/schema/EdrStatements.java +++ /dev/null @@ -1,98 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.edr.store.sql.schema; - -import org.eclipse.edc.spi.query.QuerySpec; -import org.eclipse.edc.sql.lease.LeaseStatements; -import org.eclipse.edc.sql.translation.SqlQueryStatement; - -/** - * Sql Statements for DataPlane Store - */ -public interface EdrStatements extends LeaseStatements { - - default String getEdrTable() { - return "edc_edr_cache"; - } - - default String getTransferProcessIdColumn() { - return "transfer_process_id"; - } - - default String getAgreementIdColumn() { - return "agreement_id"; - } - - default String getProviderIdColumn() { - return "provider_id"; - } - - default String getContractNegotiationIdColumn() { - return "contract_negotiation_id"; - } - - default String getAssetIdColumn() { - return "asset_id"; - } - - default String getEdrId() { - return "edr_id"; - } - - default String getCreatedAtColumn() { - return "created_at"; - } - - default String getUpdatedAtColumn() { - return "updated_at"; - } - - default String getStateColumn() { - return "state"; - } - - default String getExpirationTimestampColumn() { - return "expiration_timestamp"; - } - - default String getStateCountColumn() { - return "state_count"; - } - - default String getStateTimestampColumn() { - return "state_timestamp"; - } - - default String getErrorDetailColumn() { - return "error_detail"; - } - - String getFindByTransferProcessIdTemplate(); - - SqlQueryStatement createQuery(QuerySpec querySpec); - - String getInsertTemplate(); - - String getUpdateTemplate(); - - String getDeleteByIdTemplate(); - -} - diff --git a/edc-extensions/edr/edr-cache-sql/src/main/java/org/eclipse/tractusx/edc/edr/store/sql/schema/postgres/PostgresEdrStatements.java b/edc-extensions/edr/edr-cache-sql/src/main/java/org/eclipse/tractusx/edc/edr/store/sql/schema/postgres/PostgresEdrStatements.java deleted file mode 100644 index fea1c59b1..000000000 --- a/edc-extensions/edr/edr-cache-sql/src/main/java/org/eclipse/tractusx/edc/edr/store/sql/schema/postgres/PostgresEdrStatements.java +++ /dev/null @@ -1,31 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.edr.store.sql.schema.postgres; - -import org.eclipse.edc.sql.translation.PostgresqlOperatorTranslator; -import org.eclipse.tractusx.edc.edr.store.sql.schema.BaseSqlEdrStatements; - -public class PostgresEdrStatements extends BaseSqlEdrStatements { - - - public PostgresEdrStatements() { - super(new PostgresqlOperatorTranslator()); - } -} diff --git a/edc-extensions/edr/edr-cache-sql/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension b/edc-extensions/edr/edr-cache-sql/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension deleted file mode 100644 index 6ce8fce04..000000000 --- a/edc-extensions/edr/edr-cache-sql/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension +++ /dev/null @@ -1,20 +0,0 @@ -################################################################################# -# Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) -# -# See the NOTICE file(s) distributed with this work for additional -# information regarding copyright ownership. -# -# This program and the accompanying materials are made available under the -# terms of the Apache License, Version 2.0 which is available at -# https://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. -# -# SPDX-License-Identifier: Apache-2.0 -################################################################################# - -org.eclipse.tractusx.edc.edr.store.sql.SqlEndpointDataReferenceCacheExtension diff --git a/edc-extensions/edr/edr-cache-sql/src/test/java/org/eclipse/tractusx/edc/edr/store/sql/SqlEndpointDataReferenceCacheExtensionTest.java b/edc-extensions/edr/edr-cache-sql/src/test/java/org/eclipse/tractusx/edc/edr/store/sql/SqlEndpointDataReferenceCacheExtensionTest.java deleted file mode 100644 index 621190751..000000000 --- a/edc-extensions/edr/edr-cache-sql/src/test/java/org/eclipse/tractusx/edc/edr/store/sql/SqlEndpointDataReferenceCacheExtensionTest.java +++ /dev/null @@ -1,59 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.edr.store.sql; - -import org.eclipse.edc.junit.extensions.DependencyInjectionExtension; -import org.eclipse.edc.spi.system.ServiceExtensionContext; -import org.eclipse.edc.spi.system.configuration.Config; -import org.eclipse.edc.spi.types.TypeManager; -import org.eclipse.edc.transaction.datasource.spi.DataSourceRegistry; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.eclipse.edc.transaction.datasource.spi.DataSourceRegistry.DEFAULT_DATASOURCE; -import static org.eclipse.tractusx.edc.edr.store.sql.SqlEndpointDataReferenceCacheExtension.DATASOURCE_SETTING_NAME; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -@ExtendWith(DependencyInjectionExtension.class) -public class SqlEndpointDataReferenceCacheExtensionTest { - - @BeforeEach - void setUp(ServiceExtensionContext context) { - context.registerService(TypeManager.class, new TypeManager()); - context.registerService(DataSourceRegistry.class, mock()); - } - - @Test - void shouldInitializeTheStore(ServiceExtensionContext context, SqlEndpointDataReferenceCacheExtension extension) { - var config = mock(Config.class); - when(context.getConfig()).thenReturn(config); - when(config.getString(any(), any())).thenReturn(DEFAULT_DATASOURCE); - - var cache = extension.edrCache(context); - - assertThat(cache).isInstanceOf(SqlEndpointDataReferenceCache.class); - verify(config).getString(DATASOURCE_SETTING_NAME, DEFAULT_DATASOURCE); - } -} diff --git a/edc-extensions/edr/edr-cache-sql/src/test/java/org/eclipse/tractusx/edc/edr/store/sql/SqlEndpointDataReferenceCacheTest.java b/edc-extensions/edr/edr-cache-sql/src/test/java/org/eclipse/tractusx/edc/edr/store/sql/SqlEndpointDataReferenceCacheTest.java deleted file mode 100644 index 4faee82c0..000000000 --- a/edc-extensions/edr/edr-cache-sql/src/test/java/org/eclipse/tractusx/edc/edr/store/sql/SqlEndpointDataReferenceCacheTest.java +++ /dev/null @@ -1,142 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.edr.store.sql; - -import org.eclipse.edc.junit.annotations.PostgresqlIntegrationTest; -import org.eclipse.edc.spi.result.Result; -import org.eclipse.edc.spi.security.Vault; -import org.eclipse.edc.spi.types.TypeManager; -import org.eclipse.edc.sql.QueryExecutor; -import org.eclipse.edc.sql.lease.testfixtures.LeaseUtil; -import org.eclipse.edc.sql.testfixtures.PostgresqlStoreSetupExtension; -import org.eclipse.tractusx.edc.edr.spi.EndpointDataReferenceCacheTestBase; -import org.eclipse.tractusx.edc.edr.spi.store.EndpointDataReferenceCache; -import org.eclipse.tractusx.edc.edr.store.sql.schema.EdrStatements; -import org.eclipse.tractusx.edc.edr.store.sql.schema.postgres.PostgresEdrStatements; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.sql.SQLException; -import java.time.Clock; -import java.time.Duration; - -import static java.util.UUID.randomUUID; -import static org.eclipse.tractusx.edc.edr.spi.TestFunctions.edr; -import static org.eclipse.tractusx.edc.edr.spi.TestFunctions.edrEntry; -import static org.eclipse.tractusx.edc.edr.store.sql.SqlEndpointDataReferenceCache.SEPARATOR; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.argThat; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -@PostgresqlIntegrationTest -@ExtendWith(PostgresqlStoreSetupExtension.class) -public class SqlEndpointDataReferenceCacheTest extends EndpointDataReferenceCacheTestBase { - - EdrStatements statements = new PostgresEdrStatements(); - SqlEndpointDataReferenceCache cache; - - Clock clock = Clock.systemUTC(); - - Vault vault = mock(Vault.class); - - TypeManager typeManager = new TypeManager(); - - LeaseUtil leaseUtil; - - @BeforeEach - void setUp(PostgresqlStoreSetupExtension extension, QueryExecutor queryExecutor) throws IOException { - - when(vault.deleteSecret(any())).thenReturn(Result.success()); - when(vault.storeSecret(any(), any())).thenReturn(Result.success()); - when(vault.resolveSecret(any())).then(a -> edrJson(a.getArgument(0))); - - cache = new SqlEndpointDataReferenceCache(extension.getDataSourceRegistry(), extension.getDatasourceName(), extension.getTransactionContext(), statements, typeManager.getMapper(), vault, "", clock, queryExecutor, CONNECTOR_NAME); - var schema = Files.readString(Paths.get("./docs/schema.sql")); - extension.runQuery(schema); - leaseUtil = new LeaseUtil(extension.getTransactionContext(), extension::getConnection, statements, clock); - - } - - @AfterEach - void tearDown(PostgresqlStoreSetupExtension extension) throws SQLException { - extension.runQuery("DROP TABLE " + statements.getEdrTable() + " CASCADE"); - } - - @Test - void verify_unoffensive_secretKey() { - var tpId = "tp1"; - var assetId = "asset1"; - var edrId = "edr1"; - - var edr = edr(edrId); - var entry = edrEntry(assetId, randomUUID().toString(), tpId); - - getStore().save(entry, edr); - - verify(vault).storeSecret(argThat(s -> s.startsWith("edr--")), anyString()); - } - - @Test - void verify_custom_vaultPath(PostgresqlStoreSetupExtension extension, QueryExecutor queryExecutor) { - - var path = "testPath/"; - cache = new SqlEndpointDataReferenceCache(extension.getDataSourceRegistry(), extension.getDatasourceName(), extension.getTransactionContext(), statements, typeManager.getMapper(), vault, path, clock, queryExecutor, CONNECTOR_NAME); - - var tpId = "tp1"; - var assetId = "asset1"; - var edrId = "edr1"; - - var edr = edr(edrId); - var entry = edrEntry(assetId, randomUUID().toString(), tpId); - - cache.save(entry, edr); - - verify(vault).storeSecret(argThat(s -> s.startsWith(path + "edr--")), anyString()); - } - - @Override - protected EndpointDataReferenceCache getStore() { - return cache; - } - - @Override - protected void lockEntity(String negotiationId, String owner, Duration duration) { - leaseUtil.leaseEntity(negotiationId, owner, duration); - } - - @Override - protected boolean isLockedBy(String negotiationId, String owner) { - return leaseUtil.isLeased(negotiationId, owner); - } - - - private String edrJson(String id) { - return typeManager.writeValueAsString(edr(id.split(SEPARATOR)[1])); - } - -} diff --git a/edc-extensions/edr/edr-cache-sql/src/test/java/org/eclipse/tractusx/edc/edr/store/sql/SqlEndpointDataReferenceCacheTransactionalTest.java b/edc-extensions/edr/edr-cache-sql/src/test/java/org/eclipse/tractusx/edc/edr/store/sql/SqlEndpointDataReferenceCacheTransactionalTest.java deleted file mode 100644 index a3aae64c3..000000000 --- a/edc-extensions/edr/edr-cache-sql/src/test/java/org/eclipse/tractusx/edc/edr/store/sql/SqlEndpointDataReferenceCacheTransactionalTest.java +++ /dev/null @@ -1,157 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.edr.store.sql; - -import org.eclipse.edc.junit.annotations.PostgresqlIntegrationTest; -import org.eclipse.edc.spi.persistence.EdcPersistenceException; -import org.eclipse.edc.spi.query.QuerySpec; -import org.eclipse.edc.spi.result.Result; -import org.eclipse.edc.spi.result.StoreResult; -import org.eclipse.edc.spi.security.Vault; -import org.eclipse.edc.spi.types.TypeManager; -import org.eclipse.edc.spi.types.domain.edr.EndpointDataReference; -import org.eclipse.edc.sql.QueryExecutor; -import org.eclipse.edc.sql.testfixtures.PostgresqlStoreSetupExtension; -import org.eclipse.tractusx.edc.edr.store.sql.schema.EdrStatements; -import org.eclipse.tractusx.edc.edr.store.sql.schema.postgres.PostgresEdrStatements; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.sql.SQLException; -import java.time.Clock; - -import static java.util.UUID.randomUUID; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.eclipse.tractusx.edc.edr.spi.EndpointDataReferenceCacheTestBase.CONNECTOR_NAME; -import static org.eclipse.tractusx.edc.edr.spi.TestFunctions.edr; -import static org.eclipse.tractusx.edc.edr.spi.TestFunctions.edrEntry; -import static org.eclipse.tractusx.edc.edr.store.sql.SqlEndpointDataReferenceCache.VAULT_PREFIX; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -@PostgresqlIntegrationTest -@ExtendWith(PostgresqlStoreSetupExtension.class) -public class SqlEndpointDataReferenceCacheTransactionalTest { - - EdrStatements statements = new PostgresEdrStatements(); - SqlEndpointDataReferenceCache cache; - - Clock clock = Clock.systemUTC(); - - Vault vault = mock(Vault.class); - - TypeManager typeManager = new TypeManager(); - - @BeforeEach - void setUp(PostgresqlStoreSetupExtension extension, QueryExecutor queryExecutor) throws IOException { - - when(vault.deleteSecret(any())).thenReturn(Result.success()); - when(vault.storeSecret(any(), any())).thenReturn(Result.success()); - - cache = new SqlEndpointDataReferenceCache(extension.getDataSourceRegistry(), extension.getDatasourceName(), extension.getTransactionContext(), statements, typeManager.getMapper(), vault, "", clock, queryExecutor, CONNECTOR_NAME); - var schema = Files.readString(Paths.get("./docs/schema.sql")); - extension.runQuery(schema); - - } - - @Test - void save_shouldFail_whenVaultError() { - - var tpId = "tp1"; - var assetId = "asset1"; - var edrId = "edr1"; - - var edr = edr(edrId); - var entry = edrEntry(assetId, randomUUID().toString(), tpId); - - when(vault.storeSecret(any(), any())).thenReturn(Result.failure("fail")); - when(vault.resolveSecret(edr.getId())).thenReturn(typeManager.writeValueAsString(edr)); - - assertThatThrownBy(() -> cache.save(entry, edr)).isInstanceOf(EdcPersistenceException.class); - - assertThat(cache.resolveReference(tpId)) - .isNull(); - - } - - @Test - void save() { - - var tpId = "tp1"; - var assetId = "asset1"; - var edrId = "edr1"; - - var edr = edr(edrId); - var entry = edrEntry(assetId, randomUUID().toString(), tpId); - - when(vault.storeSecret(any(), any())).thenReturn(Result.success()); - when(vault.resolveSecret(VAULT_PREFIX + edr.getId())).thenReturn(typeManager.writeValueAsString(edr)); - - cache.save(entry, edr); - - assertThat(cache.resolveReference(tpId)) - .isNotNull() - .extracting(EndpointDataReference::getId) - .isEqualTo(edrId); - - var edrs = cache.referencesForAsset(assetId, null); - assertThat(edrs.size()).isEqualTo(1); - assertThat(edrs.get((0)).getId()).isEqualTo(edrId); - - verify(vault).storeSecret(eq(VAULT_PREFIX + edr.getId()), any()); - verify(vault, times(2)).resolveSecret(eq(VAULT_PREFIX + edr.getId())); - - } - - @Test - void deleteByTransferProcessId_shouldDelete_WhenFound() { - - var entry = edrEntry("assetId", "agreementId", "tpId"); - var edr = edr("edrId"); - cache.save(entry, edr); - - assertThat(cache.deleteByTransferProcessId(entry.getTransferProcessId())) - .extracting(StoreResult::getContent) - .isEqualTo(entry); - - assertThat(cache.resolveReference(entry.getTransferProcessId())).isNull(); - assertThat(cache.referencesForAsset(entry.getAssetId(), null)).hasSize(0); - assertThat(cache.queryForEntries(QuerySpec.max())).hasSize(0); - - verify(vault).storeSecret(eq(VAULT_PREFIX + edr.getId()), any()); - verify(vault).deleteSecret(eq(VAULT_PREFIX + edr.getId())); - } - - @AfterEach - void tearDown(PostgresqlStoreSetupExtension extension) throws SQLException { - extension.runQuery("DROP TABLE " + statements.getEdrTable() + " CASCADE"); - } - -} diff --git a/edc-extensions/edr/edr-callback/src/main/java/org/eclipse/tractusx/edc/callback/LocalCallbackExtension.java b/edc-extensions/edr/edr-callback/src/main/java/org/eclipse/tractusx/edc/callback/LocalCallbackExtension.java index ac3a22b59..e0fe5d9ee 100644 --- a/edc-extensions/edr/edr-callback/src/main/java/org/eclipse/tractusx/edc/callback/LocalCallbackExtension.java +++ b/edc-extensions/edr/edr-callback/src/main/java/org/eclipse/tractusx/edc/callback/LocalCallbackExtension.java @@ -22,7 +22,6 @@ import org.eclipse.edc.connector.spi.callback.CallbackProtocolResolverRegistry; import org.eclipse.edc.connector.spi.contractagreement.ContractAgreementService; import org.eclipse.edc.connector.spi.transferprocess.TransferProcessService; -import org.eclipse.edc.connector.transfer.spi.store.TransferProcessStore; import org.eclipse.edc.runtime.metamodel.annotation.Extension; import org.eclipse.edc.runtime.metamodel.annotation.Inject; import org.eclipse.edc.spi.message.RemoteMessageDispatcherRegistry; @@ -31,7 +30,6 @@ import org.eclipse.edc.spi.system.ServiceExtensionContext; import org.eclipse.edc.transaction.spi.TransactionContext; import org.eclipse.edc.transform.spi.TypeTransformerRegistry; -import org.eclipse.tractusx.edc.edr.spi.store.EndpointDataReferenceCache; import org.eclipse.tractusx.edc.spi.callback.InProcessCallbackRegistry; import static org.eclipse.tractusx.edc.callback.InProcessCallbackMessageDispatcher.CALLBACK_EVENT_LOCAL; @@ -50,12 +48,6 @@ public class LocalCallbackExtension implements ServiceExtension { @Inject private TransferProcessService transferProcessService; - @Inject - private TransferProcessStore transferProcessStore; - - @Inject - private EndpointDataReferenceCache edrCache; - @Inject private InProcessCallbackRegistry callbackRegistry; @@ -64,10 +56,7 @@ public class LocalCallbackExtension implements ServiceExtension { @Inject private TransactionContext transactionContext; - - @Inject - private EndpointDataReferenceCache endpointDataReferenceCache; - + @Inject private ContractAgreementService agreementService; @@ -83,7 +72,6 @@ public String name() { public void initialize(ServiceExtensionContext context) { callbackRegistry.registerHandler(new ContractNegotiationCallback(transferProcessService, monitor)); - callbackRegistry.registerHandler(new TransferProcessLocalCallback(edrCache, transferProcessStore, agreementService, transformerRegistry, transactionContext, monitor)); resolverRegistry.registerResolver(this::resolveProtocol); registry.register(new InProcessCallbackMessageDispatcher(callbackRegistry)); diff --git a/edc-extensions/edr/edr-callback/src/main/java/org/eclipse/tractusx/edc/callback/TransferProcessLocalCallback.java b/edc-extensions/edr/edr-callback/src/main/java/org/eclipse/tractusx/edc/callback/TransferProcessLocalCallback.java deleted file mode 100644 index 6188f3d6c..000000000 --- a/edc-extensions/edr/edr-callback/src/main/java/org/eclipse/tractusx/edc/callback/TransferProcessLocalCallback.java +++ /dev/null @@ -1,198 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.callback; - -import com.nimbusds.jwt.SignedJWT; -import org.eclipse.edc.connector.spi.callback.CallbackEventRemoteMessage; -import org.eclipse.edc.connector.spi.contractagreement.ContractAgreementService; -import org.eclipse.edc.connector.transfer.spi.event.TransferProcessStarted; -import org.eclipse.edc.connector.transfer.spi.event.TransferProcessTerminated; -import org.eclipse.edc.connector.transfer.spi.store.TransferProcessStore; -import org.eclipse.edc.spi.event.Event; -import org.eclipse.edc.spi.monitor.Monitor; -import org.eclipse.edc.spi.query.Criterion; -import org.eclipse.edc.spi.query.QuerySpec; -import org.eclipse.edc.spi.result.Result; -import org.eclipse.edc.spi.types.domain.edr.EndpointDataReference; -import org.eclipse.edc.transaction.spi.TransactionContext; -import org.eclipse.edc.transform.spi.TypeTransformerRegistry; -import org.eclipse.tractusx.edc.edr.spi.store.EndpointDataReferenceCache; -import org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntry; -import org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntryStates; -import org.eclipse.tractusx.edc.spi.callback.InProcessCallback; - -import java.text.ParseException; -import java.time.ZoneOffset; -import java.util.Optional; - -import static java.lang.String.format; -import static org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntryStates.REFRESHING; - -public class TransferProcessLocalCallback implements InProcessCallback { - - private final EndpointDataReferenceCache edrCache; - private final TransferProcessStore transferProcessStore; - private final TypeTransformerRegistry transformerRegistry; - private final TransactionContext transactionContext; - private final Monitor monitor; - private final ContractAgreementService agreementService; - - public TransferProcessLocalCallback(EndpointDataReferenceCache edrCache, TransferProcessStore transferProcessStore, - ContractAgreementService agreementService, TypeTransformerRegistry transformerRegistry, - TransactionContext transactionContext, Monitor monitor) { - this.edrCache = edrCache; - this.transferProcessStore = transferProcessStore; - this.agreementService = agreementService; - this.transformerRegistry = transformerRegistry; - this.transactionContext = transactionContext; - this.monitor = monitor; - } - - @Override - public Result invoke(CallbackEventRemoteMessage message) { - if (message.getEventEnvelope().getPayload() instanceof TransferProcessStarted transferProcessStarted && transferProcessStarted.getDataAddress() != null) { - return transformerRegistry.transform(transferProcessStarted.getDataAddress(), EndpointDataReference.class) - .compose(this::storeEdr) - .mapTo(); - } else if (message.getEventEnvelope().getPayload() instanceof TransferProcessTerminated terminated && terminated.getReason() != null) { - return handleTransferProcessTermination(terminated); - } else { - return Result.success(); - } - } - - private Result handleTransferProcessTermination(TransferProcessTerminated terminated) { - return transactionContext.execute(() -> { - var transferProcess = transferProcessStore.findById(terminated.getTransferProcessId()); - if (transferProcess != null) { - stopEdrNegotiation(transferProcess.getAssetId(), transferProcess.getContractId(), terminated.getReason()); - return Result.success(); - } else { - return Result.failure(format("Failed to find a transfer process with ID %s", terminated.getTransferProcessId())); - } - }); - - } - - private Result storeEdr(EndpointDataReference edr) { - return transactionContext.execute(() -> { - var transferProcess = Optional.ofNullable(transferProcessStore.findById(edr.getId())) - .orElseGet(() -> transferProcessStore.findForCorrelationId(edr.getId())); - - if (transferProcess != null) { - String contractNegotiationId; - var contractNegotiation = agreementService.findNegotiation(transferProcess.getContractId()); - if (contractNegotiation != null) { - contractNegotiationId = contractNegotiation.getId(); - } else { - var msg = format("Contract negotiation for agreement with id: %s is missing.", transferProcess.getContractId()); - monitor.warning(msg); - return Result.failure(msg); - } - var expirationTime = extractExpirationTime(edr); - - if (expirationTime.failed()) { - return expirationTime.mapTo(); - } - var cacheEntry = EndpointDataReferenceEntry.Builder.newInstance() - .transferProcessId(transferProcess.getId()) - .assetId(transferProcess.getAssetId()) - .agreementId(transferProcess.getContractId()) - .providerId(contractNegotiation.getCounterPartyId()) - .state(EndpointDataReferenceEntryStates.NEGOTIATED.code()) - .expirationTimestamp(expirationTime.getContent()) - .contractNegotiationId(contractNegotiationId) - .build(); - - cleanOldEdr(transferProcess.getAssetId(), transferProcess.getContractId()); - edrCache.save(cacheEntry, edr); - - return Result.success(); - } else { - return Result.failure(format("Failed to find a transfer process with correlation ID %s", edr.getId())); - } - }); - - } - - private void stopEdrNegotiation(String assetId, String agreementId, String errorDetail) { - var querySpec = QuerySpec.Builder.newInstance() - .filter(fieldFilter("agreementId", agreementId)) - .filter(fieldFilter("assetId", assetId)) - .filter(fieldFilter("state", REFRESHING.code())) - .build(); - - edrCache.queryForEntries(querySpec).forEach((entry -> { - monitor.debug(format("Transitioning EDR to Error Refreshing for transfer process %s", entry.getTransferProcessId())); - entry.setErrorDetail(errorDetail); - entry.transitionError(); - edrCache.update(entry); - })); - } - - private void cleanOldEdr(String assetId, String agreementId) { - var querySpec = QuerySpec.Builder.newInstance() - .filter(fieldFilter("agreementId", agreementId)) - .filter(fieldFilter("assetId", assetId)) - .build(); - - edrCache.queryForEntries(querySpec).forEach((entry -> { - monitor.debug(format("Expiring EDR for transfer process %s", entry.getTransferProcessId())); - entry.transitionToExpired(); - edrCache.update(entry); - - var transferProcess = transferProcessStore.findById(entry.getTransferProcessId()); - - if (transferProcess != null && transferProcess.canBeTerminated()) { - transferProcess.transitionTerminating(); - transferProcessStore.save(transferProcess); - } else { - monitor.info(format("Cannot terminate transfer process with id: %s", entry.getTransferProcessId())); - } - - })); - } - - private Result extractExpirationTime(EndpointDataReference edr) { - try { - if (edr.getAuthCode() != null) { - var jwt = SignedJWT.parse(edr.getAuthCode()); - var expirationTime = jwt.getJWTClaimsSet().getExpirationTime(); - if (expirationTime != null) { - return Result.success(expirationTime - .toInstant() - .atOffset(ZoneOffset.UTC) - .toInstant().toEpochMilli()); - } - } - } catch (ParseException e) { - return Result.failure(format("Failed to parts JWT token for edr %s", edr.getId())); - } - return Result.success(0L); - } - - private Criterion fieldFilter(String field, Object value) { - return Criterion.Builder.newInstance() - .operandLeft(field) - .operator("=") - .operandRight(value) - .build(); - } -} diff --git a/edc-extensions/edr/edr-callback/src/test/java/org/eclipse/tractusx/edc/callback/LocalCallbackExtensionTest.java b/edc-extensions/edr/edr-callback/src/test/java/org/eclipse/tractusx/edc/callback/LocalCallbackExtensionTest.java index 8fb31d81c..d0ba7ce27 100644 --- a/edc-extensions/edr/edr-callback/src/test/java/org/eclipse/tractusx/edc/callback/LocalCallbackExtensionTest.java +++ b/edc-extensions/edr/edr-callback/src/test/java/org/eclipse/tractusx/edc/callback/LocalCallbackExtensionTest.java @@ -66,10 +66,10 @@ void shouldInitializeTheExtension(ServiceExtensionContext context, LocalCallback assertThat(resolver.resolve("test")).isNull(); var callbackArgumentCaptor = ArgumentCaptor.forClass(InProcessCallback.class); - verify(inProcessCallbackRegistry, times(2)).registerHandler(callbackArgumentCaptor.capture()); + verify(inProcessCallbackRegistry, times(1)).registerHandler(callbackArgumentCaptor.capture()); assertThat(callbackArgumentCaptor.getAllValues()) .flatExtracting(Object::getClass) - .containsExactly(ContractNegotiationCallback.class, TransferProcessLocalCallback.class); + .containsExactly(ContractNegotiationCallback.class); } } diff --git a/edc-extensions/edr/edr-callback/src/test/java/org/eclipse/tractusx/edc/callback/TestFunctions.java b/edc-extensions/edr/edr-callback/src/test/java/org/eclipse/tractusx/edc/callback/TestFunctions.java index 4a46e31b0..724d52dfd 100644 --- a/edc-extensions/edr/edr-callback/src/test/java/org/eclipse/tractusx/edc/callback/TestFunctions.java +++ b/edc-extensions/edr/edr-callback/src/test/java/org/eclipse/tractusx/edc/callback/TestFunctions.java @@ -37,7 +37,6 @@ import org.eclipse.edc.spi.types.domain.DataAddress; import org.eclipse.edc.spi.types.domain.agreement.ContractAgreement; import org.eclipse.edc.spi.types.domain.callback.CallbackAddress; -import org.eclipse.edc.spi.types.domain.edr.EndpointDataReference; import java.time.Instant; import java.util.Date; @@ -116,16 +115,6 @@ public static TransferProcessTerminated getTransferTerminatedEvent(String transf .build(); } - public static EndpointDataReference getEdr() { - return EndpointDataReference.Builder.newInstance() - .id("dataRequestId") - .contractId("test-contract-id") - .authCode(createToken()) - .authKey("authKey") - .endpoint("http://endpoint") - .build(); - } - public static CallbackEventRemoteMessage remoteMessage(T event) { var callback = CallbackAddress.Builder.newInstance() .events(Set.of("test")) diff --git a/edc-extensions/edr/edr-callback/src/test/java/org/eclipse/tractusx/edc/callback/TransferProcessLocalCallbackTest.java b/edc-extensions/edr/edr-callback/src/test/java/org/eclipse/tractusx/edc/callback/TransferProcessLocalCallbackTest.java deleted file mode 100644 index ad9a3f318..000000000 --- a/edc-extensions/edr/edr-callback/src/test/java/org/eclipse/tractusx/edc/callback/TransferProcessLocalCallbackTest.java +++ /dev/null @@ -1,263 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.callback; - -import org.eclipse.edc.connector.contract.spi.types.negotiation.ContractNegotiation; -import org.eclipse.edc.connector.spi.contractagreement.ContractAgreementService; -import org.eclipse.edc.connector.transfer.spi.event.TransferProcessCompleted; -import org.eclipse.edc.connector.transfer.spi.event.TransferProcessDeprovisioned; -import org.eclipse.edc.connector.transfer.spi.event.TransferProcessEvent; -import org.eclipse.edc.connector.transfer.spi.event.TransferProcessProvisioned; -import org.eclipse.edc.connector.transfer.spi.event.TransferProcessRequested; -import org.eclipse.edc.connector.transfer.spi.store.TransferProcessStore; -import org.eclipse.edc.connector.transfer.spi.types.TransferProcess; -import org.eclipse.edc.spi.monitor.Monitor; -import org.eclipse.edc.spi.result.Result; -import org.eclipse.edc.spi.types.domain.DataAddress; -import org.eclipse.edc.spi.types.domain.callback.CallbackAddress; -import org.eclipse.edc.spi.types.domain.edr.EndpointDataReference; -import org.eclipse.edc.transaction.spi.NoopTransactionContext; -import org.eclipse.edc.transaction.spi.TransactionContext; -import org.eclipse.edc.transform.spi.TypeTransformerRegistry; -import org.eclipse.tractusx.edc.edr.spi.store.EndpointDataReferenceCache; -import org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntry; -import org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntryStates; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtensionContext; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.Arguments; -import org.junit.jupiter.params.provider.ArgumentsProvider; -import org.junit.jupiter.params.provider.ArgumentsSource; -import org.mockito.ArgumentCaptor; - -import java.util.List; -import java.util.Set; -import java.util.UUID; -import java.util.stream.Stream; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.eclipse.edc.spi.types.domain.edr.EndpointDataReference.EDR_SIMPLE_TYPE; -import static org.eclipse.tractusx.edc.callback.TestFunctions.getEdr; -import static org.eclipse.tractusx.edc.callback.TestFunctions.getTransferProcessStartedEvent; -import static org.eclipse.tractusx.edc.callback.TestFunctions.getTransferTerminatedEvent; -import static org.eclipse.tractusx.edc.callback.TestFunctions.remoteMessage; -import static org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntryStates.REFRESHING; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.argThat; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoInteractions; -import static org.mockito.Mockito.when; - - -public class TransferProcessLocalCallbackTest { - - TransferProcessStore transferProcessStore = mock(); - EndpointDataReferenceCache edrCache = mock(); - - TransactionContext transactionContext = new NoopTransactionContext(); - - TransferProcessLocalCallback callback; - - ContractAgreementService agreementService = mock(); - - TypeTransformerRegistry transformerRegistry = mock(TypeTransformerRegistry.class); - - - @BeforeEach - void setup() { - callback = new TransferProcessLocalCallback(edrCache, transferProcessStore, agreementService, transformerRegistry, transactionContext, mock(Monitor.class)); - } - - @Test - void invoke_shouldStoreTheEdrInCache_whenDataAddressIsPresent() { - - var transferProcessId = "transferProcessId"; - var assetId = "assetId"; - var contractId = "contractId"; - - - var edr = getEdr(); - - - var transferProcess = TransferProcess.Builder.newInstance() - .id(transferProcessId) - .assetId(assetId) - .contractId(contractId) - .dataDestination(DataAddress.Builder.newInstance().type("HttpProxy").build()) - .build(); - - var edrEntry = EndpointDataReferenceEntry.Builder.newInstance() - .agreementId(contractId) - .transferProcessId(transferProcessId) - .assetId(assetId) - .build(); - - var negotiation = ContractNegotiation.Builder.newInstance() - .id(contractId) - .counterPartyId("providerId") - .counterPartyAddress("http://test") - .protocol("protocol") - .build(); - - when(transformerRegistry.transform(any(DataAddress.class), eq(EndpointDataReference.class))).thenReturn(Result.success(edr)); - when(transferProcessStore.findForCorrelationId(edr.getId())).thenReturn(transferProcess); - when(transferProcessStore.findById(transferProcessId)).thenReturn(transferProcess); - when(agreementService.findNegotiation(contractId)).thenReturn(negotiation); - when(edrCache.queryForEntries(any())).thenReturn(Stream.of(edrEntry)); - - - var event = getTransferProcessStartedEvent(DataAddress.Builder.newInstance().type(EDR_SIMPLE_TYPE).build()); - - var cacheEntryCaptor = ArgumentCaptor.forClass(EndpointDataReferenceEntry.class); - var edrCaptor = ArgumentCaptor.forClass(EndpointDataReference.class); - var message = remoteMessage(event); - - var result = callback.invoke(message); - assertThat(result.succeeded()).isTrue(); - - verify(edrCache).save(cacheEntryCaptor.capture(), edrCaptor.capture()); - verify(edrCache).update(argThat(entry -> entry.getState() == EndpointDataReferenceEntryStates.EXPIRED.code())); - - assertThat(edrCaptor.getValue()).usingRecursiveComparison().isEqualTo(edr); - - } - - @Test - void invoke_shouldNotFail_whenDataAddressIsAbsent() { - - var event = getTransferProcessStartedEvent(); - var message = remoteMessage(event); - - var result = callback.invoke(message); - assertThat(result.succeeded()).isTrue(); - - verifyNoInteractions(edrCache); - verifyNoInteractions(transferProcessStore); - } - - @Test - void invoke_shouldNotFail_whenTransferProcessNotFound() { - - var transferProcessId = "transferProcessId"; - - var edr = getEdr(); - - when(transformerRegistry.transform(any(DataAddress.class), eq(EndpointDataReference.class))).thenReturn(Result.success(edr)); - - when(transferProcessStore.findForCorrelationId(edr.getId())).thenReturn(null); - - when(transferProcessStore.findById(transferProcessId)).thenReturn(null); - - var event = getTransferProcessStartedEvent(DataAddress.Builder.newInstance().type(EDR_SIMPLE_TYPE).build()); - var message = remoteMessage(event); - - var result = callback.invoke(message); - assertThat(result.succeeded()).isFalse(); - - verifyNoInteractions(edrCache); - } - - @Test - void invoke_shouldFail_withInvalidDataAddress() { - - var event = getTransferProcessStartedEvent(DataAddress.Builder.newInstance().type("HttpProxy").build()); - - when(transformerRegistry.transform(any(DataAddress.class), eq(EndpointDataReference.class))) - .thenReturn(Result.failure("failure")); - - var message = remoteMessage(event); - - var result = callback.invoke(message); - assertThat(result.failed()).isTrue(); - - verifyNoInteractions(edrCache); - verifyNoInteractions(transferProcessStore); - } - - @Test - void invoke_shouldStopEdrNegotiation_whenTerminatedMessageReceived() { - - var transferProcessId = "transferProcessId"; - var assetId = "assetId"; - var contractId = "contractId"; - var edr = getEdr(); - - var transferProcess = TransferProcess.Builder.newInstance() - .id(transferProcessId) - .assetId(assetId) - .contractId(contractId) - .dataDestination(DataAddress.Builder.newInstance().type("HttpProxy").build()) - .build(); - - var edrEntry = EndpointDataReferenceEntry.Builder.newInstance() - .agreementId(contractId) - .transferProcessId(transferProcessId) - .assetId(assetId) - .state(REFRESHING.code()) - .build(); - - when(transferProcessStore.findById(transferProcessId)).thenReturn(transferProcess); - when(edrCache.queryForEntries(any())).thenReturn(Stream.of(edrEntry)); - - var event = getTransferTerminatedEvent(transferProcessId, "Failure"); - var message = remoteMessage(event); - - var result = callback.invoke(message); - assertThat(result.succeeded()).isTrue(); - - verify(edrCache).update(argThat(entry -> entry.getState() == EndpointDataReferenceEntryStates.ERROR.code())); - - } - - @ParameterizedTest - @ArgumentsSource(EventInstances.class) - void invoke_shouldIgnoreOtherEvents(TransferProcessEvent event) { - var message = remoteMessage(event); - var result = callback.invoke(message); - - assertThat(result.succeeded()).isTrue(); - - verifyNoInteractions(edrCache); - } - - private static class EventInstances implements ArgumentsProvider { - - @Override - public Stream provideArguments(ExtensionContext context) { - return Stream.of( - baseBuilder(TransferProcessRequested.Builder.newInstance()).build(), - baseBuilder(TransferProcessProvisioned.Builder.newInstance()).build(), - baseBuilder(TransferProcessCompleted.Builder.newInstance()).build(), - baseBuilder(TransferProcessDeprovisioned.Builder.newInstance()).build() - ).map(Arguments::of); - - } - - private > B baseBuilder(B builder) { - var callbacks = List.of(CallbackAddress.Builder.newInstance().uri("http://local").events(Set.of("test")).build()); - return builder - .transferProcessId(UUID.randomUUID().toString()) - .callbackAddresses(callbacks); - } - } -} diff --git a/edc-extensions/tokenrefresh-handler/src/main/java/org/eclipse/tractusx/edc/common/tokenrefresh/TokenRefreshHandlerImpl.java b/edc-extensions/tokenrefresh-handler/src/main/java/org/eclipse/tractusx/edc/common/tokenrefresh/TokenRefreshHandlerImpl.java index 819574061..329827d2c 100644 --- a/edc-extensions/tokenrefresh-handler/src/main/java/org/eclipse/tractusx/edc/common/tokenrefresh/TokenRefreshHandlerImpl.java +++ b/edc-extensions/tokenrefresh-handler/src/main/java/org/eclipse/tractusx/edc/common/tokenrefresh/TokenRefreshHandlerImpl.java @@ -32,7 +32,6 @@ import org.eclipse.edc.spi.result.ServiceResult; import org.eclipse.edc.spi.result.StoreResult; import org.eclipse.edc.spi.types.domain.DataAddress; -import org.eclipse.edc.spi.types.domain.edr.EndpointDataReference; import org.eclipse.edc.util.string.StringUtils; import org.eclipse.tractusx.edc.spi.tokenrefresh.common.TokenRefreshHandler; import org.eclipse.tractusx.edc.spi.tokenrefresh.dataplane.model.TokenResponse; @@ -63,7 +62,7 @@ public class TokenRefreshHandlerImpl implements TokenRefreshHandler { /** * Creates a new TokenRefreshHandler * - * @param edrCache a persistent storage where {@link EndpointDataReference} objects are stored. + * @param edrCache a persistent storage where {@link DataAddress} objects are stored. * @param httpClient needed to make the actual refresh call against the refresh endpoint * @param ownDid the DID of this connector * @param secureTokenService Service to generate the authentication token @@ -125,19 +124,17 @@ public ServiceResult refreshToken(String tokenId, DataAddress edr) } return executeRequest(result.getContent()) - .compose(tr -> update(tokenId, edr, tr)); + .map(tr -> createNewEdr(edr, tr)); } - private ServiceResult update(String id, DataAddress oldEdr, TokenResponse tokenResponse) { - //todo: create new DataAddress out of the oldEdr, update refresh token, store and return - var newEdr = DataAddress.Builder.newInstance() + private DataAddress createNewEdr(DataAddress oldEdr, TokenResponse tokenResponse) { + return DataAddress.Builder.newInstance() .type(oldEdr.getType()) .properties(oldEdr.getProperties()) .property(EDR_PROPERTY_AUTHORIZATION, tokenResponse.accessToken()) .property(EDR_PROPERTY_REFRESH_TOKEN, tokenResponse.refreshToken()) .property(EDR_PROPERTY_EXPIRES_IN, String.valueOf(tokenResponse.expiresInSeconds())) .build(); - return ServiceResult.from(edrCache.put(id, newEdr)).map(u -> newEdr); } private ServiceResult executeRequest(Request tokenRefreshRequest) { diff --git a/edc-extensions/tokenrefresh-handler/src/test/java/org/eclipse/tractusx/edc/common/tokenrefresh/TokenRefreshHandlerImplTest.java b/edc-extensions/tokenrefresh-handler/src/test/java/org/eclipse/tractusx/edc/common/tokenrefresh/TokenRefreshHandlerImplTest.java index 83fb5341a..f0e603450 100644 --- a/edc-extensions/tokenrefresh-handler/src/test/java/org/eclipse/tractusx/edc/common/tokenrefresh/TokenRefreshHandlerImplTest.java +++ b/edc-extensions/tokenrefresh-handler/src/test/java/org/eclipse/tractusx/edc/common/tokenrefresh/TokenRefreshHandlerImplTest.java @@ -103,7 +103,6 @@ void setup() { @Test void refresh_validateCorrectRequest() throws IOException { when(edrCache.get(anyString())).thenReturn(StoreResult.success(createEdr().build())); - when(edrCache.put(any(), any())).thenReturn(StoreResult.success()); when(mockedTokenService.createToken(anyMap(), isNull())).thenReturn(Result.success(TokenRepresentation.Builder.newInstance().token("foo-auth-token").build())); var tokenResponse = new TokenResponse("new-access-token", "new-refresh-token", 60 * 5L, "bearer"); var successResponse = createResponse(tokenResponse, 200, ""); diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/DataWiper.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/DataWiper.java index 553a956d9..dc7390bee 100644 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/DataWiper.java +++ b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/DataWiper.java @@ -21,10 +21,10 @@ import org.eclipse.edc.connector.contract.spi.offer.store.ContractDefinitionStore; import org.eclipse.edc.connector.policy.spi.store.PolicyDefinitionStore; +import org.eclipse.edc.edr.spi.store.EndpointDataReferenceStore; import org.eclipse.edc.spi.asset.AssetIndex; import org.eclipse.edc.spi.query.QuerySpec; import org.eclipse.edc.spi.system.ServiceExtensionContext; -import org.eclipse.tractusx.edc.edr.spi.store.EndpointDataReferenceCache; import org.eclipse.tractusx.edc.validation.businesspartner.spi.BusinessPartnerStore; import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.PLATO_BPN; @@ -72,10 +72,10 @@ public void clearAssetIndex() { } public void clearEdrCache() { - var edrCache = context.getService(EndpointDataReferenceCache.class); - edrCache.queryForEntries(QuerySpec.max()).forEach(entry -> { + var edrCache = context.getService(EndpointDataReferenceStore.class); + edrCache.query(QuerySpec.max()).getContent().forEach(entry -> { try { - edrCache.deleteByTransferProcessId(entry.getTransferProcessId()); + edrCache.delete(entry.getTransferProcessId()); } catch (Exception e) { context.getMonitor().warning("Failed to clean up the cache", e); } diff --git a/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/ParticipantDataApi.java b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/ParticipantDataApi.java index a7efd4de6..68b6049f7 100644 --- a/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/ParticipantDataApi.java +++ b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/ParticipantDataApi.java @@ -20,7 +20,7 @@ package org.eclipse.tractusx.edc.tests; import jakarta.json.JsonObject; -import org.eclipse.edc.spi.types.domain.edr.EndpointDataReference; +import org.eclipse.edc.spi.types.domain.DataAddress; import java.util.Map; @@ -34,7 +34,7 @@ public class ParticipantDataApi { /** - * Pull the data with an {@link EndpointDataReference} + * Pull the data with an {@link DataAddress} * * @param edr The edr * @param queryParams additional params diff --git a/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/runtimes/DataWiper.java b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/runtimes/DataWiper.java index c97acd08f..3d2d88ded 100644 --- a/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/runtimes/DataWiper.java +++ b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/runtimes/DataWiper.java @@ -21,10 +21,10 @@ import org.eclipse.edc.connector.contract.spi.offer.store.ContractDefinitionStore; import org.eclipse.edc.connector.policy.spi.store.PolicyDefinitionStore; +import org.eclipse.edc.edr.spi.store.EndpointDataReferenceStore; import org.eclipse.edc.spi.asset.AssetIndex; import org.eclipse.edc.spi.query.QuerySpec; import org.eclipse.edc.spi.system.ServiceExtensionContext; -import org.eclipse.tractusx.edc.edr.spi.store.EndpointDataReferenceCache; import org.eclipse.tractusx.edc.validation.businesspartner.spi.BusinessPartnerStore; import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.PLATO_BPN; @@ -72,10 +72,10 @@ public void clearAssetIndex() { } public void clearEdrCache() { - var edrCache = context.getService(EndpointDataReferenceCache.class); - edrCache.queryForEntries(QuerySpec.max()).forEach(entry -> { + var edrCache = context.getService(EndpointDataReferenceStore.class); + edrCache.query(QuerySpec.max()).getContent().forEach(entry -> { try { - edrCache.deleteByTransferProcessId(entry.getTransferProcessId()); + edrCache.delete(entry.getTransferProcessId()); } catch (Exception e) { context.getMonitor().warning("Failed to clean up the cache", e); } diff --git a/edc-tests/edc-dataplane/edc-dataplane-tokenrefresh-tests/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/e2e/DataPlaneTokenRefreshEndToEndTest.java b/edc-tests/edc-dataplane/edc-dataplane-tokenrefresh-tests/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/e2e/DataPlaneTokenRefreshEndToEndTest.java index 8bb6cf0eb..c06cea994 100644 --- a/edc-tests/edc-dataplane/edc-dataplane-tokenrefresh-tests/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/e2e/DataPlaneTokenRefreshEndToEndTest.java +++ b/edc-tests/edc-dataplane/edc-dataplane-tokenrefresh-tests/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/e2e/DataPlaneTokenRefreshEndToEndTest.java @@ -62,6 +62,7 @@ public class DataPlaneTokenRefreshEndToEndTest { public static final String CONSUMER_DID = "did:web:alice"; public static final String PROVIDER_DID = "did:web:bob"; public static final String PROVIDER_KEY_ID = PROVIDER_DID + "#key-1"; + public static final String PROVIDER_KEY_ID_PUBLIC = PROVIDER_DID + "#key-1-public"; public static final String CONSUMER_KEY_ID = CONSUMER_DID + "#cons-1"; private static final RuntimeConfig RUNTIME_CONFIG = new RuntimeConfig(); @RegisterExtension @@ -69,7 +70,7 @@ public class DataPlaneTokenRefreshEndToEndTest { ":edc-tests:runtime:dataplane-cloud", "Token-Refresh-Dataplane", with(RUNTIME_CONFIG.baseConfig(), Map.of("edc.transfer.proxy.token.signer.privatekey.alias", PROVIDER_KEY_ID, - "edc.transfer.proxy.token.verifier.publickey.alias", PROVIDER_KEY_ID)) + "edc.transfer.proxy.token.verifier.publickey.alias", PROVIDER_KEY_ID_PUBLIC)) ); private ECKey providerKey; private ECKey consumerKey; @@ -317,6 +318,7 @@ void refresh_invalidAuthenticationToken_missingAudience() { private void prepareDataplaneRuntime() { var vault = DATAPLANE_RUNTIME.getContext().getService(Vault.class); vault.storeSecret(PROVIDER_KEY_ID, providerKey.toJSONString()); + vault.storeSecret(PROVIDER_KEY_ID_PUBLIC, providerKey.toPublicJWK().toJSONString()); } private String createAuthToken(String accessToken, ECKey signerKey) { diff --git a/samples/multi-tenancy/build.gradle.kts b/samples/multi-tenancy/build.gradle.kts index e7414bbd8..a270267dd 100644 --- a/samples/multi-tenancy/build.gradle.kts +++ b/samples/multi-tenancy/build.gradle.kts @@ -34,6 +34,7 @@ dependencies { // the token refresh extension is not needed exclude(module = "tx-iatp-sts-dim") exclude(module = "tokenrefresh-handler") + exclude(module = "edr-core") exclude(module = "edr-api-v2") exclude(module = "edr-callback") } diff --git a/settings.gradle.kts b/settings.gradle.kts index d582762f0..907830c26 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -27,7 +27,6 @@ include(":spi:tokenrefresh-spi") // core modules -include(":core:edr-cache-core") include(":core:edr-core") include(":core:json-ld-core") include(":core:core-utils") diff --git a/spi/edr-spi/build.gradle.kts b/spi/edr-spi/build.gradle.kts index 2ac7abdf0..608bf4329 100644 --- a/spi/edr-spi/build.gradle.kts +++ b/spi/edr-spi/build.gradle.kts @@ -25,7 +25,7 @@ plugins { dependencies { implementation(project(":spi:core-spi")) implementation(libs.edc.spi.core) - implementation(libs.edc.spi.contract) + implementation(libs.edc.spi.edrstore) testFixturesImplementation(libs.edc.junit) testFixturesImplementation(libs.junit.jupiter.api) diff --git a/spi/edr-spi/src/main/java/org/eclipse/tractusx/edc/edr/spi/EdrManager.java b/spi/edr-spi/src/main/java/org/eclipse/tractusx/edc/edr/spi/EdrManager.java deleted file mode 100644 index 51960cefb..000000000 --- a/spi/edr-spi/src/main/java/org/eclipse/tractusx/edc/edr/spi/EdrManager.java +++ /dev/null @@ -1,42 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.edr.spi; - -import org.eclipse.edc.connector.contract.spi.types.negotiation.ContractNegotiation; -import org.eclipse.edc.runtime.metamodel.annotation.ExtensionPoint; -import org.eclipse.edc.spi.response.StatusResult; -import org.eclipse.tractusx.edc.edr.spi.types.NegotiateEdrRequest; - -/** - * Manages EDRs lifecycle - */ -@ExtensionPoint -public interface EdrManager { - - /** - * Initiated a new EDR negotiation. An EDR negotiation consists on two sub-processes. Contract negotiation and transfer - * request. Once the latter is completed the returned EDR from the provided will be store in the EDR cache for consumption - * - * @param request Request Data - * @return The contract negotiation - */ - StatusResult initiateEdrNegotiation(NegotiateEdrRequest request); - -} diff --git a/spi/edr-spi/src/main/java/org/eclipse/tractusx/edc/edr/spi/service/EdrService.java b/spi/edr-spi/src/main/java/org/eclipse/tractusx/edc/edr/spi/service/EdrService.java index 25417637c..332329415 100644 --- a/spi/edr-spi/src/main/java/org/eclipse/tractusx/edc/edr/spi/service/EdrService.java +++ b/spi/edr-spi/src/main/java/org/eclipse/tractusx/edc/edr/spi/service/EdrService.java @@ -19,41 +19,38 @@ package org.eclipse.tractusx.edc.edr.spi.service; -import org.eclipse.edc.connector.contract.spi.types.negotiation.ContractNegotiation; +import org.eclipse.edc.edr.spi.types.EndpointDataReferenceEntry; import org.eclipse.edc.runtime.metamodel.annotation.ExtensionPoint; import org.eclipse.edc.spi.query.QuerySpec; import org.eclipse.edc.spi.result.ServiceResult; -import org.eclipse.edc.spi.types.domain.edr.EndpointDataReference; -import org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntry; -import org.eclipse.tractusx.edc.edr.spi.types.NegotiateEdrRequest; +import org.eclipse.edc.spi.types.domain.DataAddress; +import org.eclipse.tractusx.edc.edr.spi.types.RefreshMode; import java.util.List; /** - * Service for opening a transfer process. + * Mediate the access to the {@link EndpointDataReferenceEntry} and cached {@link DataAddress} EDRs. */ @ExtensionPoint public interface EdrService { + /** - * Open a transfer process by firing a contract negotiation. Implementors should fire a contract negotiation - * and automatically fire a transfer process once the agreement has been reached. + * Resolve a {@link DataAddress} EDR associated with the transfer process. The token will be refreshed + * accordingly the {@link RefreshMode} * - * @param request The open request - * @return The result containing the contract negotiation id + * @param transferProcessId The id of the transfer process + * @param mode The {@link RefreshMode} + * @return If the token in {@link DataAddress} is expired a refresh one */ - ServiceResult initiateEdrNegotiation(NegotiateEdrRequest request); + ServiceResult resolveByTransferProcess(String transferProcessId, RefreshMode mode); /** - * Return a {@link EndpointDataReference} associated with the transferProcessId in input + * Search for {@link EndpointDataReferenceEntry} * - * @param transferProcessId The transferProcessId - * @return The result containing the {@link EndpointDataReference} + * @param query The {@link QuerySpec} + * @return The list of matching {@link EndpointDataReferenceEntry} if success, failure otherwise */ - ServiceResult findByTransferProcessId(String transferProcessId); - - ServiceResult> findBy(QuerySpec querySpec); - - ServiceResult deleteByTransferProcessId(String transferProcessId); + ServiceResult> query(QuerySpec query); } diff --git a/spi/edr-spi/src/main/java/org/eclipse/tractusx/edc/edr/spi/store/EndpointDataReferenceCache.java b/spi/edr-spi/src/main/java/org/eclipse/tractusx/edc/edr/spi/store/EndpointDataReferenceCache.java deleted file mode 100644 index f1f4496f5..000000000 --- a/spi/edr-spi/src/main/java/org/eclipse/tractusx/edc/edr/spi/store/EndpointDataReferenceCache.java +++ /dev/null @@ -1,92 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.edr.spi.store; - -import org.eclipse.edc.spi.persistence.StateEntityStore; -import org.eclipse.edc.spi.query.QuerySpec; -import org.eclipse.edc.spi.result.StoreResult; -import org.eclipse.edc.spi.types.domain.edr.EndpointDataReference; -import org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntry; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.List; -import java.util.stream.Stream; - -import static org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntryStates.NEGOTIATED; -import static org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntryStates.REFRESHING; - -/** - * Caches and resolves {@link EndpointDataReference}s - */ -public interface EndpointDataReferenceCache extends StateEntityStore { - - /** - * Resolves an {@link EndpointDataReference} for the transfer process, returning null if one does not exist. - */ - @Nullable - EndpointDataReference resolveReference(String transferProcessId); - - /** - * Resolves an {@link EndpointDataReference} for the transfer process, returning null if one does not exist. - */ - @Nullable - StoreResult findByIdAndLease(String transferProcessId); - - /** - * Resolves the {@link EndpointDataReference}s for the asset. - */ - @NotNull - List referencesForAsset(String assetId, String providerId); - - - /** - * Filter the {@link EndpointDataReferenceEntry} that are in negotiated or refreshing state - * - * @param entry The {@link EndpointDataReferenceEntry} - */ - default boolean filterActive(EndpointDataReferenceEntry entry) { - return entry.getState() == NEGOTIATED.code() || entry.getState() == REFRESHING.code(); - } - - /** - * Returns all the EDR entries in the store that are covered by a given {@link QuerySpec}. - */ - - Stream queryForEntries(QuerySpec spec); - - /** - * Saves an {@link EndpointDataReference} to the cache using upsert semantics. - */ - void save(EndpointDataReferenceEntry entry, EndpointDataReference edr); - - - /** - * Saves an {@link EndpointDataReference} to the cache using upsert semantics. - */ - void update(EndpointDataReferenceEntry entry); - - /** - * Deletes stored endpoint reference data associated with the given transfer process. - */ - StoreResult deleteByTransferProcessId(String id); - - -} diff --git a/spi/edr-spi/src/main/java/org/eclipse/tractusx/edc/edr/spi/types/EndpointDataReferenceEntry.java b/spi/edr-spi/src/main/java/org/eclipse/tractusx/edc/edr/spi/types/EndpointDataReferenceEntry.java deleted file mode 100644 index 3c3736867..000000000 --- a/spi/edr-spi/src/main/java/org/eclipse/tractusx/edc/edr/spi/types/EndpointDataReferenceEntry.java +++ /dev/null @@ -1,235 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.edr.spi.types; - -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonIgnore; -import com.fasterxml.jackson.databind.annotation.JsonDeserialize; -import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder; -import org.eclipse.edc.spi.entity.StatefulEntity; -import org.eclipse.edc.spi.types.domain.edr.EndpointDataReference; - -import java.util.Arrays; -import java.util.Objects; -import java.util.function.Predicate; - -import static java.lang.String.format; -import static java.util.Objects.requireNonNull; -import static org.eclipse.edc.spi.CoreConstants.EDC_NAMESPACE; -import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.TX_NAMESPACE; -import static org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntryStates.DELETING; -import static org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntryStates.ERROR; -import static org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntryStates.EXPIRED; -import static org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntryStates.NEGOTIATED; -import static org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntryStates.REFRESHING; - -/** - * An entry in the cache for an {@link EndpointDataReference}. - */ -@JsonDeserialize(builder = EndpointDataReferenceEntry.Builder.class) -public class EndpointDataReferenceEntry extends StatefulEntity { - - public static final String SIMPLE_TYPE = "EndpointDataReferenceEntry"; - public static final String EDR_ENTRY_TYPE = TX_NAMESPACE + SIMPLE_TYPE; - public static final String EDR_ENTRY_STATE = TX_NAMESPACE + "edrState"; - public static final String EDR_ENTRY_EXPIRATION_DATE = TX_NAMESPACE + "expirationDate"; - public static final String ASSET_ID = "assetId"; - public static final String EDR_ENTRY_ASSET_ID = EDC_NAMESPACE + ASSET_ID; - public static final String AGREEMENT_ID = "agreementId"; - public static final String EDR_ENTRY_AGREEMENT_ID = EDC_NAMESPACE + AGREEMENT_ID; - public static final String CONTRACT_NEGOTIATION_ID = "contractNegotiationId"; - public static final String EDR_ENTRY_CONTRACT_NEGOTIATION_ID = EDC_NAMESPACE + CONTRACT_NEGOTIATION_ID; - - public static final String TRANSFER_PROCESS_ID = "transferProcessId"; - public static final String EDR_ENTRY_TRANSFER_PROCESS_ID = EDC_NAMESPACE + TRANSFER_PROCESS_ID; - public static final String PROVIDER_ID = "providerId"; - public static final String EDR_ENTRY_PROVIDER_ID = EDC_NAMESPACE + PROVIDER_ID; - private String assetId; - private String agreementId; - private String transferProcessId; - - private String contractNegotiationId; - - private String providerId; - - private Long expirationTimestamp; - - private EndpointDataReferenceEntry() { - state = NEGOTIATED.code(); - } - - @Override - public String getId() { - return getTransferProcessId(); - } - - - @Override - public EndpointDataReferenceEntry copy() { - var builder = Builder.newInstance() - .transferProcessId(transferProcessId) - .agreementId(agreementId) - .assetId(assetId) - .providerId(providerId) - .contractNegotiationId(contractNegotiationId) - .expirationTimestamp(expirationTimestamp); - return copy(builder); - } - - @Override - public String stateAsString() { - return EndpointDataReferenceEntryStates.from(state).toString(); - } - - @JsonIgnore - public String getEdrState() { - return EndpointDataReferenceEntryStates.from(getState()).name(); - } - - public String getAssetId() { - return assetId; - } - - public String getAgreementId() { - return agreementId; - } - - public String getTransferProcessId() { - return transferProcessId; - } - - public String getProviderId() { - return providerId; - } - - public String getContractNegotiationId() { - return contractNegotiationId; - } - - public Long getExpirationTimestamp() { - return expirationTimestamp; - } - - @Override - public int hashCode() { - return Objects.hash(assetId, agreementId, transferProcessId); - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - var that = (EndpointDataReferenceEntry) o; - - return transferProcessId.equals(that.transferProcessId); - } - - public void transitionToRefreshing() { - transition(REFRESHING, REFRESHING, NEGOTIATED); - } - - public void transitionToNegotiated() { - transition(NEGOTIATED, NEGOTIATED, REFRESHING); - } - - public void transitionError() { - transition(ERROR, REFRESHING, NEGOTIATED); - } - - public void transitionToExpired() { - transition(EXPIRED, EXPIRED, NEGOTIATED, REFRESHING); - } - - public void transitionToDeleting() { - transition(DELETING, DELETING, EXPIRED); - } - - private void transition(EndpointDataReferenceEntryStates end, Predicate canTransitTo) { - if (!canTransitTo.test(EndpointDataReferenceEntryStates.from(state))) { - throw new IllegalStateException(format("Cannot transition from state %s to %s", EndpointDataReferenceEntryStates.from(state), EndpointDataReferenceEntryStates.from(end.code()))); - } - transitionTo(end.code()); - } - - private void transition(EndpointDataReferenceEntryStates end, EndpointDataReferenceEntryStates... starts) { - transition(end, (state) -> Arrays.stream(starts).anyMatch(s -> s == state)); - } - - - @JsonPOJOBuilder(withPrefix = "") - public static class Builder extends StatefulEntity.Builder { - - private Builder() { - super(new EndpointDataReferenceEntry()); - } - - @JsonCreator - public static Builder newInstance() { - return new Builder(); - } - - public Builder assetId(String assetId) { - entity.assetId = assetId; - return this; - } - - public Builder agreementId(String agreementId) { - entity.agreementId = agreementId; - return this; - } - - public Builder transferProcessId(String transferProcessId) { - entity.transferProcessId = transferProcessId; - entity.id = transferProcessId; - return this; - } - - public Builder providerId(String providerId) { - entity.providerId = providerId; - return this; - } - - public Builder contractNegotiationId(String contractNegotiationId) { - entity.contractNegotiationId = contractNegotiationId; - return this; - } - - public Builder expirationTimestamp(Long expirationTimestamp) { - entity.expirationTimestamp = expirationTimestamp; - return this; - } - - @Override - public Builder self() { - return this; - } - - public EndpointDataReferenceEntry build() { - super.build(); - requireNonNull(entity.assetId, ASSET_ID); - requireNonNull(entity.agreementId, AGREEMENT_ID); - requireNonNull(entity.transferProcessId, TRANSFER_PROCESS_ID); - - return entity; - } - } - -} diff --git a/spi/edr-spi/src/main/java/org/eclipse/tractusx/edc/edr/spi/types/EndpointDataReferenceEntryStates.java b/spi/edr-spi/src/main/java/org/eclipse/tractusx/edc/edr/spi/types/EndpointDataReferenceEntryStates.java deleted file mode 100644 index ebb13cad5..000000000 --- a/spi/edr-spi/src/main/java/org/eclipse/tractusx/edc/edr/spi/types/EndpointDataReferenceEntryStates.java +++ /dev/null @@ -1,52 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2021,2022 Microsoft Corporation - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.edr.spi.types; - -import java.util.Arrays; - -/** - * Defines the states an EDR entry can be in. - */ -public enum EndpointDataReferenceEntryStates { - - NEGOTIATED(50), - - REFRESHING(100), - - EXPIRED(200), - - ERROR(300), - - DELETING(400); - private final int code; - - EndpointDataReferenceEntryStates(int code) { - this.code = code; - } - - public static EndpointDataReferenceEntryStates from(int code) { - return Arrays.stream(values()).filter(tps -> tps.code == code).findFirst().orElse(null); - } - - public int code() { - return code; - } - -} diff --git a/core/edr-cache-core/build.gradle.kts b/spi/edr-spi/src/main/java/org/eclipse/tractusx/edc/edr/spi/types/RefreshMode.java similarity index 71% rename from core/edr-cache-core/build.gradle.kts rename to spi/edr-spi/src/main/java/org/eclipse/tractusx/edc/edr/spi/types/RefreshMode.java index 72b9dd51b..371457ae0 100644 --- a/core/edr-cache-core/build.gradle.kts +++ b/spi/edr-spi/src/main/java/org/eclipse/tractusx/edc/edr/spi/types/RefreshMode.java @@ -17,20 +17,16 @@ * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ -plugins { - `java-library` -} - -dependencies { - implementation(libs.edc.spi.core) - implementation(libs.edc.config.filesystem) - implementation(libs.edc.util) +package org.eclipse.tractusx.edc.edr.spi.types; - implementation(project(":spi:edr-spi")) - - testImplementation(libs.edc.lib.query) - testImplementation(testFixtures(project(":spi:edr-spi"))) - testImplementation(libs.edc.core.connector) +import org.eclipse.edc.spi.types.domain.DataAddress; +import org.eclipse.tractusx.edc.edr.spi.service.EdrService; +/** + * Different refresh modes to be used when resolving an {@link DataAddress} with {@link EdrService#resolveByTransferProcess} + */ +public enum RefreshMode { + NO_REFRESH, + AUTO_REFRESH, + FORCE_REFRESH } - diff --git a/spi/edr-spi/src/test/java/org/eclipse/tractusx/edc/edr/spi/EndpointDataReferenceEntryTest.java b/spi/edr-spi/src/test/java/org/eclipse/tractusx/edc/edr/spi/EndpointDataReferenceEntryTest.java deleted file mode 100644 index a58c074b7..000000000 --- a/spi/edr-spi/src/test/java/org/eclipse/tractusx/edc/edr/spi/EndpointDataReferenceEntryTest.java +++ /dev/null @@ -1,49 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.edr.spi; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntry; -import org.junit.jupiter.api.Test; - -import static java.util.UUID.randomUUID; -import static org.assertj.core.api.Assertions.assertThat; - -class EndpointDataReferenceEntryTest { - - @Test - void verify_serializeDeserialize() throws JsonProcessingException { - var mapper = new ObjectMapper(); - - var entry = EndpointDataReferenceEntry.Builder.newInstance() - .assetId(randomUUID().toString()) - .agreementId(randomUUID().toString()) - .transferProcessId(randomUUID().toString()) - .build(); - - var serialized = mapper.writeValueAsString(entry); - var deserialized = mapper.readValue(serialized, EndpointDataReferenceEntry.class); - - assertThat(deserialized.getTransferProcessId()).isNotEmpty(); - assertThat(deserialized.getAssetId()).isNotEmpty(); - assertThat(deserialized.getAgreementId()).isNotEmpty(); - } -} diff --git a/spi/edr-spi/src/testFixtures/java/org/eclipse/tractusx/edc/edr/spi/EndpointDataReferenceCacheTestBase.java b/spi/edr-spi/src/testFixtures/java/org/eclipse/tractusx/edc/edr/spi/EndpointDataReferenceCacheTestBase.java deleted file mode 100644 index 44decab32..000000000 --- a/spi/edr-spi/src/testFixtures/java/org/eclipse/tractusx/edc/edr/spi/EndpointDataReferenceCacheTestBase.java +++ /dev/null @@ -1,414 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.edr.spi; - -import org.eclipse.edc.spi.query.Criterion; -import org.eclipse.edc.spi.query.QuerySpec; -import org.eclipse.edc.spi.result.StoreFailure; -import org.eclipse.edc.spi.result.StoreResult; -import org.eclipse.edc.spi.types.domain.edr.EndpointDataReference; -import org.eclipse.tractusx.edc.edr.spi.store.EndpointDataReferenceCache; -import org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntry; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; - -import java.time.Duration; -import java.util.stream.Collectors; -import java.util.stream.IntStream; - -import static java.util.UUID.randomUUID; -import static java.util.stream.IntStream.range; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.awaitility.Awaitility.await; -import static org.eclipse.edc.spi.persistence.StateEntityStore.hasState; -import static org.eclipse.tractusx.edc.edr.spi.TestFunctions.edr; -import static org.eclipse.tractusx.edc.edr.spi.TestFunctions.edrEntry; -import static org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntryStates.NEGOTIATED; -import static org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntryStates.REFRESHING; -import static org.hamcrest.Matchers.hasSize; - -public abstract class EndpointDataReferenceCacheTestBase { - - public static final String CONNECTOR_NAME = "test-connector"; - - @Test - void save() { - - var tpId = "tp1"; - var assetId = "asset1"; - var edrId = "edr1"; - - var edr = edr(edrId); - var entry = edrEntry(assetId, randomUUID().toString(), tpId); - - getStore().save(entry, edr); - - assertThat(getStore().resolveReference(tpId)) - .isNotNull() - .extracting(EndpointDataReference::getId) - .isEqualTo(edrId); - - var edrs = getStore().referencesForAsset(assetId, null); - assertThat(edrs.size()).isEqualTo(1); - assertThat(edrs.get((0)).getId()).isEqualTo(edrId); - - - } - - @Test - void findByTransferProcessId() { - var entry = edrEntry("assetId", "agreementId", "tpId"); - getStore().save(entry, edr("edrId")); - - assertThat(getStore().findByIdAndLease(entry.getTransferProcessId())).isNotNull(); - } - - @Test - void queryEntries_noQuerySpec() { - var all = IntStream.range(0, 10) - .mapToObj(i -> edrEntry("assetId" + i, "agreementId" + i, "tpId" + i)) - .peek(entry -> getStore().save(entry, edr(entry.getTransferProcessId()))) - .collect(Collectors.toList()); - - assertThat(getStore().queryForEntries(QuerySpec.none())).containsExactlyInAnyOrderElementsOf(all); - } - - @Test - void queryEntries_assetIdQuerySpec() { - IntStream.range(0, 10) - .mapToObj(i -> edrEntry("assetId" + i, "agreementId" + i, "tpId" + i)) - .forEach(entry -> getStore().save(entry, edr(entry.getTransferProcessId()))); - - var entry = edrEntry("assetId", "agreementId", "tpId"); - getStore().save(entry, edr("edrId")); - - var filter = Criterion.Builder.newInstance() - .operandLeft("assetId") - .operator("=") - .operandRight(entry.getAssetId()) - .build(); - - assertThat(getStore().queryForEntries(QuerySpec.Builder.newInstance().filter(filter).build())).containsOnly(entry); - } - - @Test - void queryEntries_agreementIdQuerySpec() { - IntStream.range(0, 10) - .mapToObj(i -> edrEntry("assetId" + i, "agreementId" + i, "tpId" + i)) - .forEach(entry -> getStore().save(entry, edr(entry.getTransferProcessId()))); - - var entry = edrEntry("assetId", "agreementId", "tpId"); - getStore().save(entry, edr("edrId")); - - var filter = Criterion.Builder.newInstance() - .operandLeft("agreementId") - .operator("=") - .operandRight(entry.getAgreementId()) - .build(); - - assertThat(getStore().queryForEntries(QuerySpec.Builder.newInstance().filter(filter).build())).containsOnly(entry); - } - - @Test - void queryEntries_contractNegotiationIdSpec() { - IntStream.range(0, 10) - .mapToObj(i -> edrEntry("assetId" + i, "agreementId" + i, "tpId" + i, "contractNegotiationId" + i)) - .forEach(entry -> getStore().save(entry, edr(entry.getTransferProcessId()))); - - var entry = edrEntry("assetId", "agreementId", "tpId", "contractNegotiationId"); - getStore().save(entry, edr("edrId")); - - var filter = Criterion.Builder.newInstance() - .operandLeft("contractNegotiationId") - .operator("=") - .operandRight(entry.getContractNegotiationId()) - .build(); - - assertThat(getStore().queryForEntries(QuerySpec.Builder.newInstance().filter(filter).build())).containsOnly(entry); - } - - @Test - void queryEntries_providerIdQuerySpec() { - IntStream.range(0, 10) - .mapToObj(i -> edrEntry("assetId" + i, "agreementId" + i, "tpId" + i)) - .forEach(entry -> getStore().save(entry, edr(entry.getTransferProcessId()))); - - var entry = edrEntry("assetId", "agreementId", "tpId"); - getStore().save(entry, edr("edrId")); - - var filter = Criterion.Builder.newInstance() - .operandLeft("providerId") - .operator("=") - .operandRight(entry.getProviderId()) - .build(); - - assertThat(getStore().queryForEntries(QuerySpec.Builder.newInstance().filter(filter).build())).containsOnly(entry); - } - - @Test - void deleteByTransferProcessId_shouldDelete_WhenFound() { - - var entry = edrEntry("assetId", "agreementId", "tpId"); - getStore().save(entry, edr("edrId")); - - assertThat(getStore().deleteByTransferProcessId(entry.getTransferProcessId())) - .extracting(StoreResult::getContent) - .isEqualTo(entry); - - assertThat(getStore().resolveReference(entry.getTransferProcessId())).isNull(); - assertThat(getStore().referencesForAsset(entry.getAssetId(), entry.getProviderId())).hasSize(0); - assertThat(getStore().queryForEntries(QuerySpec.max())).hasSize(0); - - } - - @Test - void deleteByTransferProcessId_shouldReturnError_whenNotFound() { - assertThat(getStore().deleteByTransferProcessId("notFound")) - .extracting(StoreResult::reason) - .isEqualTo(StoreFailure.Reason.NOT_FOUND); - } - - @Test - void nextNotLeased() { - var all = IntStream.range(0, 10) - .mapToObj(i -> edrEntry("assetId" + i, "agreementId" + i, "tpId" + i)) - .peek((entry -> getStore().save(entry, edr(entry.getTransferProcessId())))) - .toList(); - - assertThat(getStore().nextNotLeased(5, hasState(NEGOTIATED.code()))) - .hasSize(5) - .extracting(EndpointDataReferenceEntry::getTransferProcessId) - .isSubsetOf(all.stream().map(EndpointDataReferenceEntry::getTransferProcessId).collect(Collectors.toList())) - .allMatch(id -> isLockedBy(id, CONNECTOR_NAME)); - } - - @Test - void nextNotLeased_shouldOnlyReturnFreeItems() { - var all = IntStream.range(0, 10) - .mapToObj(i -> edrEntry("assetId" + i, "agreementId" + i, "tpId" + i)) - .peek((entry -> getStore().save(entry, edr(entry.getTransferProcessId())))) - .collect(Collectors.toList()); - - // lease a few - var leasedTp = all.stream().skip(5).peek(tp -> lockEntity(tp.getId(), CONNECTOR_NAME)).toList(); - - // should not contain leased TPs - assertThat(getStore().nextNotLeased(10, hasState(NEGOTIATED.code()))) - .hasSize(5) - .isSubsetOf(all) - .doesNotContainAnyElementsOf(leasedTp); - } - - @Test - void nextNotLeased_noFreeItem_shouldReturnEmpty() { - var state = NEGOTIATED; - range(0, 3) - .mapToObj(i -> edrEntry("assetId" + i, "agreementId" + i, "tpId" + i)) - .forEach((entry -> getStore().save(entry, edr(entry.getTransferProcessId())))); - - // first time works - assertThat(getStore().nextNotLeased(10, hasState(state.code()))).hasSize(3); - // second time returns empty list - assertThat(getStore().nextNotLeased(10, hasState(state.code()))).isEmpty(); - } - - @Test - void nextNotLeased_noneInDesiredState() { - range(0, 3) - .mapToObj(i -> edrEntry("assetId" + i, "agreementId" + i, "tpId" + i)) - .forEach((entry -> getStore().save(entry, edr(entry.getTransferProcessId())))); - - - var nextNotLeased = getStore().nextNotLeased(10, hasState(REFRESHING.code())); - - assertThat(nextNotLeased).isEmpty(); - } - - @Test - void nextNotLeased_batchSizeLimits() { - range(0, 10) - .mapToObj(i -> edrEntry("assetId" + i, "agreementId" + i, "tpId" + i)) - .forEach((entry -> getStore().save(entry, edr(entry.getTransferProcessId())))); - - - // first time works - var result = getStore().nextNotLeased(3, hasState(NEGOTIATED.code())); - assertThat(result).hasSize(3); - } - - @Test - void nextNotLeased_verifyTemporalOrdering() { - range(0, 10) - .mapToObj(i -> edrEntry("assetId" + i, "agreementId" + i, String.valueOf(i))) - .peek(this::delayByTenMillis) - .forEach((entry -> getStore().save(entry, edr(entry.getTransferProcessId())))); - - assertThat(getStore().nextNotLeased(20, hasState(NEGOTIATED.code()))) - .extracting(EndpointDataReferenceEntry::getId) - .map(Integer::parseInt) - .isSortedAccordingTo(Integer::compareTo); - } - - @Test - void nextNotLeased_verifyMostRecentlyUpdatedIsLast() throws InterruptedException { - var all = range(0, 10) - .mapToObj(i -> edrEntry("assetId" + i, "agreementId" + i, "tpId" + i)) - .peek((entry -> getStore().save(entry, edr(entry.getTransferProcessId())))) - .toList(); - - Thread.sleep(100); - - var fourth = all.get(3); - fourth.updateStateTimestamp(); - getStore().update(fourth); - - var next = getStore().nextNotLeased(20, hasState(NEGOTIATED.code())); - assertThat(next.indexOf(fourth)).isEqualTo(9); - } - - @Test - @DisplayName("Verifies that calling nextNotLeased locks the TP for any subsequent calls") - void nextNotLeased_locksEntity() { - var entry = edrEntry("assetId", "agreementId", "tpId"); - getStore().save(entry, edr("edrId")); - - getStore().nextNotLeased(100, hasState(NEGOTIATED.code())); - - assertThat(isLockedBy(entry.getId(), CONNECTOR_NAME)).isTrue(); - } - - @Test - void nextNotLeased_expiredLease() { - var entry = edrEntry("assetId", "agreementId", "tpId"); - getStore().save(entry, edr("edrId")); - - lockEntity(entry.getId(), CONNECTOR_NAME, Duration.ofMillis(100)); - - await().atLeast(Duration.ofMillis(100)) - .atMost(Duration.ofMillis(500)) - .until(() -> getStore().nextNotLeased(10, hasState(NEGOTIATED.code())), hasSize(1)); - } - - @Test - void nextNotLeased_shouldLeaseEntityUntilUpdate() { - var entry = edrEntry("assetId", "agreementId", "tpId"); - getStore().save(entry, edr("edrId")); - - var firstQueryResult = getStore().nextNotLeased(1, hasState(NEGOTIATED.code())); - assertThat(firstQueryResult).hasSize(1); - - var secondQueryResult = getStore().nextNotLeased(1, hasState(NEGOTIATED.code())); - assertThat(secondQueryResult).hasSize(0); - - var retrieved = firstQueryResult.get(0); - getStore().update(retrieved); - - var thirdQueryResult = getStore().nextNotLeased(1, hasState(NEGOTIATED.code())); - assertThat(thirdQueryResult).hasSize(1); - } - - @Test - void nextNotLeased_avoidsStarvation() throws InterruptedException { - - range(0, 10) - .mapToObj(i -> edrEntry("assetId" + i, "agreementId" + i, "tpId" + i)) - .forEach((entry -> getStore().save(entry, edr(entry.getTransferProcessId())))); - - var list1 = getStore().nextNotLeased(5, hasState(NEGOTIATED.code())); - Thread.sleep(50); //simulate a short delay to generate different timestamps - list1.forEach(tp -> { - tp.updateStateTimestamp(); - getStore().update(tp); - }); - var list2 = getStore().nextNotLeased(5, hasState(NEGOTIATED.code())); - assertThat(list1).isNotEqualTo(list2).doesNotContainAnyElementsOf(list2); - } - - @Test - @DisplayName("Verify that the lease on a TP is cleared by an update") - void update_shouldBreakLease() { - var entry = edrEntry("assetId", "agreementId", "tpId"); - getStore().save(entry, edr("edrId")); - // acquire lease - lockEntity(entry.getId(), CONNECTOR_NAME); - - entry.transitionToRefreshing(); //modify - getStore().update(entry); - - // lease should be broken - var notLeased = getStore().nextNotLeased(10, hasState(REFRESHING.code())); - - assertThat(notLeased).usingRecursiveFieldByFieldElementComparator().containsExactly(entry); - } - - @Test - void update_leasedByOther_shouldThrowException() { - var entry = edrEntry("assetId", "agreementId", "tpId"); - getStore().save(entry, edr("edrId")); - - lockEntity(entry.getId(), "someone"); - - entry.transitionToRefreshing(); - - // leased by someone else -> throw exception - assertThatThrownBy(() -> getStore().update(entry)).isInstanceOf(IllegalStateException.class); - } - - @Test - void delete_isLeasedBySelf_shouldThrowException() { - var entry = edrEntry("assetId", "agreementId", "tpId"); - getStore().save(entry, edr("edrId")); - - lockEntity(entry.getId(), CONNECTOR_NAME); - - - assertThatThrownBy(() -> getStore().deleteByTransferProcessId(entry.getTransferProcessId())).isInstanceOf(IllegalStateException.class); - } - - @Test - void delete_isLeasedByOther_shouldThrowException() { - var entry = edrEntry("assetId", "agreementId", "tpId"); - getStore().save(entry, edr("edrId")); - - lockEntity(entry.getId(), "someone-else"); - - assertThatThrownBy(() -> getStore().deleteByTransferProcessId(entry.getTransferProcessId())).isInstanceOf(IllegalStateException.class); - } - - protected abstract EndpointDataReferenceCache getStore(); - - protected abstract void lockEntity(String negotiationId, String owner, Duration duration); - - protected void lockEntity(String negotiationId, String owner) { - lockEntity(negotiationId, owner, Duration.ofSeconds(60)); - } - - protected abstract boolean isLockedBy(String negotiationId, String owner); - - private void delayByTenMillis(EndpointDataReferenceEntry t) { - try { - Thread.sleep(10); - } catch (InterruptedException ignored) { - // noop - } - t.updateStateTimestamp(); - } -} diff --git a/spi/edr-spi/src/testFixtures/java/org/eclipse/tractusx/edc/edr/spi/TestFunctions.java b/spi/edr-spi/src/testFixtures/java/org/eclipse/tractusx/edc/edr/spi/TestFunctions.java deleted file mode 100644 index 00312f669..000000000 --- a/spi/edr-spi/src/testFixtures/java/org/eclipse/tractusx/edc/edr/spi/TestFunctions.java +++ /dev/null @@ -1,64 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.edr.spi; - -import org.eclipse.edc.spi.types.domain.edr.EndpointDataReference; -import org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntry; -import org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntryStates; - -import java.util.UUID; - -import static org.eclipse.tractusx.edc.edr.spi.types.EndpointDataReferenceEntryStates.NEGOTIATED; - -public class TestFunctions { - - - public static EndpointDataReference edr(String id) { - return EndpointDataReference.Builder.newInstance() - .endpoint("http://test.com") - .contractId("test-contract-id") - .id(id) - .authCode("11111") - .authKey("authentication").build(); - } - - public static EndpointDataReferenceEntry edrEntry(String assetId, String agreementId, String transferProcessId) { - return edrEntry(assetId, agreementId, transferProcessId, NEGOTIATED); - } - - public static EndpointDataReferenceEntry edrEntry(String assetId, String agreementId, String transferProcessId, String contractNegotiationId) { - return edrEntry(assetId, agreementId, transferProcessId, NEGOTIATED, contractNegotiationId); - } - - public static EndpointDataReferenceEntry edrEntry(String assetId, String agreementId, String transferProcessId, EndpointDataReferenceEntryStates state) { - return edrEntry(assetId, agreementId, transferProcessId, state, null); - } - - public static EndpointDataReferenceEntry edrEntry(String assetId, String agreementId, String transferProcessId, EndpointDataReferenceEntryStates state, String contractNegotiationId) { - return EndpointDataReferenceEntry.Builder.newInstance() - .assetId(assetId) - .agreementId(agreementId) - .transferProcessId(transferProcessId) - .providerId(UUID.randomUUID().toString()) - .contractNegotiationId(contractNegotiationId) - .state(state.code()) - .build(); - } -} diff --git a/spi/tokenrefresh-spi/src/main/java/org/eclipse/tractusx/edc/spi/tokenrefresh/common/TokenRefreshHandler.java b/spi/tokenrefresh-spi/src/main/java/org/eclipse/tractusx/edc/spi/tokenrefresh/common/TokenRefreshHandler.java index d2c84bfba..952b40dda 100644 --- a/spi/tokenrefresh-spi/src/main/java/org/eclipse/tractusx/edc/spi/tokenrefresh/common/TokenRefreshHandler.java +++ b/spi/tokenrefresh-spi/src/main/java/org/eclipse/tractusx/edc/spi/tokenrefresh/common/TokenRefreshHandler.java @@ -27,8 +27,7 @@ */ public interface TokenRefreshHandler { /** - * Refreshes a token identified by the token ID and returns the updated token. If tokens are kept in persistent storage or - * a HSM, implementors must update that entry. + * Refreshes a token identified by the token ID and returns the refreshed token. * * @param tokenId The ID of the token, e.g. a {@code jti} claim in JWT tokens. * @return An updated access+refresh token pair. @@ -36,8 +35,7 @@ public interface TokenRefreshHandler { ServiceResult refreshToken(String tokenId); /** - * Refreshes a token identified by the token ID and returns the updated token. If tokens are kept in persistent storage or - * a HSM, implementors must update that entry. + * Refreshes a token identified by the token ID and returns the refreshed token. * * @param tokenId The ID of the token, e.g. a {@code jti} claim in JWT tokens. * @param edr The {@link DataAddress} containing the EDR From b12d05a2d79ea63777ad4a08d3c1a207df3a8817 Mon Sep 17 00:00:00 2001 From: Paul Latzelsperger <43503240+paullatzelsperger@users.noreply.github.com> Date: Sat, 30 Mar 2024 15:47:28 +0100 Subject: [PATCH 082/100] chore: update to latest EDC package restructuring (#1176) * chore(compile): fix compile errors after EDC refactor * DEPENDENCIES * DEPENDENCIES * force refresh deps * force rebuild * revert disabling module cache [skip ci] --- .github/workflows/verify.yaml | 4 ++- DEPENDENCIES | 14 +++++++--- .../edc/identity/mapper/BdrsClient.java | 2 +- .../identity/mapper/BdrsClientExtension.java | 2 +- .../edc/identity/mapper/BdrsClientTest.java | 2 +- ...BusinessPartnerGroupApiControllerTest.java | 2 +- ...inessPartnerNumberValidationExtension.java | 8 +++--- .../BusinessPartnerValidationExtension.java | 12 ++++----- .../asset/ConsumerAssetRequestController.java | 2 +- .../edr/edr-api-v2/build.gradle.kts | 1 + .../edc/api/edr/v2/EdrCacheApiController.java | 4 +-- .../edc/api/edr/v2/EdrCacheApiExtension.java | 2 +- .../edr/v2/dto/NegotiateEdrRequestDto.java | 8 ++---- .../edc/api/edr/v2/schema/EdrSchema.java | 2 +- ...ctToNegotiateEdrRequestDtoTransformer.java | 2 +- ...tDtoToNegotiatedEdrRequestTransformer.java | 2 +- .../NegotiateEdrRequestDtoValidator.java | 6 ++--- .../api/edr/v2/EdrCacheApiControllerTest.java | 6 ++--- .../edc/api/edr/v2/TestFunctions.java | 8 +++--- ...NegotiateEdrRequestDtoTransformerTest.java | 21 +++++++-------- .../NegotiateEdrRequestDtoValidatorTest.java | 6 ++--- .../callback/ContractNegotiationCallback.java | 8 +++--- .../InProcessCallbackMessageDispatcher.java | 2 +- .../InProcessCallbackRegistryImpl.java | 2 +- .../edc/callback/LocalCallbackExtension.java | 8 +++--- .../ContractNegotiationCallbackTest.java | 26 +++++++++---------- .../callback/LocalCallbackExtensionTest.java | 4 +-- .../tractusx/edc/callback/TestFunctions.java | 10 +++---- .../iatp/sts/dim/DimSecureTokenService.java | 4 +-- .../dim/DimSecureTokenServiceExtension.java | 2 +- .../sts/dim/DimSecureTokenServiceTest.java | 2 +- ...AssetPostgresqlMigrationExtensionTest.java | 6 ++--- .../AdditionalHeadersProvisionedResource.java | 2 +- .../AdditionalHeadersProvisioner.java | 10 +++---- .../AdditionalHeadersResourceDefinition.java | 2 +- ...nalHeadersResourceDefinitionGenerator.java | 10 +++---- .../ProvisionAdditionalHeadersExtension.java | 6 ++--- .../AdditionalHeadersProvisionerTest.java | 9 +++---- ...eadersResourceDefinitionGeneratorTest.java | 8 +++--- ...ovisionAdditionalHeadersExtensionTest.java | 4 +-- .../TokenRefreshHandlerExtension.java | 2 +- .../tokenrefresh/TokenRefreshHandlerImpl.java | 2 +- .../TokenRefreshHandlerImplTest.java | 2 +- .../sftp/provisioner/NoOpSftpProvisioner.java | 10 +++---- .../SftpProviderResourceDefinition.java | 2 +- ...tpProviderResourceDefinitionGenerator.java | 6 ++--- .../SftpProvisionedContentResource.java | 2 +- .../provisioner/SftpProvisionerExtension.java | 4 +-- .../provisioner/NoOpSftpProvisionerTest.java | 4 +-- ...oviderResourceDefinitionGeneratorTest.java | 2 +- .../tractusx/edc/lifecycle/DataWiper.java | 6 ++--- .../edc/lifecycle/ParticipantRuntime.java | 2 +- .../catalog/DimCatalogIntegrationTest.java | 2 +- .../edc/tests/catalog/CatalogTest.java | 2 +- .../tests/edrv2/AbstractNegotiateEdrTest.java | 18 ++++++------- .../tests/edrv2/EdrCacheApiEndToEndTest.java | 2 +- .../edc/tests/IdentityParticipant.java | 2 +- .../tractusx/edc/tests/ParticipantEdrApi.java | 4 +-- .../tests/helpers/CatalogHelperFunctions.java | 6 ++--- .../EdrNegotiationHelperFunctions.java | 3 +-- .../tests/helpers/PolicyHelperFunctions.java | 4 +-- .../TransferProcessHelperFunctions.java | 2 +- .../participant/TractusxParticipantBase.java | 2 +- .../edc/tests/runtimes/DataWiper.java | 6 ++--- .../tests/runtimes/ParticipantRuntime.java | 2 +- .../tests/runtimes/PgParticipantRuntime.java | 16 ++++++------ .../transfer/HttpConsumerPullBaseTest.java | 2 +- .../tests/transfer/ProviderPushBaseTest.java | 4 +-- .../iatp/runtime/IatpParticipantRuntime.java | 2 +- .../policy/PolicyMonitorEndToEndTest.java | 6 ++--- .../TransferWithTokenRefreshTest.java | 2 +- .../transfer/test/ParticipantRuntime.java | 2 +- .../DataPlaneTokenRefreshEndToEndTest.java | 2 +- .../edc/spi/callback/InProcessCallback.java | 2 +- .../callback/InProcessCallbackRegistry.java | 2 +- .../tractusx/edc/edr/spi/CoreConstants.java | 3 ++- spi/edr-spi/build.gradle.kts | 1 + .../edr/spi/types/NegotiateEdrRequest.java | 10 +++---- 78 files changed, 198 insertions(+), 196 deletions(-) diff --git a/.github/workflows/verify.yaml b/.github/workflows/verify.yaml index 3824cd3f0..258c67bcf 100644 --- a/.github/workflows/verify.yaml +++ b/.github/workflows/verify.yaml @@ -153,4 +153,6 @@ jobs: - uses: ./.github/actions/setup-java - name: Run Azure/S3 dataplane tests - run: ./gradlew -p edc-tests/edc-dataplane test -DincludeTags="AzureCosmosDbIntegrationTest,AwsS3IntegrationTest" + run: | + ./gradlew compileJava compileTestJava + ./gradlew -p edc-tests/edc-dataplane test -DincludeTags="AzureCosmosDbIntegrationTest,AwsS3IntegrationTest" diff --git a/DEPENDENCIES b/DEPENDENCIES index f48b6d9d7..d55dd2faf 100644 --- a/DEPENDENCIES +++ b/DEPENDENCIES @@ -222,7 +222,7 @@ maven/mavencentral/io.rest-assured/xml-path/5.4.0, Apache-2.0, approved, #12038 maven/mavencentral/io.setl/rdf-urdna/1.1, Apache-2.0, approved, clearlydefined maven/mavencentral/io.swagger.core.v3/swagger-annotations-jakarta/2.2.15, Apache-2.0, approved, #5947 maven/mavencentral/io.swagger.core.v3/swagger-annotations-jakarta/2.2.18, Apache-2.0, approved, #5947 -maven/mavencentral/io.swagger.core.v3/swagger-annotations-jakarta/2.2.20, Apache-2.0, approved, #5947 +maven/mavencentral/io.swagger.core.v3/swagger-annotations-jakarta/2.2.21, Apache-2.0, approved, #5947 maven/mavencentral/io.swagger.core.v3/swagger-annotations/2.2.15, Apache-2.0, approved, #11362 maven/mavencentral/io.swagger.core.v3/swagger-annotations/2.2.8, Apache-2.0, approved, #11362 maven/mavencentral/io.swagger.core.v3/swagger-core-jakarta/2.2.15, Apache-2.0, approved, #5929 @@ -350,16 +350,15 @@ maven/mavencentral/org.eclipse.edc/aws-s3-test/0.6.1-SNAPSHOT, Apache-2.0, appro maven/mavencentral/org.eclipse.edc/azure-blob-core/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/azure-test/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/boot-lib/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/boot-spi/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/boot/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/callback-event-dispatcher/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/callback-http-dispatcher/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/catalog-api/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/catalog-core/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/catalog-spi/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/configuration-filesystem/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/connector-core/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/contract-agreement-api/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/contract-core/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/contract-definition-api/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/contract-definition-store-sql/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/contract-negotiation-api/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc @@ -370,9 +369,13 @@ maven/mavencentral/org.eclipse.edc/control-plane-aggregate-services/0.6.1-SNAPSH maven/mavencentral/org.eclipse.edc/control-plane-api-client-spi/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/control-plane-api-client/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/control-plane-api/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/control-plane-catalog/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/control-plane-contract/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/control-plane-core/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/control-plane-policies-lib/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/control-plane-spi/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/control-plane-transfer/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/control-plane-transform/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/core-spi/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/crypto-common-lib/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/data-address-http-data-spi/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc @@ -487,7 +490,6 @@ maven/mavencentral/org.eclipse.edc/token-spi/0.6.1-SNAPSHOT, Apache-2.0, approve maven/mavencentral/org.eclipse.edc/transaction-datasource-spi/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/transaction-local/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/transaction-spi/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/transfer-core/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/transfer-data-plane-signaling/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/transfer-data-plane-spi/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/transfer-process-api/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc @@ -495,10 +497,13 @@ maven/mavencentral/org.eclipse.edc/transfer-process-store-sql/0.6.1-SNAPSHOT, Ap maven/mavencentral/org.eclipse.edc/transfer-pull-http-dynamic-receiver/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/transfer-spi/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/transform-core/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/transform-lib/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/transform-spi/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/util-lib/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/util/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/validator-core/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/validator-data-address-http-data/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/validator-lib/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/validator-spi/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/vault-azure/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/vault-hashicorp/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc @@ -597,6 +602,7 @@ maven/mavencentral/org.ow2.asm/asm/9.3, BSD-3-Clause, approved, clearlydefined maven/mavencentral/org.ow2.asm/asm/9.5, BSD-3-Clause, approved, #7554 maven/mavencentral/org.ow2.asm/asm/9.6, BSD-3-Clause, approved, #10776 maven/mavencentral/org.postgresql/postgresql/42.7.2, BSD-2-Clause AND Apache-2.0, approved, #11681 +maven/mavencentral/org.postgresql/postgresql/42.7.3, BSD-2-Clause AND Apache-2.0, approved, #11681 maven/mavencentral/org.reactivestreams/reactive-streams/1.0.4, CC0-1.0, approved, CQ16332 maven/mavencentral/org.reflections/reflections/0.10.2, Apache-2.0 AND WTFPL, approved, clearlydefined maven/mavencentral/org.rnorth.duct-tape/duct-tape/1.0.8, MIT, approved, clearlydefined diff --git a/edc-extensions/bdrs-client/src/main/java/org/eclipse/tractusx/edc/identity/mapper/BdrsClient.java b/edc-extensions/bdrs-client/src/main/java/org/eclipse/tractusx/edc/identity/mapper/BdrsClient.java index 174410d19..f84fa141b 100644 --- a/edc-extensions/bdrs-client/src/main/java/org/eclipse/tractusx/edc/identity/mapper/BdrsClient.java +++ b/edc-extensions/bdrs-client/src/main/java/org/eclipse/tractusx/edc/identity/mapper/BdrsClient.java @@ -22,8 +22,8 @@ import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import okhttp3.Request; +import org.eclipse.edc.http.spi.EdcHttpClient; import org.eclipse.edc.spi.EdcException; -import org.eclipse.edc.spi.http.EdcHttpClient; import org.eclipse.edc.spi.iam.AudienceResolver; import org.eclipse.edc.spi.monitor.Monitor; import org.eclipse.edc.spi.types.domain.message.RemoteMessage; diff --git a/edc-extensions/bdrs-client/src/main/java/org/eclipse/tractusx/edc/identity/mapper/BdrsClientExtension.java b/edc-extensions/bdrs-client/src/main/java/org/eclipse/tractusx/edc/identity/mapper/BdrsClientExtension.java index a9899db07..99d7ffc74 100644 --- a/edc-extensions/bdrs-client/src/main/java/org/eclipse/tractusx/edc/identity/mapper/BdrsClientExtension.java +++ b/edc-extensions/bdrs-client/src/main/java/org/eclipse/tractusx/edc/identity/mapper/BdrsClientExtension.java @@ -19,11 +19,11 @@ package org.eclipse.tractusx.edc.identity.mapper; +import org.eclipse.edc.http.spi.EdcHttpClient; import org.eclipse.edc.runtime.metamodel.annotation.Extension; import org.eclipse.edc.runtime.metamodel.annotation.Inject; import org.eclipse.edc.runtime.metamodel.annotation.Provider; import org.eclipse.edc.runtime.metamodel.annotation.Setting; -import org.eclipse.edc.spi.http.EdcHttpClient; import org.eclipse.edc.spi.iam.AudienceResolver; import org.eclipse.edc.spi.system.ServiceExtension; import org.eclipse.edc.spi.system.ServiceExtensionContext; diff --git a/edc-extensions/bdrs-client/src/test/java/org/eclipse/tractusx/edc/identity/mapper/BdrsClientTest.java b/edc-extensions/bdrs-client/src/test/java/org/eclipse/tractusx/edc/identity/mapper/BdrsClientTest.java index c6a47e838..bb77c54c2 100644 --- a/edc-extensions/bdrs-client/src/test/java/org/eclipse/tractusx/edc/identity/mapper/BdrsClientTest.java +++ b/edc-extensions/bdrs-client/src/test/java/org/eclipse/tractusx/edc/identity/mapper/BdrsClientTest.java @@ -22,10 +22,10 @@ import com.fasterxml.jackson.databind.ObjectMapper; import dev.failsafe.RetryPolicy; import okhttp3.OkHttpClient; +import org.eclipse.edc.http.client.EdcHttpClientImpl; import org.eclipse.edc.spi.EdcException; import org.eclipse.edc.spi.monitor.Monitor; import org.eclipse.edc.spi.types.domain.message.RemoteMessage; -import org.eclipse.http.client.EdcHttpClientImpl; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; diff --git a/edc-extensions/bpn-validation/bpn-validation-api/src/test/java/org/eclipse/tractusx/edc/api/bpn/BusinessPartnerGroupApiControllerTest.java b/edc-extensions/bpn-validation/bpn-validation-api/src/test/java/org/eclipse/tractusx/edc/api/bpn/BusinessPartnerGroupApiControllerTest.java index a1b93e882..f2a9033b8 100644 --- a/edc-extensions/bpn-validation/bpn-validation-api/src/test/java/org/eclipse/tractusx/edc/api/bpn/BusinessPartnerGroupApiControllerTest.java +++ b/edc-extensions/bpn-validation/bpn-validation-api/src/test/java/org/eclipse/tractusx/edc/api/bpn/BusinessPartnerGroupApiControllerTest.java @@ -37,7 +37,7 @@ import static io.restassured.http.ContentType.JSON; import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.CONTEXT; import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.ID; -import static org.eclipse.edc.spi.CoreConstants.EDC_NAMESPACE; +import static org.eclipse.edc.spi.constants.CoreConstants.EDC_NAMESPACE; import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.TX_NAMESPACE; import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.TX_PREFIX; import static org.hamcrest.Matchers.notNullValue; diff --git a/edc-extensions/bpn-validation/bpn-validation-core/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/BusinessPartnerNumberValidationExtension.java b/edc-extensions/bpn-validation/bpn-validation-core/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/BusinessPartnerNumberValidationExtension.java index 8776044f1..4ecebe5c4 100644 --- a/edc-extensions/bpn-validation/bpn-validation-core/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/BusinessPartnerNumberValidationExtension.java +++ b/edc-extensions/bpn-validation/bpn-validation-core/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/BusinessPartnerNumberValidationExtension.java @@ -28,9 +28,9 @@ import org.eclipse.edc.spi.system.ServiceExtensionContext; import org.eclipse.tractusx.edc.validation.businesspartner.functions.BusinessPartnerNumberPermissionFunction; -import static org.eclipse.edc.connector.contract.spi.offer.ContractDefinitionResolver.CATALOGING_SCOPE; -import static org.eclipse.edc.connector.contract.spi.validation.ContractValidationService.NEGOTIATION_SCOPE; -import static org.eclipse.edc.connector.contract.spi.validation.ContractValidationService.TRANSFER_SCOPE; +import static org.eclipse.edc.connector.controlplane.contract.spi.offer.ContractDefinitionResolver.CATALOGING_SCOPE; +import static org.eclipse.edc.connector.controlplane.contract.spi.validation.ContractValidationService.NEGOTIATION_SCOPE; +import static org.eclipse.edc.connector.controlplane.contract.spi.validation.ContractValidationService.TRANSFER_SCOPE; import static org.eclipse.edc.policy.model.OdrlNamespace.ODRL_SCHEMA; import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.TX_NAMESPACE; import static org.eclipse.tractusx.edc.validation.businesspartner.BusinessPartnerNumberValidationExtension.NAME; @@ -62,7 +62,7 @@ public class BusinessPartnerNumberValidationExtension implements ServiceExtensio private RuleBindingRegistry ruleBindingRegistry; @Inject private PolicyEngine policyEngine; - + @Override public String name() { return NAME; diff --git a/edc-extensions/bpn-validation/bpn-validation-core/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/BusinessPartnerValidationExtension.java b/edc-extensions/bpn-validation/bpn-validation-core/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/BusinessPartnerValidationExtension.java index d7938a777..8e52a6ee3 100644 --- a/edc-extensions/bpn-validation/bpn-validation-core/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/BusinessPartnerValidationExtension.java +++ b/edc-extensions/bpn-validation/bpn-validation-core/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/BusinessPartnerValidationExtension.java @@ -29,17 +29,17 @@ import org.eclipse.tractusx.edc.validation.businesspartner.functions.BusinessPartnerGroupFunction; import org.eclipse.tractusx.edc.validation.businesspartner.spi.BusinessPartnerStore; -import static org.eclipse.edc.connector.contract.spi.offer.ContractDefinitionResolver.CATALOGING_SCOPE; -import static org.eclipse.edc.connector.contract.spi.validation.ContractValidationService.NEGOTIATION_SCOPE; -import static org.eclipse.edc.connector.contract.spi.validation.ContractValidationService.TRANSFER_SCOPE; +import static org.eclipse.edc.connector.controlplane.contract.spi.offer.ContractDefinitionResolver.CATALOGING_SCOPE; +import static org.eclipse.edc.connector.controlplane.contract.spi.validation.ContractValidationService.NEGOTIATION_SCOPE; +import static org.eclipse.edc.connector.controlplane.contract.spi.validation.ContractValidationService.TRANSFER_SCOPE; import static org.eclipse.edc.policy.model.OdrlNamespace.ODRL_SCHEMA; /** * Registers a {@link org.eclipse.tractusx.edc.validation.businesspartner.functions.BusinessPartnerGroupFunction} for the following scopes: *
      - *
    • {@link org.eclipse.edc.connector.contract.spi.offer.ContractDefinitionResolver#CATALOGING_SCOPE}
    • - *
    • {@link org.eclipse.edc.connector.contract.spi.validation.ContractValidationService#NEGOTIATION_SCOPE}
    • - *
    • {@link org.eclipse.edc.connector.contract.spi.validation.ContractValidationService#TRANSFER_SCOPE}
    • + *
    • {@link org.eclipse.edc.connector.controlplane.contract.spi.offer.ContractDefinitionResolver.CATALOGING_SCOPE}
    • + *
    • {@link org.eclipse.edc.connector.controlplane.contract.spi.validation.ContractValidationService.NEGOTIATION_SCOPE}
    • + *
    • {@link org.eclipse.edc.connector.controlplane.contract.spi.validation.ContractValidationService.TRANSFER_SCOPE}
    • *
    * The rule to which the function is bound is {@link BusinessPartnerGroupFunction#BUSINESS_PARTNER_CONSTRAINT_KEY}. That means, that policies that are bound to these scopes look * like this: diff --git a/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-consumer-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/consumer/api/asset/ConsumerAssetRequestController.java b/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-consumer-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/consumer/api/asset/ConsumerAssetRequestController.java index 42ba2f807..7c1e8d44a 100644 --- a/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-consumer-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/consumer/api/asset/ConsumerAssetRequestController.java +++ b/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-consumer-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/consumer/api/asset/ConsumerAssetRequestController.java @@ -56,7 +56,7 @@ import static java.util.UUID.randomUUID; import static org.eclipse.edc.connector.dataplane.spi.schema.DataFlowRequestSchema.PATH; import static org.eclipse.edc.connector.dataplane.spi.schema.DataFlowRequestSchema.QUERY_PARAMS; -import static org.eclipse.edc.spi.CoreConstants.EDC_NAMESPACE; +import static org.eclipse.edc.spi.constants.CoreConstants.EDC_NAMESPACE; import static org.eclipse.tractusx.edc.edr.spi.types.RefreshMode.AUTO_REFRESH; /** diff --git a/edc-extensions/edr/edr-api-v2/build.gradle.kts b/edc-extensions/edr/edr-api-v2/build.gradle.kts index 71dc0ca7e..3e3b028f5 100644 --- a/edc-extensions/edr/edr-api-v2/build.gradle.kts +++ b/edc-extensions/edr/edr-api-v2/build.gradle.kts @@ -39,4 +39,5 @@ dependencies { testImplementation(libs.edc.junit) testImplementation(libs.edc.lib.jersey.providers) testImplementation(libs.edc.core.transform) + testImplementation(libs.edc.spi.contract) } diff --git a/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/EdrCacheApiController.java b/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/EdrCacheApiController.java index 17df78c59..415b936da 100644 --- a/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/EdrCacheApiController.java +++ b/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/EdrCacheApiController.java @@ -31,8 +31,8 @@ import jakarta.ws.rs.QueryParam; import jakarta.ws.rs.core.MediaType; import org.eclipse.edc.api.model.IdResponse; -import org.eclipse.edc.connector.contract.spi.types.negotiation.ContractRequest; -import org.eclipse.edc.connector.spi.contractnegotiation.ContractNegotiationService; +import org.eclipse.edc.connector.controlplane.contract.spi.types.negotiation.ContractRequest; +import org.eclipse.edc.connector.controlplane.services.spi.contractnegotiation.ContractNegotiationService; import org.eclipse.edc.edr.spi.store.EndpointDataReferenceStore; import org.eclipse.edc.edr.spi.types.EndpointDataReferenceEntry; import org.eclipse.edc.spi.EdcException; diff --git a/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/EdrCacheApiExtension.java b/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/EdrCacheApiExtension.java index c9b482e58..b90d2f045 100644 --- a/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/EdrCacheApiExtension.java +++ b/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/EdrCacheApiExtension.java @@ -21,7 +21,7 @@ import jakarta.json.Json; import org.eclipse.edc.connector.api.management.configuration.ManagementApiConfiguration; -import org.eclipse.edc.connector.spi.contractnegotiation.ContractNegotiationService; +import org.eclipse.edc.connector.controlplane.services.spi.contractnegotiation.ContractNegotiationService; import org.eclipse.edc.edr.spi.store.EndpointDataReferenceStore; import org.eclipse.edc.jsonld.spi.JsonLd; import org.eclipse.edc.runtime.metamodel.annotation.Inject; diff --git a/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/dto/NegotiateEdrRequestDto.java b/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/dto/NegotiateEdrRequestDto.java index de05beb78..46760d228 100644 --- a/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/dto/NegotiateEdrRequestDto.java +++ b/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/dto/NegotiateEdrRequestDto.java @@ -19,13 +19,13 @@ package org.eclipse.tractusx.edc.api.edr.v2.dto; -import org.eclipse.edc.connector.api.management.contractnegotiation.model.ContractOfferDescription; +import org.eclipse.edc.connector.controlplane.api.management.contractnegotiation.model.ContractOfferDescription; import org.eclipse.edc.spi.types.domain.callback.CallbackAddress; import java.util.ArrayList; import java.util.List; -import static org.eclipse.edc.spi.CoreConstants.EDC_NAMESPACE; +import static org.eclipse.edc.spi.constants.CoreConstants.EDC_NAMESPACE; import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.TX_NAMESPACE; public class NegotiateEdrRequestDto { @@ -64,10 +64,6 @@ public String getCounterPartyId() { return counterPartyId; } - public String getProviderId() { - return providerId; - } - public List getCallbackAddresses() { return callbackAddresses; } diff --git a/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/schema/EdrSchema.java b/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/schema/EdrSchema.java index 0f022452c..e62ac0d03 100644 --- a/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/schema/EdrSchema.java +++ b/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/schema/EdrSchema.java @@ -21,7 +21,7 @@ import io.swagger.v3.oas.annotations.media.Schema; import org.eclipse.edc.connector.api.management.configuration.ManagementApiSchema; -import org.eclipse.edc.connector.api.management.contractnegotiation.ContractNegotiationApi; +import org.eclipse.edc.connector.controlplane.api.management.contractnegotiation.ContractNegotiationApi; import org.eclipse.edc.edr.spi.types.EndpointDataReferenceEntry; import org.eclipse.tractusx.edc.api.edr.v2.dto.NegotiateEdrRequestDto; diff --git a/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/transform/JsonObjectToNegotiateEdrRequestDtoTransformer.java b/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/transform/JsonObjectToNegotiateEdrRequestDtoTransformer.java index 721743466..ea630cdc5 100644 --- a/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/transform/JsonObjectToNegotiateEdrRequestDtoTransformer.java +++ b/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/transform/JsonObjectToNegotiateEdrRequestDtoTransformer.java @@ -21,7 +21,7 @@ import jakarta.json.JsonObject; import jakarta.json.JsonValue; -import org.eclipse.edc.connector.api.management.contractnegotiation.model.ContractOfferDescription; +import org.eclipse.edc.connector.controlplane.api.management.contractnegotiation.model.ContractOfferDescription; import org.eclipse.edc.jsonld.spi.transformer.AbstractJsonLdTransformer; import org.eclipse.edc.spi.types.domain.callback.CallbackAddress; import org.eclipse.edc.transform.spi.TransformerContext; diff --git a/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/transform/NegotiateEdrRequestDtoToNegotiatedEdrRequestTransformer.java b/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/transform/NegotiateEdrRequestDtoToNegotiatedEdrRequestTransformer.java index 24bd3e533..cb1f62d63 100644 --- a/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/transform/NegotiateEdrRequestDtoToNegotiatedEdrRequestTransformer.java +++ b/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/transform/NegotiateEdrRequestDtoToNegotiatedEdrRequestTransformer.java @@ -19,7 +19,7 @@ package org.eclipse.tractusx.edc.api.edr.v2.transform; -import org.eclipse.edc.spi.types.domain.offer.ContractOffer; +import org.eclipse.edc.connector.controlplane.contract.spi.types.offer.ContractOffer; import org.eclipse.edc.transform.spi.TransformerContext; import org.eclipse.edc.transform.spi.TypeTransformer; import org.eclipse.tractusx.edc.api.edr.v2.dto.NegotiateEdrRequestDto; diff --git a/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/validation/NegotiateEdrRequestDtoValidator.java b/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/validation/NegotiateEdrRequestDtoValidator.java index 667a37afd..a7086bd39 100644 --- a/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/validation/NegotiateEdrRequestDtoValidator.java +++ b/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/validation/NegotiateEdrRequestDtoValidator.java @@ -26,9 +26,9 @@ import org.eclipse.edc.validator.spi.Validator; import org.eclipse.tractusx.edc.api.edr.v2.dto.NegotiateEdrRequestDto; -import static org.eclipse.edc.connector.api.management.contractnegotiation.model.ContractOfferDescription.ASSET_ID; -import static org.eclipse.edc.connector.api.management.contractnegotiation.model.ContractOfferDescription.OFFER_ID; -import static org.eclipse.edc.connector.api.management.contractnegotiation.model.ContractOfferDescription.POLICY; +import static org.eclipse.edc.connector.controlplane.api.management.contractnegotiation.model.ContractOfferDescription.ASSET_ID; +import static org.eclipse.edc.connector.controlplane.api.management.contractnegotiation.model.ContractOfferDescription.OFFER_ID; +import static org.eclipse.edc.connector.controlplane.api.management.contractnegotiation.model.ContractOfferDescription.POLICY; public class NegotiateEdrRequestDtoValidator { diff --git a/edc-extensions/edr/edr-api-v2/src/test/java/org/eclipse/tractusx/edc/api/edr/v2/EdrCacheApiControllerTest.java b/edc-extensions/edr/edr-api-v2/src/test/java/org/eclipse/tractusx/edc/api/edr/v2/EdrCacheApiControllerTest.java index 4c7dd8982..6d8fce426 100644 --- a/edc-extensions/edr/edr-api-v2/src/test/java/org/eclipse/tractusx/edc/api/edr/v2/EdrCacheApiControllerTest.java +++ b/edc-extensions/edr/edr-api-v2/src/test/java/org/eclipse/tractusx/edc/api/edr/v2/EdrCacheApiControllerTest.java @@ -24,7 +24,7 @@ import jakarta.json.JsonObject; import jakarta.json.JsonObjectBuilder; import org.eclipse.edc.api.model.IdResponse; -import org.eclipse.edc.connector.spi.contractnegotiation.ContractNegotiationService; +import org.eclipse.edc.connector.controlplane.services.spi.contractnegotiation.ContractNegotiationService; import org.eclipse.edc.edr.spi.store.EndpointDataReferenceStore; import org.eclipse.edc.edr.spi.types.EndpointDataReferenceEntry; import org.eclipse.edc.junit.annotations.ApiTest; @@ -58,8 +58,8 @@ import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.ID; import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.TYPE; import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.VOCAB; -import static org.eclipse.edc.spi.CoreConstants.EDC_NAMESPACE; -import static org.eclipse.edc.spi.CoreConstants.EDC_PREFIX; +import static org.eclipse.edc.spi.constants.CoreConstants.EDC_NAMESPACE; +import static org.eclipse.edc.spi.constants.CoreConstants.EDC_PREFIX; import static org.eclipse.tractusx.edc.api.edr.v2.TestFunctions.createContractNegotiation; import static org.eclipse.tractusx.edc.api.edr.v2.TestFunctions.negotiationRequest; import static org.eclipse.tractusx.edc.api.edr.v2.TestFunctions.openRequest; diff --git a/edc-extensions/edr/edr-api-v2/src/test/java/org/eclipse/tractusx/edc/api/edr/v2/TestFunctions.java b/edc-extensions/edr/edr-api-v2/src/test/java/org/eclipse/tractusx/edc/api/edr/v2/TestFunctions.java index 96a2e9b27..44837c176 100644 --- a/edc-extensions/edr/edr-api-v2/src/test/java/org/eclipse/tractusx/edc/api/edr/v2/TestFunctions.java +++ b/edc-extensions/edr/edr-api-v2/src/test/java/org/eclipse/tractusx/edc/api/edr/v2/TestFunctions.java @@ -21,17 +21,17 @@ import jakarta.json.Json; import jakarta.json.JsonObject; -import org.eclipse.edc.connector.api.management.contractnegotiation.model.ContractOfferDescription; -import org.eclipse.edc.connector.contract.spi.types.negotiation.ContractNegotiation; +import org.eclipse.edc.connector.controlplane.api.management.contractnegotiation.model.ContractOfferDescription; +import org.eclipse.edc.connector.controlplane.contract.spi.types.negotiation.ContractNegotiation; +import org.eclipse.edc.connector.controlplane.contract.spi.types.offer.ContractOffer; import org.eclipse.edc.policy.model.Policy; -import org.eclipse.edc.spi.types.domain.offer.ContractOffer; import org.eclipse.tractusx.edc.api.edr.v2.dto.NegotiateEdrRequestDto; import org.eclipse.tractusx.edc.edr.spi.types.NegotiateEdrRequest; import java.util.UUID; import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.TYPE; -import static org.eclipse.edc.spi.CoreConstants.EDC_NAMESPACE; +import static org.eclipse.edc.spi.constants.CoreConstants.EDC_NAMESPACE; public class TestFunctions { diff --git a/edc-extensions/edr/edr-api-v2/src/test/java/org/eclipse/tractusx/edc/api/edr/v2/transform/JsonObjectToNegotiateEdrRequestDtoTransformerTest.java b/edc-extensions/edr/edr-api-v2/src/test/java/org/eclipse/tractusx/edc/api/edr/v2/transform/JsonObjectToNegotiateEdrRequestDtoTransformerTest.java index 6409d37f4..d48b3943e 100644 --- a/edc-extensions/edr/edr-api-v2/src/test/java/org/eclipse/tractusx/edc/api/edr/v2/transform/JsonObjectToNegotiateEdrRequestDtoTransformerTest.java +++ b/edc-extensions/edr/edr-api-v2/src/test/java/org/eclipse/tractusx/edc/api/edr/v2/transform/JsonObjectToNegotiateEdrRequestDtoTransformerTest.java @@ -23,7 +23,7 @@ import jakarta.json.JsonArrayBuilder; import jakarta.json.JsonObject; import jakarta.json.JsonValue; -import org.eclipse.edc.connector.api.management.contractnegotiation.model.ContractOfferDescription; +import org.eclipse.edc.connector.controlplane.api.management.contractnegotiation.model.ContractOfferDescription; import org.eclipse.edc.jsonld.TitaniumJsonLd; import org.eclipse.edc.jsonld.spi.JsonLd; import org.eclipse.edc.spi.monitor.Monitor; @@ -36,20 +36,19 @@ import java.util.Set; import static org.assertj.core.api.Assertions.assertThat; -import static org.eclipse.edc.connector.api.management.contractnegotiation.model.ContractOfferDescription.ASSET_ID; -import static org.eclipse.edc.connector.api.management.contractnegotiation.model.ContractOfferDescription.OFFER_ID; -import static org.eclipse.edc.connector.api.management.contractnegotiation.model.ContractOfferDescription.POLICY; -import static org.eclipse.edc.connector.contract.spi.types.negotiation.ContractRequest.CALLBACK_ADDRESSES; -import static org.eclipse.edc.connector.contract.spi.types.negotiation.ContractRequest.CONTRACT_REQUEST_TYPE; -import static org.eclipse.edc.connector.contract.spi.types.negotiation.ContractRequest.OFFER; -import static org.eclipse.edc.connector.contract.spi.types.negotiation.ContractRequest.PROTOCOL; -import static org.eclipse.edc.connector.contract.spi.types.negotiation.ContractRequest.PROVIDER_ID; +import static org.eclipse.edc.connector.controlplane.api.management.contractnegotiation.model.ContractOfferDescription.OFFER_ID; +import static org.eclipse.edc.connector.controlplane.contract.spi.types.negotiation.ContractRequest.CALLBACK_ADDRESSES; +import static org.eclipse.edc.connector.controlplane.contract.spi.types.negotiation.ContractRequest.CONTRACT_REQUEST_TYPE; +import static org.eclipse.edc.connector.controlplane.contract.spi.types.negotiation.ContractRequest.OFFER; +import static org.eclipse.edc.connector.controlplane.contract.spi.types.negotiation.ContractRequest.POLICY; +import static org.eclipse.edc.connector.controlplane.contract.spi.types.negotiation.ContractRequest.PROTOCOL; +import static org.eclipse.edc.edr.spi.types.EndpointDataReferenceEntry.ASSET_ID; import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.TYPE; import static org.eclipse.edc.jsonld.spi.PropertyAndTypeNames.ODRL_OBLIGATION_ATTRIBUTE; import static org.eclipse.edc.jsonld.spi.PropertyAndTypeNames.ODRL_PERMISSION_ATTRIBUTE; import static org.eclipse.edc.jsonld.spi.PropertyAndTypeNames.ODRL_POLICY_TYPE_SET; import static org.eclipse.edc.jsonld.spi.PropertyAndTypeNames.ODRL_PROHIBITION_ATTRIBUTE; -import static org.eclipse.edc.spi.CoreConstants.EDC_NAMESPACE; +import static org.eclipse.edc.spi.constants.CoreConstants.EDC_NAMESPACE; import static org.eclipse.edc.spi.types.domain.callback.CallbackAddress.EVENTS; import static org.eclipse.edc.spi.types.domain.callback.CallbackAddress.IS_TRANSACTIONAL; import static org.eclipse.edc.spi.types.domain.callback.CallbackAddress.URI; @@ -81,7 +80,6 @@ void transform() { .add(EDR_REQUEST_DTO_COUNTERPARTY_ADDRESS, "test-address") .add(EDR_REQUEST_DTO_COUNTERPARTY_ID, "test-conn-id") .add(PROTOCOL, "test-protocol") - .add(PROVIDER_ID, "test-provider-id") .add(CALLBACK_ADDRESSES, createCallbackAddress()) .add(OFFER, Json.createObjectBuilder() .add(OFFER_ID, "test-offer-id") @@ -109,7 +107,6 @@ void transform() { assertThat(dto.getProtocol()).isEqualTo("test-protocol"); assertThat(dto.getCounterPartyAddress()).isEqualTo("test-address"); assertThat(dto.getCounterPartyId()).isEqualTo("test-conn-id"); - assertThat(dto.getProviderId()).isEqualTo("test-provider-id"); assertThat(dto.getOffer()).isNotNull(); } diff --git a/edc-extensions/edr/edr-api-v2/src/test/java/org/eclipse/tractusx/edc/api/edr/v2/validation/NegotiateEdrRequestDtoValidatorTest.java b/edc-extensions/edr/edr-api-v2/src/test/java/org/eclipse/tractusx/edc/api/edr/v2/validation/NegotiateEdrRequestDtoValidatorTest.java index 6dfc87b2b..8f75402e0 100644 --- a/edc-extensions/edr/edr-api-v2/src/test/java/org/eclipse/tractusx/edc/api/edr/v2/validation/NegotiateEdrRequestDtoValidatorTest.java +++ b/edc-extensions/edr/edr-api-v2/src/test/java/org/eclipse/tractusx/edc/api/edr/v2/validation/NegotiateEdrRequestDtoValidatorTest.java @@ -31,9 +31,9 @@ import static jakarta.json.Json.createObjectBuilder; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.InstanceOfAssertFactories.list; -import static org.eclipse.edc.connector.api.management.contractnegotiation.model.ContractOfferDescription.ASSET_ID; -import static org.eclipse.edc.connector.api.management.contractnegotiation.model.ContractOfferDescription.OFFER_ID; -import static org.eclipse.edc.connector.api.management.contractnegotiation.model.ContractOfferDescription.POLICY; +import static org.eclipse.edc.connector.controlplane.api.management.contractnegotiation.model.ContractOfferDescription.ASSET_ID; +import static org.eclipse.edc.connector.controlplane.api.management.contractnegotiation.model.ContractOfferDescription.OFFER_ID; +import static org.eclipse.edc.connector.controlplane.api.management.contractnegotiation.model.ContractOfferDescription.POLICY; import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.VALUE; import static org.eclipse.edc.junit.assertions.AbstractResultAssert.assertThat; import static org.eclipse.tractusx.edc.api.edr.v2.dto.NegotiateEdrRequestDto.EDR_REQUEST_DTO_COUNTERPARTY_ADDRESS; diff --git a/edc-extensions/edr/edr-callback/src/main/java/org/eclipse/tractusx/edc/callback/ContractNegotiationCallback.java b/edc-extensions/edr/edr-callback/src/main/java/org/eclipse/tractusx/edc/callback/ContractNegotiationCallback.java index bb537a9e8..015bf53ab 100644 --- a/edc-extensions/edr/edr-callback/src/main/java/org/eclipse/tractusx/edc/callback/ContractNegotiationCallback.java +++ b/edc-extensions/edr/edr-callback/src/main/java/org/eclipse/tractusx/edc/callback/ContractNegotiationCallback.java @@ -19,10 +19,10 @@ package org.eclipse.tractusx.edc.callback; -import org.eclipse.edc.connector.contract.spi.event.contractnegotiation.ContractNegotiationFinalized; -import org.eclipse.edc.connector.spi.callback.CallbackEventRemoteMessage; -import org.eclipse.edc.connector.spi.transferprocess.TransferProcessService; -import org.eclipse.edc.connector.transfer.spi.types.TransferRequest; +import org.eclipse.edc.connector.controlplane.contract.spi.event.contractnegotiation.ContractNegotiationFinalized; +import org.eclipse.edc.connector.controlplane.services.spi.callback.CallbackEventRemoteMessage; +import org.eclipse.edc.connector.controlplane.services.spi.transferprocess.TransferProcessService; +import org.eclipse.edc.connector.controlplane.transfer.spi.types.TransferRequest; import org.eclipse.edc.spi.event.Event; import org.eclipse.edc.spi.monitor.Monitor; import org.eclipse.edc.spi.result.Result; diff --git a/edc-extensions/edr/edr-callback/src/main/java/org/eclipse/tractusx/edc/callback/InProcessCallbackMessageDispatcher.java b/edc-extensions/edr/edr-callback/src/main/java/org/eclipse/tractusx/edc/callback/InProcessCallbackMessageDispatcher.java index d540d9fcf..67287114b 100644 --- a/edc-extensions/edr/edr-callback/src/main/java/org/eclipse/tractusx/edc/callback/InProcessCallbackMessageDispatcher.java +++ b/edc-extensions/edr/edr-callback/src/main/java/org/eclipse/tractusx/edc/callback/InProcessCallbackMessageDispatcher.java @@ -19,7 +19,7 @@ package org.eclipse.tractusx.edc.callback; -import org.eclipse.edc.connector.spi.callback.CallbackEventRemoteMessage; +import org.eclipse.edc.connector.controlplane.services.spi.callback.CallbackEventRemoteMessage; import org.eclipse.edc.spi.EdcException; import org.eclipse.edc.spi.event.Event; import org.eclipse.edc.spi.message.RemoteMessageDispatcher; diff --git a/edc-extensions/edr/edr-callback/src/main/java/org/eclipse/tractusx/edc/callback/InProcessCallbackRegistryImpl.java b/edc-extensions/edr/edr-callback/src/main/java/org/eclipse/tractusx/edc/callback/InProcessCallbackRegistryImpl.java index c03e660c3..c91b742a2 100644 --- a/edc-extensions/edr/edr-callback/src/main/java/org/eclipse/tractusx/edc/callback/InProcessCallbackRegistryImpl.java +++ b/edc-extensions/edr/edr-callback/src/main/java/org/eclipse/tractusx/edc/callback/InProcessCallbackRegistryImpl.java @@ -19,7 +19,7 @@ package org.eclipse.tractusx.edc.callback; -import org.eclipse.edc.connector.spi.callback.CallbackEventRemoteMessage; +import org.eclipse.edc.connector.controlplane.services.spi.callback.CallbackEventRemoteMessage; import org.eclipse.edc.spi.event.Event; import org.eclipse.edc.spi.result.Result; import org.eclipse.tractusx.edc.spi.callback.InProcessCallback; diff --git a/edc-extensions/edr/edr-callback/src/main/java/org/eclipse/tractusx/edc/callback/LocalCallbackExtension.java b/edc-extensions/edr/edr-callback/src/main/java/org/eclipse/tractusx/edc/callback/LocalCallbackExtension.java index e0fe5d9ee..a13220d36 100644 --- a/edc-extensions/edr/edr-callback/src/main/java/org/eclipse/tractusx/edc/callback/LocalCallbackExtension.java +++ b/edc-extensions/edr/edr-callback/src/main/java/org/eclipse/tractusx/edc/callback/LocalCallbackExtension.java @@ -19,9 +19,9 @@ package org.eclipse.tractusx.edc.callback; -import org.eclipse.edc.connector.spi.callback.CallbackProtocolResolverRegistry; -import org.eclipse.edc.connector.spi.contractagreement.ContractAgreementService; -import org.eclipse.edc.connector.spi.transferprocess.TransferProcessService; +import org.eclipse.edc.connector.controlplane.services.spi.callback.CallbackProtocolResolverRegistry; +import org.eclipse.edc.connector.controlplane.services.spi.contractagreement.ContractAgreementService; +import org.eclipse.edc.connector.controlplane.services.spi.transferprocess.TransferProcessService; import org.eclipse.edc.runtime.metamodel.annotation.Extension; import org.eclipse.edc.runtime.metamodel.annotation.Inject; import org.eclipse.edc.spi.message.RemoteMessageDispatcherRegistry; @@ -56,7 +56,7 @@ public class LocalCallbackExtension implements ServiceExtension { @Inject private TransactionContext transactionContext; - + @Inject private ContractAgreementService agreementService; diff --git a/edc-extensions/edr/edr-callback/src/test/java/org/eclipse/tractusx/edc/callback/ContractNegotiationCallbackTest.java b/edc-extensions/edr/edr-callback/src/test/java/org/eclipse/tractusx/edc/callback/ContractNegotiationCallbackTest.java index c38d27bcb..9247bda85 100644 --- a/edc-extensions/edr/edr-callback/src/test/java/org/eclipse/tractusx/edc/callback/ContractNegotiationCallbackTest.java +++ b/edc-extensions/edr/edr-callback/src/test/java/org/eclipse/tractusx/edc/callback/ContractNegotiationCallbackTest.java @@ -19,22 +19,22 @@ package org.eclipse.tractusx.edc.callback; -import org.eclipse.edc.connector.contract.spi.event.contractnegotiation.ContractNegotiationAccepted; -import org.eclipse.edc.connector.contract.spi.event.contractnegotiation.ContractNegotiationAgreed; -import org.eclipse.edc.connector.contract.spi.event.contractnegotiation.ContractNegotiationEvent; -import org.eclipse.edc.connector.contract.spi.event.contractnegotiation.ContractNegotiationFinalized; -import org.eclipse.edc.connector.contract.spi.event.contractnegotiation.ContractNegotiationInitiated; -import org.eclipse.edc.connector.contract.spi.event.contractnegotiation.ContractNegotiationOffered; -import org.eclipse.edc.connector.contract.spi.event.contractnegotiation.ContractNegotiationRequested; -import org.eclipse.edc.connector.contract.spi.event.contractnegotiation.ContractNegotiationTerminated; -import org.eclipse.edc.connector.contract.spi.event.contractnegotiation.ContractNegotiationVerified; -import org.eclipse.edc.connector.spi.transferprocess.TransferProcessService; -import org.eclipse.edc.connector.transfer.spi.types.TransferProcess; -import org.eclipse.edc.connector.transfer.spi.types.TransferRequest; +import org.eclipse.edc.connector.controlplane.contract.spi.event.contractnegotiation.ContractNegotiationAccepted; +import org.eclipse.edc.connector.controlplane.contract.spi.event.contractnegotiation.ContractNegotiationAgreed; +import org.eclipse.edc.connector.controlplane.contract.spi.event.contractnegotiation.ContractNegotiationEvent; +import org.eclipse.edc.connector.controlplane.contract.spi.event.contractnegotiation.ContractNegotiationFinalized; +import org.eclipse.edc.connector.controlplane.contract.spi.event.contractnegotiation.ContractNegotiationInitiated; +import org.eclipse.edc.connector.controlplane.contract.spi.event.contractnegotiation.ContractNegotiationOffered; +import org.eclipse.edc.connector.controlplane.contract.spi.event.contractnegotiation.ContractNegotiationRequested; +import org.eclipse.edc.connector.controlplane.contract.spi.event.contractnegotiation.ContractNegotiationTerminated; +import org.eclipse.edc.connector.controlplane.contract.spi.event.contractnegotiation.ContractNegotiationVerified; +import org.eclipse.edc.connector.controlplane.contract.spi.types.agreement.ContractAgreement; +import org.eclipse.edc.connector.controlplane.services.spi.transferprocess.TransferProcessService; +import org.eclipse.edc.connector.controlplane.transfer.spi.types.TransferProcess; +import org.eclipse.edc.connector.controlplane.transfer.spi.types.TransferRequest; import org.eclipse.edc.policy.model.Policy; import org.eclipse.edc.spi.monitor.Monitor; import org.eclipse.edc.spi.result.ServiceResult; -import org.eclipse.edc.spi.types.domain.agreement.ContractAgreement; import org.eclipse.edc.spi.types.domain.callback.CallbackAddress; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; diff --git a/edc-extensions/edr/edr-callback/src/test/java/org/eclipse/tractusx/edc/callback/LocalCallbackExtensionTest.java b/edc-extensions/edr/edr-callback/src/test/java/org/eclipse/tractusx/edc/callback/LocalCallbackExtensionTest.java index d0ba7ce27..1c764c360 100644 --- a/edc-extensions/edr/edr-callback/src/test/java/org/eclipse/tractusx/edc/callback/LocalCallbackExtensionTest.java +++ b/edc-extensions/edr/edr-callback/src/test/java/org/eclipse/tractusx/edc/callback/LocalCallbackExtensionTest.java @@ -19,8 +19,8 @@ package org.eclipse.tractusx.edc.callback; -import org.eclipse.edc.connector.spi.callback.CallbackProtocolResolver; -import org.eclipse.edc.connector.spi.callback.CallbackProtocolResolverRegistry; +import org.eclipse.edc.connector.controlplane.services.spi.callback.CallbackProtocolResolver; +import org.eclipse.edc.connector.controlplane.services.spi.callback.CallbackProtocolResolverRegistry; import org.eclipse.edc.junit.extensions.DependencyInjectionExtension; import org.eclipse.edc.spi.message.RemoteMessageDispatcherRegistry; import org.eclipse.edc.spi.system.ServiceExtensionContext; diff --git a/edc-extensions/edr/edr-callback/src/test/java/org/eclipse/tractusx/edc/callback/TestFunctions.java b/edc-extensions/edr/edr-callback/src/test/java/org/eclipse/tractusx/edc/callback/TestFunctions.java index 724d52dfd..7fa7a36f8 100644 --- a/edc-extensions/edr/edr-callback/src/test/java/org/eclipse/tractusx/edc/callback/TestFunctions.java +++ b/edc-extensions/edr/edr-callback/src/test/java/org/eclipse/tractusx/edc/callback/TestFunctions.java @@ -27,15 +27,15 @@ import com.nimbusds.jose.jwk.gen.RSAKeyGenerator; import com.nimbusds.jwt.JWTClaimsSet; import com.nimbusds.jwt.SignedJWT; -import org.eclipse.edc.connector.contract.spi.event.contractnegotiation.ContractNegotiationFinalized; -import org.eclipse.edc.connector.spi.callback.CallbackEventRemoteMessage; -import org.eclipse.edc.connector.transfer.spi.event.TransferProcessStarted; -import org.eclipse.edc.connector.transfer.spi.event.TransferProcessTerminated; +import org.eclipse.edc.connector.controlplane.contract.spi.event.contractnegotiation.ContractNegotiationFinalized; +import org.eclipse.edc.connector.controlplane.contract.spi.types.agreement.ContractAgreement; +import org.eclipse.edc.connector.controlplane.services.spi.callback.CallbackEventRemoteMessage; +import org.eclipse.edc.connector.controlplane.transfer.spi.event.TransferProcessStarted; +import org.eclipse.edc.connector.controlplane.transfer.spi.event.TransferProcessTerminated; import org.eclipse.edc.policy.model.Policy; import org.eclipse.edc.spi.event.Event; import org.eclipse.edc.spi.event.EventEnvelope; import org.eclipse.edc.spi.types.domain.DataAddress; -import org.eclipse.edc.spi.types.domain.agreement.ContractAgreement; import org.eclipse.edc.spi.types.domain.callback.CallbackAddress; import java.time.Instant; diff --git a/edc-extensions/iatp/tx-iatp-sts-dim/src/main/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/DimSecureTokenService.java b/edc-extensions/iatp/tx-iatp-sts-dim/src/main/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/DimSecureTokenService.java index aef7c5a5e..f6b1f9e5f 100644 --- a/edc-extensions/iatp/tx-iatp-sts-dim/src/main/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/DimSecureTokenService.java +++ b/edc-extensions/iatp/tx-iatp-sts-dim/src/main/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/DimSecureTokenService.java @@ -26,8 +26,8 @@ import okhttp3.Request; import okhttp3.RequestBody; import okhttp3.Response; +import org.eclipse.edc.http.spi.EdcHttpClient; import org.eclipse.edc.identitytrust.SecureTokenService; -import org.eclipse.edc.spi.http.EdcHttpClient; import org.eclipse.edc.spi.iam.TokenRepresentation; import org.eclipse.edc.spi.monitor.Monitor; import org.eclipse.edc.spi.result.Result; @@ -47,11 +47,11 @@ import java.util.function.Consumer; import static java.lang.String.format; +import static org.eclipse.edc.http.spi.FallbackFactories.retryWhenStatusIsNotIn; import static org.eclipse.edc.identitytrust.SelfIssuedTokenConstants.PRESENTATION_TOKEN_CLAIM; import static org.eclipse.edc.jwt.spi.JwtRegisteredClaimNames.AUDIENCE; import static org.eclipse.edc.jwt.spi.JwtRegisteredClaimNames.ISSUER; import static org.eclipse.edc.jwt.spi.JwtRegisteredClaimNames.SUBJECT; -import static org.eclipse.edc.spi.http.FallbackFactories.retryWhenStatusIsNotIn; /** * Implementation of {@link SecureTokenService} that talks with DIM wallet. It supports two APIs for fetching the diff --git a/edc-extensions/iatp/tx-iatp-sts-dim/src/main/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/DimSecureTokenServiceExtension.java b/edc-extensions/iatp/tx-iatp-sts-dim/src/main/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/DimSecureTokenServiceExtension.java index 0722510f8..165b55db8 100644 --- a/edc-extensions/iatp/tx-iatp-sts-dim/src/main/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/DimSecureTokenServiceExtension.java +++ b/edc-extensions/iatp/tx-iatp-sts-dim/src/main/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/DimSecureTokenServiceExtension.java @@ -19,12 +19,12 @@ package org.eclipse.tractusx.edc.iam.iatp.sts.dim; +import org.eclipse.edc.http.spi.EdcHttpClient; import org.eclipse.edc.identitytrust.SecureTokenService; import org.eclipse.edc.runtime.metamodel.annotation.Extension; import org.eclipse.edc.runtime.metamodel.annotation.Inject; import org.eclipse.edc.runtime.metamodel.annotation.Provider; import org.eclipse.edc.runtime.metamodel.annotation.Setting; -import org.eclipse.edc.spi.http.EdcHttpClient; import org.eclipse.edc.spi.monitor.Monitor; import org.eclipse.edc.spi.system.ServiceExtension; import org.eclipse.edc.spi.system.ServiceExtensionContext; diff --git a/edc-extensions/iatp/tx-iatp-sts-dim/src/test/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/DimSecureTokenServiceTest.java b/edc-extensions/iatp/tx-iatp-sts-dim/src/test/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/DimSecureTokenServiceTest.java index ef4a0a758..cef39d4f8 100644 --- a/edc-extensions/iatp/tx-iatp-sts-dim/src/test/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/DimSecureTokenServiceTest.java +++ b/edc-extensions/iatp/tx-iatp-sts-dim/src/test/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/DimSecureTokenServiceTest.java @@ -45,12 +45,12 @@ import java.util.function.Consumer; import static org.assertj.core.api.Assertions.assertThat; +import static org.eclipse.edc.http.client.testfixtures.HttpTestUtils.testHttpClient; import static org.eclipse.edc.identitytrust.SelfIssuedTokenConstants.PRESENTATION_TOKEN_CLAIM; import static org.eclipse.edc.junit.assertions.AbstractResultAssert.assertThat; import static org.eclipse.edc.jwt.spi.JwtRegisteredClaimNames.AUDIENCE; import static org.eclipse.edc.jwt.spi.JwtRegisteredClaimNames.ISSUER; import static org.eclipse.edc.jwt.spi.JwtRegisteredClaimNames.SUBJECT; -import static org.eclipse.http.client.testfixtures.HttpTestUtils.testHttpClient; import static org.mockito.ArgumentMatchers.isA; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; diff --git a/edc-extensions/postgresql-migration/src/test/java/org/eclipse/tractusx/edc/postgresql/migration/AssetPostgresqlMigrationExtensionTest.java b/edc-extensions/postgresql-migration/src/test/java/org/eclipse/tractusx/edc/postgresql/migration/AssetPostgresqlMigrationExtensionTest.java index 34a332f45..2d18a999e 100644 --- a/edc-extensions/postgresql-migration/src/test/java/org/eclipse/tractusx/edc/postgresql/migration/AssetPostgresqlMigrationExtensionTest.java +++ b/edc-extensions/postgresql-migration/src/test/java/org/eclipse/tractusx/edc/postgresql/migration/AssetPostgresqlMigrationExtensionTest.java @@ -19,11 +19,11 @@ package org.eclipse.tractusx.edc.postgresql.migration; -import org.eclipse.edc.connector.store.sql.assetindex.SqlAssetIndex; -import org.eclipse.edc.connector.store.sql.assetindex.schema.postgres.PostgresDialectStatements; +import org.eclipse.edc.connector.controlplane.asset.spi.domain.Asset; +import org.eclipse.edc.connector.controlplane.store.sql.assetindex.SqlAssetIndex; +import org.eclipse.edc.connector.controlplane.store.sql.assetindex.schema.postgres.PostgresDialectStatements; import org.eclipse.edc.junit.annotations.PostgresqlIntegrationTest; import org.eclipse.edc.spi.types.TypeManager; -import org.eclipse.edc.spi.types.domain.asset.Asset; import org.eclipse.edc.sql.QueryExecutor; import org.eclipse.edc.sql.testfixtures.PostgresqlStoreSetupExtension; import org.flywaydb.core.api.MigrationVersion; diff --git a/edc-extensions/provision-additional-headers/src/main/java/org/eclipse/tractusx/edc/provision/additionalheaders/AdditionalHeadersProvisionedResource.java b/edc-extensions/provision-additional-headers/src/main/java/org/eclipse/tractusx/edc/provision/additionalheaders/AdditionalHeadersProvisionedResource.java index 23ead4361..f6d3a6751 100644 --- a/edc-extensions/provision-additional-headers/src/main/java/org/eclipse/tractusx/edc/provision/additionalheaders/AdditionalHeadersProvisionedResource.java +++ b/edc-extensions/provision-additional-headers/src/main/java/org/eclipse/tractusx/edc/provision/additionalheaders/AdditionalHeadersProvisionedResource.java @@ -23,7 +23,7 @@ import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder; -import org.eclipse.edc.connector.transfer.spi.types.ProvisionedContentResource; +import org.eclipse.edc.connector.controlplane.transfer.spi.types.ProvisionedContentResource; @JsonDeserialize(builder = AdditionalHeadersProvisionedResource.Builder.class) class AdditionalHeadersProvisionedResource extends ProvisionedContentResource { diff --git a/edc-extensions/provision-additional-headers/src/main/java/org/eclipse/tractusx/edc/provision/additionalheaders/AdditionalHeadersProvisioner.java b/edc-extensions/provision-additional-headers/src/main/java/org/eclipse/tractusx/edc/provision/additionalheaders/AdditionalHeadersProvisioner.java index f810b4af2..80e2ab166 100644 --- a/edc-extensions/provision-additional-headers/src/main/java/org/eclipse/tractusx/edc/provision/additionalheaders/AdditionalHeadersProvisioner.java +++ b/edc-extensions/provision-additional-headers/src/main/java/org/eclipse/tractusx/edc/provision/additionalheaders/AdditionalHeadersProvisioner.java @@ -20,12 +20,12 @@ package org.eclipse.tractusx.edc.provision.additionalheaders; +import org.eclipse.edc.connector.controlplane.transfer.spi.provision.Provisioner; +import org.eclipse.edc.connector.controlplane.transfer.spi.types.DeprovisionedResource; +import org.eclipse.edc.connector.controlplane.transfer.spi.types.ProvisionResponse; +import org.eclipse.edc.connector.controlplane.transfer.spi.types.ProvisionedResource; +import org.eclipse.edc.connector.controlplane.transfer.spi.types.ResourceDefinition; import org.eclipse.edc.connector.dataplane.http.spi.HttpDataAddress; -import org.eclipse.edc.connector.transfer.spi.provision.Provisioner; -import org.eclipse.edc.connector.transfer.spi.types.DeprovisionedResource; -import org.eclipse.edc.connector.transfer.spi.types.ProvisionResponse; -import org.eclipse.edc.connector.transfer.spi.types.ProvisionedResource; -import org.eclipse.edc.connector.transfer.spi.types.ResourceDefinition; import org.eclipse.edc.policy.model.Policy; import org.eclipse.edc.spi.response.StatusResult; diff --git a/edc-extensions/provision-additional-headers/src/main/java/org/eclipse/tractusx/edc/provision/additionalheaders/AdditionalHeadersResourceDefinition.java b/edc-extensions/provision-additional-headers/src/main/java/org/eclipse/tractusx/edc/provision/additionalheaders/AdditionalHeadersResourceDefinition.java index 6ce362c0e..3b2536fd6 100644 --- a/edc-extensions/provision-additional-headers/src/main/java/org/eclipse/tractusx/edc/provision/additionalheaders/AdditionalHeadersResourceDefinition.java +++ b/edc-extensions/provision-additional-headers/src/main/java/org/eclipse/tractusx/edc/provision/additionalheaders/AdditionalHeadersResourceDefinition.java @@ -24,7 +24,7 @@ import com.fasterxml.jackson.annotation.JsonTypeName; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder; -import org.eclipse.edc.connector.transfer.spi.types.ResourceDefinition; +import org.eclipse.edc.connector.controlplane.transfer.spi.types.ResourceDefinition; import org.eclipse.edc.spi.types.domain.DataAddress; @JsonDeserialize(builder = AdditionalHeadersResourceDefinition.Builder.class) diff --git a/edc-extensions/provision-additional-headers/src/main/java/org/eclipse/tractusx/edc/provision/additionalheaders/AdditionalHeadersResourceDefinitionGenerator.java b/edc-extensions/provision-additional-headers/src/main/java/org/eclipse/tractusx/edc/provision/additionalheaders/AdditionalHeadersResourceDefinitionGenerator.java index 26f12fa15..5baa3e5e9 100644 --- a/edc-extensions/provision-additional-headers/src/main/java/org/eclipse/tractusx/edc/provision/additionalheaders/AdditionalHeadersResourceDefinitionGenerator.java +++ b/edc-extensions/provision-additional-headers/src/main/java/org/eclipse/tractusx/edc/provision/additionalheaders/AdditionalHeadersResourceDefinitionGenerator.java @@ -20,13 +20,13 @@ package org.eclipse.tractusx.edc.provision.additionalheaders; -import org.eclipse.edc.connector.spi.contractagreement.ContractAgreementService; -import org.eclipse.edc.connector.transfer.spi.provision.ProviderResourceDefinitionGenerator; -import org.eclipse.edc.connector.transfer.spi.types.ResourceDefinition; -import org.eclipse.edc.connector.transfer.spi.types.TransferProcess; +import org.eclipse.edc.connector.controlplane.contract.spi.types.agreement.ContractAgreement; +import org.eclipse.edc.connector.controlplane.services.spi.contractagreement.ContractAgreementService; +import org.eclipse.edc.connector.controlplane.transfer.spi.provision.ProviderResourceDefinitionGenerator; +import org.eclipse.edc.connector.controlplane.transfer.spi.types.ResourceDefinition; +import org.eclipse.edc.connector.controlplane.transfer.spi.types.TransferProcess; import org.eclipse.edc.policy.model.Policy; import org.eclipse.edc.spi.types.domain.DataAddress; -import org.eclipse.edc.spi.types.domain.agreement.ContractAgreement; import org.jetbrains.annotations.Nullable; import java.util.Optional; diff --git a/edc-extensions/provision-additional-headers/src/main/java/org/eclipse/tractusx/edc/provision/additionalheaders/ProvisionAdditionalHeadersExtension.java b/edc-extensions/provision-additional-headers/src/main/java/org/eclipse/tractusx/edc/provision/additionalheaders/ProvisionAdditionalHeadersExtension.java index b1322de9a..321d6b655 100644 --- a/edc-extensions/provision-additional-headers/src/main/java/org/eclipse/tractusx/edc/provision/additionalheaders/ProvisionAdditionalHeadersExtension.java +++ b/edc-extensions/provision-additional-headers/src/main/java/org/eclipse/tractusx/edc/provision/additionalheaders/ProvisionAdditionalHeadersExtension.java @@ -20,9 +20,9 @@ package org.eclipse.tractusx.edc.provision.additionalheaders; -import org.eclipse.edc.connector.spi.contractagreement.ContractAgreementService; -import org.eclipse.edc.connector.transfer.spi.provision.ProvisionManager; -import org.eclipse.edc.connector.transfer.spi.provision.ResourceManifestGenerator; +import org.eclipse.edc.connector.controlplane.services.spi.contractagreement.ContractAgreementService; +import org.eclipse.edc.connector.controlplane.transfer.spi.provision.ProvisionManager; +import org.eclipse.edc.connector.controlplane.transfer.spi.provision.ResourceManifestGenerator; import org.eclipse.edc.runtime.metamodel.annotation.Inject; import org.eclipse.edc.spi.system.ServiceExtension; import org.eclipse.edc.spi.system.ServiceExtensionContext; diff --git a/edc-extensions/provision-additional-headers/src/test/java/org/eclipse/tractusx/edc/provision/additionalheaders/AdditionalHeadersProvisionerTest.java b/edc-extensions/provision-additional-headers/src/test/java/org/eclipse/tractusx/edc/provision/additionalheaders/AdditionalHeadersProvisionerTest.java index f15c72f6d..1a3a986c2 100644 --- a/edc-extensions/provision-additional-headers/src/test/java/org/eclipse/tractusx/edc/provision/additionalheaders/AdditionalHeadersProvisionerTest.java +++ b/edc-extensions/provision-additional-headers/src/test/java/org/eclipse/tractusx/edc/provision/additionalheaders/AdditionalHeadersProvisionerTest.java @@ -20,11 +20,11 @@ package org.eclipse.tractusx.edc.provision.additionalheaders; +import org.eclipse.edc.connector.controlplane.transfer.spi.types.ProvisionResponse; +import org.eclipse.edc.connector.controlplane.transfer.spi.types.ProvisionedDataAddressResource; +import org.eclipse.edc.connector.controlplane.transfer.spi.types.ProvisionedResource; +import org.eclipse.edc.connector.controlplane.transfer.spi.types.ResourceDefinition; import org.eclipse.edc.connector.dataplane.http.spi.HttpDataAddress; -import org.eclipse.edc.connector.transfer.spi.types.ProvisionResponse; -import org.eclipse.edc.connector.transfer.spi.types.ProvisionedDataAddressResource; -import org.eclipse.edc.connector.transfer.spi.types.ProvisionedResource; -import org.eclipse.edc.connector.transfer.spi.types.ResourceDefinition; import org.eclipse.edc.policy.model.Policy; import org.eclipse.edc.spi.response.StatusResult; import org.junit.jupiter.api.Test; @@ -66,7 +66,6 @@ void shouldAddAdditionalHeaders() { .build(); var result = provisioner.provision(resourceDefinition, Policy.Builder.newInstance().build()); - assertThat(result) .succeedsWithin(5, SECONDS) .matches(StatusResult::succeeded) diff --git a/edc-extensions/provision-additional-headers/src/test/java/org/eclipse/tractusx/edc/provision/additionalheaders/AdditionalHeadersResourceDefinitionGeneratorTest.java b/edc-extensions/provision-additional-headers/src/test/java/org/eclipse/tractusx/edc/provision/additionalheaders/AdditionalHeadersResourceDefinitionGeneratorTest.java index 81e03b8d9..0dff0d818 100644 --- a/edc-extensions/provision-additional-headers/src/test/java/org/eclipse/tractusx/edc/provision/additionalheaders/AdditionalHeadersResourceDefinitionGeneratorTest.java +++ b/edc-extensions/provision-additional-headers/src/test/java/org/eclipse/tractusx/edc/provision/additionalheaders/AdditionalHeadersResourceDefinitionGeneratorTest.java @@ -20,13 +20,13 @@ package org.eclipse.tractusx.edc.provision.additionalheaders; +import org.eclipse.edc.connector.controlplane.contract.spi.types.agreement.ContractAgreement; +import org.eclipse.edc.connector.controlplane.services.spi.contractagreement.ContractAgreementService; +import org.eclipse.edc.connector.controlplane.transfer.spi.provision.ProviderResourceDefinitionGenerator; +import org.eclipse.edc.connector.controlplane.transfer.spi.types.TransferProcess; import org.eclipse.edc.connector.dataplane.http.spi.HttpDataAddress; -import org.eclipse.edc.connector.spi.contractagreement.ContractAgreementService; -import org.eclipse.edc.connector.transfer.spi.provision.ProviderResourceDefinitionGenerator; -import org.eclipse.edc.connector.transfer.spi.types.TransferProcess; import org.eclipse.edc.policy.model.Policy; import org.eclipse.edc.spi.types.domain.DataAddress; -import org.eclipse.edc.spi.types.domain.agreement.ContractAgreement; import org.junit.jupiter.api.Test; import java.util.UUID; diff --git a/edc-extensions/provision-additional-headers/src/test/java/org/eclipse/tractusx/edc/provision/additionalheaders/ProvisionAdditionalHeadersExtensionTest.java b/edc-extensions/provision-additional-headers/src/test/java/org/eclipse/tractusx/edc/provision/additionalheaders/ProvisionAdditionalHeadersExtensionTest.java index 3e86729e0..b05713cee 100644 --- a/edc-extensions/provision-additional-headers/src/test/java/org/eclipse/tractusx/edc/provision/additionalheaders/ProvisionAdditionalHeadersExtensionTest.java +++ b/edc-extensions/provision-additional-headers/src/test/java/org/eclipse/tractusx/edc/provision/additionalheaders/ProvisionAdditionalHeadersExtensionTest.java @@ -20,8 +20,8 @@ package org.eclipse.tractusx.edc.provision.additionalheaders; -import org.eclipse.edc.connector.transfer.spi.provision.ProvisionManager; -import org.eclipse.edc.connector.transfer.spi.provision.ResourceManifestGenerator; +import org.eclipse.edc.connector.controlplane.transfer.spi.provision.ProvisionManager; +import org.eclipse.edc.connector.controlplane.transfer.spi.provision.ResourceManifestGenerator; import org.eclipse.edc.junit.extensions.DependencyInjectionExtension; import org.eclipse.edc.spi.system.ServiceExtensionContext; import org.junit.jupiter.api.BeforeEach; diff --git a/edc-extensions/tokenrefresh-handler/src/main/java/org/eclipse/tractusx/edc/common/tokenrefresh/TokenRefreshHandlerExtension.java b/edc-extensions/tokenrefresh-handler/src/main/java/org/eclipse/tractusx/edc/common/tokenrefresh/TokenRefreshHandlerExtension.java index 607a75817..f5a320332 100644 --- a/edc-extensions/tokenrefresh-handler/src/main/java/org/eclipse/tractusx/edc/common/tokenrefresh/TokenRefreshHandlerExtension.java +++ b/edc-extensions/tokenrefresh-handler/src/main/java/org/eclipse/tractusx/edc/common/tokenrefresh/TokenRefreshHandlerExtension.java @@ -20,11 +20,11 @@ package org.eclipse.tractusx.edc.common.tokenrefresh; import org.eclipse.edc.edr.spi.store.EndpointDataReferenceCache; +import org.eclipse.edc.http.spi.EdcHttpClient; import org.eclipse.edc.identitytrust.SecureTokenService; import org.eclipse.edc.runtime.metamodel.annotation.Extension; import org.eclipse.edc.runtime.metamodel.annotation.Inject; import org.eclipse.edc.runtime.metamodel.annotation.Provider; -import org.eclipse.edc.spi.http.EdcHttpClient; import org.eclipse.edc.spi.system.ServiceExtension; import org.eclipse.edc.spi.system.ServiceExtensionContext; import org.eclipse.edc.spi.types.TypeManager; diff --git a/edc-extensions/tokenrefresh-handler/src/main/java/org/eclipse/tractusx/edc/common/tokenrefresh/TokenRefreshHandlerImpl.java b/edc-extensions/tokenrefresh-handler/src/main/java/org/eclipse/tractusx/edc/common/tokenrefresh/TokenRefreshHandlerImpl.java index 329827d2c..dd59927ad 100644 --- a/edc-extensions/tokenrefresh-handler/src/main/java/org/eclipse/tractusx/edc/common/tokenrefresh/TokenRefreshHandlerImpl.java +++ b/edc-extensions/tokenrefresh-handler/src/main/java/org/eclipse/tractusx/edc/common/tokenrefresh/TokenRefreshHandlerImpl.java @@ -25,8 +25,8 @@ import okhttp3.Request; import okhttp3.RequestBody; import org.eclipse.edc.edr.spi.store.EndpointDataReferenceCache; +import org.eclipse.edc.http.spi.EdcHttpClient; import org.eclipse.edc.identitytrust.SecureTokenService; -import org.eclipse.edc.spi.http.EdcHttpClient; import org.eclipse.edc.spi.monitor.Monitor; import org.eclipse.edc.spi.result.Result; import org.eclipse.edc.spi.result.ServiceResult; diff --git a/edc-extensions/tokenrefresh-handler/src/test/java/org/eclipse/tractusx/edc/common/tokenrefresh/TokenRefreshHandlerImplTest.java b/edc-extensions/tokenrefresh-handler/src/test/java/org/eclipse/tractusx/edc/common/tokenrefresh/TokenRefreshHandlerImplTest.java index f0e603450..d77b9b43e 100644 --- a/edc-extensions/tokenrefresh-handler/src/test/java/org/eclipse/tractusx/edc/common/tokenrefresh/TokenRefreshHandlerImplTest.java +++ b/edc-extensions/tokenrefresh-handler/src/test/java/org/eclipse/tractusx/edc/common/tokenrefresh/TokenRefreshHandlerImplTest.java @@ -36,8 +36,8 @@ import okhttp3.ResponseBody; import org.assertj.core.api.Assertions; import org.eclipse.edc.edr.spi.store.EndpointDataReferenceCache; +import org.eclipse.edc.http.spi.EdcHttpClient; import org.eclipse.edc.identitytrust.SecureTokenService; -import org.eclipse.edc.spi.http.EdcHttpClient; import org.eclipse.edc.spi.iam.TokenRepresentation; import org.eclipse.edc.spi.result.Result; import org.eclipse.edc.spi.result.StoreResult; diff --git a/edc-extensions/transferprocess-sftp-provisioner/src/main/java/org/eclipse/tractusx/edc/transferprocess/sftp/provisioner/NoOpSftpProvisioner.java b/edc-extensions/transferprocess-sftp-provisioner/src/main/java/org/eclipse/tractusx/edc/transferprocess/sftp/provisioner/NoOpSftpProvisioner.java index 0aa507416..a0dc9891d 100644 --- a/edc-extensions/transferprocess-sftp-provisioner/src/main/java/org/eclipse/tractusx/edc/transferprocess/sftp/provisioner/NoOpSftpProvisioner.java +++ b/edc-extensions/transferprocess-sftp-provisioner/src/main/java/org/eclipse/tractusx/edc/transferprocess/sftp/provisioner/NoOpSftpProvisioner.java @@ -19,11 +19,11 @@ package org.eclipse.tractusx.edc.transferprocess.sftp.provisioner; -import org.eclipse.edc.connector.transfer.spi.provision.Provisioner; -import org.eclipse.edc.connector.transfer.spi.types.DeprovisionedResource; -import org.eclipse.edc.connector.transfer.spi.types.ProvisionResponse; -import org.eclipse.edc.connector.transfer.spi.types.ProvisionedResource; -import org.eclipse.edc.connector.transfer.spi.types.ResourceDefinition; +import org.eclipse.edc.connector.controlplane.transfer.spi.provision.Provisioner; +import org.eclipse.edc.connector.controlplane.transfer.spi.types.DeprovisionedResource; +import org.eclipse.edc.connector.controlplane.transfer.spi.types.ProvisionResponse; +import org.eclipse.edc.connector.controlplane.transfer.spi.types.ProvisionedResource; +import org.eclipse.edc.connector.controlplane.transfer.spi.types.ResourceDefinition; import org.eclipse.edc.policy.engine.spi.PolicyEngine; import org.eclipse.edc.policy.model.Policy; import org.eclipse.edc.spi.response.ResponseStatus; diff --git a/edc-extensions/transferprocess-sftp-provisioner/src/main/java/org/eclipse/tractusx/edc/transferprocess/sftp/provisioner/SftpProviderResourceDefinition.java b/edc-extensions/transferprocess-sftp-provisioner/src/main/java/org/eclipse/tractusx/edc/transferprocess/sftp/provisioner/SftpProviderResourceDefinition.java index fd13eb2d0..45c71eff3 100644 --- a/edc-extensions/transferprocess-sftp-provisioner/src/main/java/org/eclipse/tractusx/edc/transferprocess/sftp/provisioner/SftpProviderResourceDefinition.java +++ b/edc-extensions/transferprocess-sftp-provisioner/src/main/java/org/eclipse/tractusx/edc/transferprocess/sftp/provisioner/SftpProviderResourceDefinition.java @@ -19,7 +19,7 @@ package org.eclipse.tractusx.edc.transferprocess.sftp.provisioner; -import org.eclipse.edc.connector.transfer.spi.types.ResourceDefinition; +import org.eclipse.edc.connector.controlplane.transfer.spi.types.ResourceDefinition; import org.eclipse.tractusx.edc.transferprocess.sftp.common.SftpDataAddress; public class SftpProviderResourceDefinition extends ResourceDefinition { diff --git a/edc-extensions/transferprocess-sftp-provisioner/src/main/java/org/eclipse/tractusx/edc/transferprocess/sftp/provisioner/SftpProviderResourceDefinitionGenerator.java b/edc-extensions/transferprocess-sftp-provisioner/src/main/java/org/eclipse/tractusx/edc/transferprocess/sftp/provisioner/SftpProviderResourceDefinitionGenerator.java index 53de10d8c..370b1054e 100644 --- a/edc-extensions/transferprocess-sftp-provisioner/src/main/java/org/eclipse/tractusx/edc/transferprocess/sftp/provisioner/SftpProviderResourceDefinitionGenerator.java +++ b/edc-extensions/transferprocess-sftp-provisioner/src/main/java/org/eclipse/tractusx/edc/transferprocess/sftp/provisioner/SftpProviderResourceDefinitionGenerator.java @@ -19,9 +19,9 @@ package org.eclipse.tractusx.edc.transferprocess.sftp.provisioner; -import org.eclipse.edc.connector.transfer.spi.provision.ProviderResourceDefinitionGenerator; -import org.eclipse.edc.connector.transfer.spi.types.ResourceDefinition; -import org.eclipse.edc.connector.transfer.spi.types.TransferProcess; +import org.eclipse.edc.connector.controlplane.transfer.spi.provision.ProviderResourceDefinitionGenerator; +import org.eclipse.edc.connector.controlplane.transfer.spi.types.ResourceDefinition; +import org.eclipse.edc.connector.controlplane.transfer.spi.types.TransferProcess; import org.eclipse.edc.policy.model.Policy; import org.eclipse.edc.spi.types.domain.DataAddress; import org.eclipse.tractusx.edc.transferprocess.sftp.common.EdcSftpException; diff --git a/edc-extensions/transferprocess-sftp-provisioner/src/main/java/org/eclipse/tractusx/edc/transferprocess/sftp/provisioner/SftpProvisionedContentResource.java b/edc-extensions/transferprocess-sftp-provisioner/src/main/java/org/eclipse/tractusx/edc/transferprocess/sftp/provisioner/SftpProvisionedContentResource.java index 61bb9089e..2879252a7 100644 --- a/edc-extensions/transferprocess-sftp-provisioner/src/main/java/org/eclipse/tractusx/edc/transferprocess/sftp/provisioner/SftpProvisionedContentResource.java +++ b/edc-extensions/transferprocess-sftp-provisioner/src/main/java/org/eclipse/tractusx/edc/transferprocess/sftp/provisioner/SftpProvisionedContentResource.java @@ -19,7 +19,7 @@ package org.eclipse.tractusx.edc.transferprocess.sftp.provisioner; -import org.eclipse.edc.connector.transfer.spi.types.ProvisionedContentResource; +import org.eclipse.edc.connector.controlplane.transfer.spi.types.ProvisionedContentResource; import org.eclipse.edc.policy.model.Policy; import org.eclipse.tractusx.edc.transferprocess.sftp.common.SftpDataAddress; diff --git a/edc-extensions/transferprocess-sftp-provisioner/src/main/java/org/eclipse/tractusx/edc/transferprocess/sftp/provisioner/SftpProvisionerExtension.java b/edc-extensions/transferprocess-sftp-provisioner/src/main/java/org/eclipse/tractusx/edc/transferprocess/sftp/provisioner/SftpProvisionerExtension.java index 5b36db1a9..b3d5c0a14 100644 --- a/edc-extensions/transferprocess-sftp-provisioner/src/main/java/org/eclipse/tractusx/edc/transferprocess/sftp/provisioner/SftpProvisionerExtension.java +++ b/edc-extensions/transferprocess-sftp-provisioner/src/main/java/org/eclipse/tractusx/edc/transferprocess/sftp/provisioner/SftpProvisionerExtension.java @@ -19,8 +19,8 @@ package org.eclipse.tractusx.edc.transferprocess.sftp.provisioner; -import org.eclipse.edc.connector.transfer.spi.provision.ProviderResourceDefinitionGenerator; -import org.eclipse.edc.connector.transfer.spi.provision.ProvisionManager; +import org.eclipse.edc.connector.controlplane.transfer.spi.provision.ProviderResourceDefinitionGenerator; +import org.eclipse.edc.connector.controlplane.transfer.spi.provision.ProvisionManager; import org.eclipse.edc.policy.engine.spi.PolicyEngine; import org.eclipse.edc.runtime.metamodel.annotation.Inject; import org.eclipse.edc.runtime.metamodel.annotation.Provides; diff --git a/edc-extensions/transferprocess-sftp-provisioner/src/test/java/org/eclipse/tractusx/edc/transferprocess/sftp/provisioner/NoOpSftpProvisionerTest.java b/edc-extensions/transferprocess-sftp-provisioner/src/test/java/org/eclipse/tractusx/edc/transferprocess/sftp/provisioner/NoOpSftpProvisionerTest.java index cfbe7a9a3..4fc772118 100644 --- a/edc-extensions/transferprocess-sftp-provisioner/src/test/java/org/eclipse/tractusx/edc/transferprocess/sftp/provisioner/NoOpSftpProvisionerTest.java +++ b/edc-extensions/transferprocess-sftp-provisioner/src/test/java/org/eclipse/tractusx/edc/transferprocess/sftp/provisioner/NoOpSftpProvisionerTest.java @@ -20,8 +20,8 @@ package org.eclipse.tractusx.edc.transferprocess.sftp.provisioner; -import org.eclipse.edc.connector.transfer.spi.types.ProvisionedContentResource; -import org.eclipse.edc.connector.transfer.spi.types.ResourceDefinition; +import org.eclipse.edc.connector.controlplane.transfer.spi.types.ProvisionedContentResource; +import org.eclipse.edc.connector.controlplane.transfer.spi.types.ResourceDefinition; import org.eclipse.edc.policy.engine.spi.PolicyEngine; import org.eclipse.edc.policy.model.Policy; import org.eclipse.edc.spi.result.AbstractResult; diff --git a/edc-extensions/transferprocess-sftp-provisioner/src/test/java/org/eclipse/tractusx/edc/transferprocess/sftp/provisioner/SftpProviderResourceDefinitionGeneratorTest.java b/edc-extensions/transferprocess-sftp-provisioner/src/test/java/org/eclipse/tractusx/edc/transferprocess/sftp/provisioner/SftpProviderResourceDefinitionGeneratorTest.java index 13eccdbff..1e2de4965 100644 --- a/edc-extensions/transferprocess-sftp-provisioner/src/test/java/org/eclipse/tractusx/edc/transferprocess/sftp/provisioner/SftpProviderResourceDefinitionGeneratorTest.java +++ b/edc-extensions/transferprocess-sftp-provisioner/src/test/java/org/eclipse/tractusx/edc/transferprocess/sftp/provisioner/SftpProviderResourceDefinitionGeneratorTest.java @@ -21,7 +21,7 @@ package org.eclipse.tractusx.edc.transferprocess.sftp.provisioner; -import org.eclipse.edc.connector.transfer.spi.types.TransferProcess; +import org.eclipse.edc.connector.controlplane.transfer.spi.types.TransferProcess; import org.eclipse.edc.policy.model.Policy; import org.eclipse.edc.spi.types.domain.DataAddress; import org.eclipse.tractusx.edc.transferprocess.sftp.common.SftpDataAddress; diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/DataWiper.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/DataWiper.java index dc7390bee..904b97626 100644 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/DataWiper.java +++ b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/DataWiper.java @@ -19,10 +19,10 @@ package org.eclipse.tractusx.edc.lifecycle; -import org.eclipse.edc.connector.contract.spi.offer.store.ContractDefinitionStore; -import org.eclipse.edc.connector.policy.spi.store.PolicyDefinitionStore; +import org.eclipse.edc.connector.controlplane.asset.spi.index.AssetIndex; +import org.eclipse.edc.connector.controlplane.contract.spi.offer.store.ContractDefinitionStore; +import org.eclipse.edc.connector.controlplane.policy.spi.store.PolicyDefinitionStore; import org.eclipse.edc.edr.spi.store.EndpointDataReferenceStore; -import org.eclipse.edc.spi.asset.AssetIndex; import org.eclipse.edc.spi.query.QuerySpec; import org.eclipse.edc.spi.system.ServiceExtensionContext; import org.eclipse.tractusx.edc.validation.businesspartner.spi.BusinessPartnerStore; diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/ParticipantRuntime.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/ParticipantRuntime.java index ce4a2e80a..9ba359c1e 100644 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/ParticipantRuntime.java +++ b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/ParticipantRuntime.java @@ -22,11 +22,11 @@ import com.nimbusds.jose.JOSEException; import com.nimbusds.jose.jwk.Curve; import com.nimbusds.jose.jwk.gen.ECKeyGenerator; +import org.eclipse.edc.boot.system.injection.InjectionContainer; import org.eclipse.edc.junit.extensions.EdcRuntimeExtension; import org.eclipse.edc.spi.security.Vault; import org.eclipse.edc.spi.system.ServiceExtension; import org.eclipse.edc.spi.system.ServiceExtensionContext; -import org.eclipse.edc.spi.system.injection.InjectionContainer; import org.junit.jupiter.api.extension.AfterAllCallback; import org.junit.jupiter.api.extension.BeforeAllCallback; import org.junit.jupiter.api.extension.ExtensionContext; diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/catalog/DimCatalogIntegrationTest.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/catalog/DimCatalogIntegrationTest.java index 4e59c58cc..8ccd84d1f 100644 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/catalog/DimCatalogIntegrationTest.java +++ b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/catalog/DimCatalogIntegrationTest.java @@ -30,7 +30,7 @@ import java.util.Map; import static org.assertj.core.api.Assertions.assertThat; -import static org.eclipse.edc.test.system.utils.PolicyFixtures.noConstraintPolicy; +import static org.eclipse.edc.connector.controlplane.test.system.utils.PolicyFixtures.noConstraintPolicy; import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.CX_POLICY_NS; import static org.eclipse.tractusx.edc.helpers.DimHelper.configureParticipant; import static org.eclipse.tractusx.edc.lifecycle.Runtimes.dimRuntime; diff --git a/edc-tests/edc-controlplane/catalog-tests/src/test/java/org/eclipse/tractusx/edc/tests/catalog/CatalogTest.java b/edc-tests/edc-controlplane/catalog-tests/src/test/java/org/eclipse/tractusx/edc/tests/catalog/CatalogTest.java index f2a835960..14dba2c55 100644 --- a/edc-tests/edc-controlplane/catalog-tests/src/test/java/org/eclipse/tractusx/edc/tests/catalog/CatalogTest.java +++ b/edc-tests/edc-controlplane/catalog-tests/src/test/java/org/eclipse/tractusx/edc/tests/catalog/CatalogTest.java @@ -34,7 +34,7 @@ import static java.util.stream.IntStream.range; import static org.assertj.core.api.Assertions.assertThat; -import static org.eclipse.edc.test.system.utils.PolicyFixtures.noConstraintPolicy; +import static org.eclipse.edc.connector.controlplane.test.system.utils.PolicyFixtures.noConstraintPolicy; import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.PLATO_BPN; import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.PLATO_NAME; import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.SOKRATES_BPN; diff --git a/edc-tests/edc-controlplane/edr-api-tests/src/test/java/org/eclipse/tractusx/edc/tests/edrv2/AbstractNegotiateEdrTest.java b/edc-tests/edc-controlplane/edr-api-tests/src/test/java/org/eclipse/tractusx/edc/tests/edrv2/AbstractNegotiateEdrTest.java index 6e355b2ba..4443d84f5 100644 --- a/edc-tests/edc-controlplane/edr-api-tests/src/test/java/org/eclipse/tractusx/edc/tests/edrv2/AbstractNegotiateEdrTest.java +++ b/edc-tests/edc-controlplane/edr-api-tests/src/test/java/org/eclipse/tractusx/edc/tests/edrv2/AbstractNegotiateEdrTest.java @@ -22,15 +22,15 @@ import jakarta.json.Json; import okhttp3.mockwebserver.MockResponse; import okhttp3.mockwebserver.MockWebServer; -import org.eclipse.edc.connector.contract.spi.event.contractnegotiation.ContractNegotiationAgreed; -import org.eclipse.edc.connector.contract.spi.event.contractnegotiation.ContractNegotiationFinalized; -import org.eclipse.edc.connector.contract.spi.event.contractnegotiation.ContractNegotiationInitiated; -import org.eclipse.edc.connector.contract.spi.event.contractnegotiation.ContractNegotiationRequested; -import org.eclipse.edc.connector.contract.spi.event.contractnegotiation.ContractNegotiationVerified; -import org.eclipse.edc.connector.transfer.spi.event.TransferProcessInitiated; -import org.eclipse.edc.connector.transfer.spi.event.TransferProcessProvisioned; -import org.eclipse.edc.connector.transfer.spi.event.TransferProcessRequested; -import org.eclipse.edc.connector.transfer.spi.event.TransferProcessStarted; +import org.eclipse.edc.connector.controlplane.contract.spi.event.contractnegotiation.ContractNegotiationAgreed; +import org.eclipse.edc.connector.controlplane.contract.spi.event.contractnegotiation.ContractNegotiationFinalized; +import org.eclipse.edc.connector.controlplane.contract.spi.event.contractnegotiation.ContractNegotiationInitiated; +import org.eclipse.edc.connector.controlplane.contract.spi.event.contractnegotiation.ContractNegotiationRequested; +import org.eclipse.edc.connector.controlplane.contract.spi.event.contractnegotiation.ContractNegotiationVerified; +import org.eclipse.edc.connector.controlplane.transfer.spi.event.TransferProcessInitiated; +import org.eclipse.edc.connector.controlplane.transfer.spi.event.TransferProcessProvisioned; +import org.eclipse.edc.connector.controlplane.transfer.spi.event.TransferProcessRequested; +import org.eclipse.edc.connector.controlplane.transfer.spi.event.TransferProcessStarted; import org.eclipse.edc.policy.model.Operator; import org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration; import org.eclipse.tractusx.edc.tests.helpers.EdrNegotiationHelperFunctions; diff --git a/edc-tests/edc-controlplane/edr-api-tests/src/test/java/org/eclipse/tractusx/edc/tests/edrv2/EdrCacheApiEndToEndTest.java b/edc-tests/edc-controlplane/edr-api-tests/src/test/java/org/eclipse/tractusx/edc/tests/edrv2/EdrCacheApiEndToEndTest.java index b9a760e17..69cbb5075 100644 --- a/edc-tests/edc-controlplane/edr-api-tests/src/test/java/org/eclipse/tractusx/edc/tests/edrv2/EdrCacheApiEndToEndTest.java +++ b/edc-tests/edc-controlplane/edr-api-tests/src/test/java/org/eclipse/tractusx/edc/tests/edrv2/EdrCacheApiEndToEndTest.java @@ -55,7 +55,7 @@ import java.util.Map; import static org.assertj.core.api.Assertions.assertThat; -import static org.eclipse.edc.spi.CoreConstants.EDC_NAMESPACE; +import static org.eclipse.edc.spi.constants.CoreConstants.EDC_NAMESPACE; import static org.eclipse.edc.util.io.Ports.getFreePort; import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.EDR_PROPERTY_EXPIRES_IN; import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.EDR_PROPERTY_REFRESH_ENDPOINT; diff --git a/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/IdentityParticipant.java b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/IdentityParticipant.java index c396cd47c..879e690f6 100644 --- a/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/IdentityParticipant.java +++ b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/IdentityParticipant.java @@ -20,8 +20,8 @@ package org.eclipse.tractusx.edc.tests; import com.nimbusds.jose.jwk.JWK; +import org.eclipse.edc.connector.controlplane.test.system.utils.Participant; import org.eclipse.edc.security.token.jwt.CryptoConverter; -import org.eclipse.edc.test.system.utils.Participant; import java.security.KeyPair; diff --git a/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/ParticipantEdrApi.java b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/ParticipantEdrApi.java index fccc1bb0d..a8aec8b06 100644 --- a/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/ParticipantEdrApi.java +++ b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/ParticipantEdrApi.java @@ -24,7 +24,7 @@ import jakarta.json.Json; import jakarta.json.JsonArray; import jakarta.json.JsonObject; -import org.eclipse.edc.test.system.utils.Participant; +import org.eclipse.edc.connector.controlplane.test.system.utils.Participant; import org.eclipse.tractusx.edc.tests.participant.TransferParticipant; import static io.restassured.http.ContentType.JSON; @@ -36,7 +36,7 @@ import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.VOCAB; import static org.eclipse.edc.jsonld.spi.PropertyAndTypeNames.ODRL_ASSIGNER_ATTRIBUTE; import static org.eclipse.edc.jsonld.spi.PropertyAndTypeNames.ODRL_TARGET_ATTRIBUTE; -import static org.eclipse.edc.spi.CoreConstants.EDC_NAMESPACE; +import static org.eclipse.edc.spi.constants.CoreConstants.EDC_NAMESPACE; import static org.eclipse.tractusx.edc.tests.helpers.CatalogHelperFunctions.getDatasetContractId; import static org.eclipse.tractusx.edc.tests.helpers.CatalogHelperFunctions.getDatasetFirstPolicy; import static org.eclipse.tractusx.edc.tests.helpers.EdrNegotiationHelperFunctions.createEdrNegotiationRequest; diff --git a/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/helpers/CatalogHelperFunctions.java b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/helpers/CatalogHelperFunctions.java index e52880858..2533b7959 100644 --- a/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/helpers/CatalogHelperFunctions.java +++ b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/helpers/CatalogHelperFunctions.java @@ -23,12 +23,12 @@ import jakarta.json.JsonArray; import jakarta.json.JsonObject; import jakarta.json.JsonValue; -import org.eclipse.edc.connector.contract.spi.ContractId; +import org.eclipse.edc.connector.controlplane.contract.spi.ContractId; -import static org.eclipse.edc.catalog.spi.CatalogRequest.CATALOG_REQUEST_QUERY_SPEC; +import static org.eclipse.edc.connector.controlplane.catalog.spi.CatalogRequest.CATALOG_REQUEST_QUERY_SPEC; import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.ID; import static org.eclipse.edc.jsonld.spi.PropertyAndTypeNames.ODRL_POLICY_ATTRIBUTE; -import static org.eclipse.edc.spi.CoreConstants.EDC_NAMESPACE; +import static org.eclipse.edc.spi.constants.CoreConstants.EDC_NAMESPACE; public class CatalogHelperFunctions { diff --git a/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/helpers/EdrNegotiationHelperFunctions.java b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/helpers/EdrNegotiationHelperFunctions.java index 34fe19c6f..76a927708 100644 --- a/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/helpers/EdrNegotiationHelperFunctions.java +++ b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/helpers/EdrNegotiationHelperFunctions.java @@ -32,7 +32,7 @@ import java.util.Set; import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.TYPE; -import static org.eclipse.edc.spi.CoreConstants.EDC_NAMESPACE; +import static org.eclipse.edc.spi.constants.CoreConstants.EDC_NAMESPACE; public class EdrNegotiationHelperFunctions { @@ -42,7 +42,6 @@ public static JsonObject createEdrNegotiationRequest(String connectorAddress, St return Json.createObjectBuilder() .add(TYPE, NegotiateEdrRequestDto.EDR_REQUEST_DTO_TYPE) .add(EDC_NAMESPACE + "counterPartyId", providerId) - .add(EDC_NAMESPACE + "providerId", providerId) .add(EDC_NAMESPACE + "counterPartyAddress", connectorAddress) .add(EDC_NAMESPACE + "protocol", "dataspace-protocol-http") .add(EDC_NAMESPACE + "offer", Json.createObjectBuilder() diff --git a/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/helpers/PolicyHelperFunctions.java b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/helpers/PolicyHelperFunctions.java index d545b4f86..946723094 100644 --- a/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/helpers/PolicyHelperFunctions.java +++ b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/helpers/PolicyHelperFunctions.java @@ -25,7 +25,7 @@ import jakarta.json.JsonArrayBuilder; import jakarta.json.JsonObject; import jakarta.json.JsonObjectBuilder; -import org.eclipse.edc.connector.policy.spi.PolicyDefinition; +import org.eclipse.edc.connector.controlplane.policy.spi.PolicyDefinition; import org.eclipse.edc.jsonld.util.JacksonJsonLd; import org.eclipse.edc.policy.model.AtomicConstraint; import org.eclipse.edc.policy.model.Operator; @@ -43,7 +43,7 @@ import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.TYPE; import static org.eclipse.edc.jsonld.spi.PropertyAndTypeNames.ODRL_CONSTRAINT_TYPE; import static org.eclipse.edc.jsonld.spi.PropertyAndTypeNames.ODRL_LOGICAL_CONSTRAINT_TYPE; -import static org.eclipse.edc.spi.CoreConstants.EDC_NAMESPACE; +import static org.eclipse.edc.spi.constants.CoreConstants.EDC_NAMESPACE; public class PolicyHelperFunctions { diff --git a/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/helpers/TransferProcessHelperFunctions.java b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/helpers/TransferProcessHelperFunctions.java index 73d1a44c7..82cafae36 100644 --- a/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/helpers/TransferProcessHelperFunctions.java +++ b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/helpers/TransferProcessHelperFunctions.java @@ -25,7 +25,7 @@ import static jakarta.json.Json.createObjectBuilder; import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.ID; import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.TYPE; -import static org.eclipse.edc.spi.CoreConstants.EDC_NAMESPACE; +import static org.eclipse.edc.spi.constants.CoreConstants.EDC_NAMESPACE; public class TransferProcessHelperFunctions { diff --git a/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/participant/TractusxParticipantBase.java b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/participant/TractusxParticipantBase.java index c8e3baae9..6977e33a1 100644 --- a/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/participant/TractusxParticipantBase.java +++ b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/participant/TractusxParticipantBase.java @@ -20,7 +20,7 @@ package org.eclipse.tractusx.edc.tests.participant; import jakarta.json.Json; -import org.eclipse.edc.test.system.utils.Participant; +import org.eclipse.edc.connector.controlplane.test.system.utils.Participant; import org.eclipse.tractusx.edc.tests.IdentityParticipant; import org.eclipse.tractusx.edc.tests.ParticipantDataApi; import org.eclipse.tractusx.edc.tests.ParticipantEdrApi; diff --git a/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/runtimes/DataWiper.java b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/runtimes/DataWiper.java index 3d2d88ded..12e66c0ff 100644 --- a/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/runtimes/DataWiper.java +++ b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/runtimes/DataWiper.java @@ -19,10 +19,10 @@ package org.eclipse.tractusx.edc.tests.runtimes; -import org.eclipse.edc.connector.contract.spi.offer.store.ContractDefinitionStore; -import org.eclipse.edc.connector.policy.spi.store.PolicyDefinitionStore; +import org.eclipse.edc.connector.controlplane.asset.spi.index.AssetIndex; +import org.eclipse.edc.connector.controlplane.contract.spi.offer.store.ContractDefinitionStore; +import org.eclipse.edc.connector.controlplane.policy.spi.store.PolicyDefinitionStore; import org.eclipse.edc.edr.spi.store.EndpointDataReferenceStore; -import org.eclipse.edc.spi.asset.AssetIndex; import org.eclipse.edc.spi.query.QuerySpec; import org.eclipse.edc.spi.system.ServiceExtensionContext; import org.eclipse.tractusx.edc.validation.businesspartner.spi.BusinessPartnerStore; diff --git a/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/runtimes/ParticipantRuntime.java b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/runtimes/ParticipantRuntime.java index 653524236..f13b719db 100644 --- a/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/runtimes/ParticipantRuntime.java +++ b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/runtimes/ParticipantRuntime.java @@ -23,6 +23,7 @@ import com.nimbusds.jose.jwk.Curve; import com.nimbusds.jose.jwk.ECKey; import com.nimbusds.jose.jwk.gen.ECKeyGenerator; +import org.eclipse.edc.boot.system.injection.InjectionContainer; import org.eclipse.edc.iam.did.spi.resolution.DidPublicKeyResolver; import org.eclipse.edc.iam.identitytrust.sts.embedded.EmbeddedSecureTokenService; import org.eclipse.edc.identitytrust.SecureTokenService; @@ -33,7 +34,6 @@ import org.eclipse.edc.spi.security.Vault; import org.eclipse.edc.spi.system.ServiceExtension; import org.eclipse.edc.spi.system.ServiceExtensionContext; -import org.eclipse.edc.spi.system.injection.InjectionContainer; import org.eclipse.edc.spi.types.domain.message.RemoteMessage; import org.eclipse.edc.token.JwtGenerationService; import org.eclipse.tractusx.edc.tests.MockBpnIdentityService; diff --git a/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/runtimes/PgParticipantRuntime.java b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/runtimes/PgParticipantRuntime.java index 8300d892d..9d720b30f 100644 --- a/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/runtimes/PgParticipantRuntime.java +++ b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/runtimes/PgParticipantRuntime.java @@ -19,6 +19,7 @@ package org.eclipse.tractusx.edc.tests.runtimes; +import org.eclipse.edc.boot.system.injection.InjectionContainer; import org.eclipse.edc.boot.vault.InMemoryVault; import org.eclipse.edc.spi.monitor.ConsoleMonitor; import org.eclipse.edc.spi.monitor.Monitor; @@ -26,7 +27,6 @@ import org.eclipse.edc.spi.security.Vault; import org.eclipse.edc.spi.system.ServiceExtension; import org.eclipse.edc.spi.system.ServiceExtensionContext; -import org.eclipse.edc.spi.system.injection.InjectionContainer; import org.eclipse.edc.sql.testfixtures.PostgresqlLocalInstance; import org.junit.jupiter.api.extension.AfterAllCallback; import org.junit.jupiter.api.extension.BeforeAllCallback; @@ -77,13 +77,6 @@ public void afterAll(ExtensionContext context) throws Exception { postgreSqlContainer.close(); } - @Override - protected void bootExtensions(ServiceExtensionContext context, List> serviceExtensions) { - PostgresqlLocalInstance helper = new PostgresqlLocalInstance(postgreSqlContainer.getUsername(), postgreSqlContainer.getPassword(), baseJdbcUrl(), postgreSqlContainer.getDatabaseName()); - helper.createDatabase(); - super.bootExtensions(context, serviceExtensions); - } - public Map postgresqlConfiguration(String name) { var jdbcUrl = jdbcUrl(name); return new HashMap<>() { @@ -110,6 +103,13 @@ public String baseJdbcUrl() { return format("jdbc:postgresql://%s:%s/", postgreSqlContainer.getHost(), postgreSqlContainer.getFirstMappedPort()); } + @Override + protected void bootExtensions(ServiceExtensionContext context, List> serviceExtensions) { + PostgresqlLocalInstance helper = new PostgresqlLocalInstance(postgreSqlContainer.getUsername(), postgreSqlContainer.getPassword(), baseJdbcUrl(), postgreSqlContainer.getDatabaseName()); + helper.createDatabase(); + super.bootExtensions(context, serviceExtensions); + } + protected void mockVault() { this.registerServiceMock(Vault.class, new InMemoryVaultOverride(new ConsoleMonitor())); } diff --git a/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/transfer/HttpConsumerPullBaseTest.java b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/transfer/HttpConsumerPullBaseTest.java index c32af6cb9..697615d93 100644 --- a/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/transfer/HttpConsumerPullBaseTest.java +++ b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/transfer/HttpConsumerPullBaseTest.java @@ -21,7 +21,7 @@ import jakarta.json.Json; import jakarta.json.JsonObject; -import org.eclipse.edc.connector.transfer.spi.types.TransferProcessStates; +import org.eclipse.edc.connector.controlplane.transfer.spi.types.TransferProcessStates; import org.eclipse.tractusx.edc.tests.ParticipantAwareTest; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; diff --git a/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/transfer/ProviderPushBaseTest.java b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/transfer/ProviderPushBaseTest.java index 90b2b41fc..fdb03f995 100644 --- a/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/transfer/ProviderPushBaseTest.java +++ b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/transfer/ProviderPushBaseTest.java @@ -33,9 +33,9 @@ import static jakarta.json.Json.createObjectBuilder; import static org.assertj.core.api.Assertions.assertThat; import static org.awaitility.Awaitility.await; -import static org.eclipse.edc.connector.transfer.spi.types.TransferProcessStates.COMPLETED; +import static org.eclipse.edc.connector.controlplane.transfer.spi.types.TransferProcessStates.COMPLETED; import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.TYPE; -import static org.eclipse.edc.spi.CoreConstants.EDC_NAMESPACE; +import static org.eclipse.edc.spi.constants.CoreConstants.EDC_NAMESPACE; import static org.eclipse.edc.util.io.Ports.getFreePort; import static org.eclipse.tractusx.edc.tests.helpers.PolicyHelperFunctions.bnpPolicy; import static org.eclipse.tractusx.edc.tests.participant.TractusxParticipantBase.ASYNC_TIMEOUT; diff --git a/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/iatp/runtime/IatpParticipantRuntime.java b/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/iatp/runtime/IatpParticipantRuntime.java index ad2d28560..6864fdc03 100644 --- a/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/iatp/runtime/IatpParticipantRuntime.java +++ b/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/iatp/runtime/IatpParticipantRuntime.java @@ -20,12 +20,12 @@ package org.eclipse.tractusx.edc.tests.transfer.iatp.runtime; import com.nimbusds.jose.jwk.JWK; +import org.eclipse.edc.boot.system.injection.InjectionContainer; import org.eclipse.edc.junit.extensions.EdcRuntimeExtension; import org.eclipse.edc.security.token.jwt.CryptoConverter; import org.eclipse.edc.spi.security.Vault; import org.eclipse.edc.spi.system.ServiceExtension; import org.eclipse.edc.spi.system.ServiceExtensionContext; -import org.eclipse.edc.spi.system.injection.InjectionContainer; import org.eclipse.tractusx.edc.tests.runtimes.DataWiper; import org.junit.jupiter.api.extension.AfterAllCallback; import org.junit.jupiter.api.extension.BeforeAllCallback; diff --git a/edc-tests/edc-controlplane/policy-tests/src/test/java/org/eclipse/tractusx/edc/tests/policy/PolicyMonitorEndToEndTest.java b/edc-tests/edc-controlplane/policy-tests/src/test/java/org/eclipse/tractusx/edc/tests/policy/PolicyMonitorEndToEndTest.java index 793226960..373a10ca1 100644 --- a/edc-tests/edc-controlplane/policy-tests/src/test/java/org/eclipse/tractusx/edc/tests/policy/PolicyMonitorEndToEndTest.java +++ b/edc-tests/edc-controlplane/policy-tests/src/test/java/org/eclipse/tractusx/edc/tests/policy/PolicyMonitorEndToEndTest.java @@ -34,9 +34,9 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.awaitility.Awaitility.await; -import static org.eclipse.edc.connector.transfer.spi.types.TransferProcessStates.STARTED; -import static org.eclipse.edc.connector.transfer.spi.types.TransferProcessStates.TERMINATED; -import static org.eclipse.edc.test.system.utils.PolicyFixtures.inForceDatePolicy; +import static org.eclipse.edc.connector.controlplane.contract.spi.types.negotiation.ContractNegotiationStates.TERMINATED; +import static org.eclipse.edc.connector.controlplane.test.system.utils.PolicyFixtures.inForceDatePolicy; +import static org.eclipse.edc.connector.controlplane.transfer.spi.types.TransferProcessStates.STARTED; import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.PLATO_BPN; import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.PLATO_NAME; import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.SOKRATES_BPN; diff --git a/edc-tests/edc-controlplane/transfer-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/TransferWithTokenRefreshTest.java b/edc-tests/edc-controlplane/transfer-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/TransferWithTokenRefreshTest.java index d82e6edce..b213a982f 100644 --- a/edc-tests/edc-controlplane/transfer-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/TransferWithTokenRefreshTest.java +++ b/edc-tests/edc-controlplane/transfer-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/TransferWithTokenRefreshTest.java @@ -21,7 +21,7 @@ import jakarta.json.Json; import jakarta.json.JsonObject; -import org.eclipse.edc.connector.transfer.spi.types.TransferProcessStates; +import org.eclipse.edc.connector.controlplane.transfer.spi.types.TransferProcessStates; import org.eclipse.edc.junit.annotations.EndToEndTest; import org.eclipse.tractusx.edc.tests.participant.TransferParticipant; import org.eclipse.tractusx.edc.tests.runtimes.ParticipantRuntime; diff --git a/edc-tests/edc-dataplane/cloud-transfer-tests/src/test/java/org/eclipse/tractusx/edc/dataplane/transfer/test/ParticipantRuntime.java b/edc-tests/edc-dataplane/cloud-transfer-tests/src/test/java/org/eclipse/tractusx/edc/dataplane/transfer/test/ParticipantRuntime.java index 49d9efbb1..a3662b2b0 100644 --- a/edc-tests/edc-dataplane/cloud-transfer-tests/src/test/java/org/eclipse/tractusx/edc/dataplane/transfer/test/ParticipantRuntime.java +++ b/edc-tests/edc-dataplane/cloud-transfer-tests/src/test/java/org/eclipse/tractusx/edc/dataplane/transfer/test/ParticipantRuntime.java @@ -19,13 +19,13 @@ package org.eclipse.tractusx.edc.dataplane.transfer.test; +import org.eclipse.edc.boot.system.injection.InjectionContainer; import org.eclipse.edc.junit.extensions.EdcRuntimeExtension; import org.eclipse.edc.spi.monitor.ConsoleMonitor; import org.eclipse.edc.spi.monitor.Monitor; import org.eclipse.edc.spi.security.Vault; import org.eclipse.edc.spi.system.ServiceExtension; import org.eclipse.edc.spi.system.ServiceExtensionContext; -import org.eclipse.edc.spi.system.injection.InjectionContainer; import org.junit.jupiter.api.extension.AfterAllCallback; import org.junit.jupiter.api.extension.BeforeAllCallback; import org.junit.jupiter.api.extension.ExtensionContext; diff --git a/edc-tests/edc-dataplane/edc-dataplane-tokenrefresh-tests/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/e2e/DataPlaneTokenRefreshEndToEndTest.java b/edc-tests/edc-dataplane/edc-dataplane-tokenrefresh-tests/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/e2e/DataPlaneTokenRefreshEndToEndTest.java index c06cea994..77e5341dd 100644 --- a/edc-tests/edc-dataplane/edc-dataplane-tokenrefresh-tests/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/e2e/DataPlaneTokenRefreshEndToEndTest.java +++ b/edc-tests/edc-dataplane/edc-dataplane-tokenrefresh-tests/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/e2e/DataPlaneTokenRefreshEndToEndTest.java @@ -52,7 +52,7 @@ import static org.apache.http.HttpHeaders.AUTHORIZATION; import static org.assertj.core.api.Assertions.assertThat; -import static org.eclipse.edc.spi.CoreConstants.EDC_NAMESPACE; +import static org.eclipse.edc.spi.constants.CoreConstants.EDC_NAMESPACE; import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.TX_AUTH_NS; import static org.hamcrest.Matchers.containsString; diff --git a/spi/callback-spi/src/main/java/org/eclipse/tractusx/edc/spi/callback/InProcessCallback.java b/spi/callback-spi/src/main/java/org/eclipse/tractusx/edc/spi/callback/InProcessCallback.java index 4528daca0..2b5ffbb44 100644 --- a/spi/callback-spi/src/main/java/org/eclipse/tractusx/edc/spi/callback/InProcessCallback.java +++ b/spi/callback-spi/src/main/java/org/eclipse/tractusx/edc/spi/callback/InProcessCallback.java @@ -19,7 +19,7 @@ package org.eclipse.tractusx.edc.spi.callback; -import org.eclipse.edc.connector.spi.callback.CallbackEventRemoteMessage; +import org.eclipse.edc.connector.controlplane.services.spi.callback.CallbackEventRemoteMessage; import org.eclipse.edc.spi.event.Event; import org.eclipse.edc.spi.result.Result; diff --git a/spi/callback-spi/src/main/java/org/eclipse/tractusx/edc/spi/callback/InProcessCallbackRegistry.java b/spi/callback-spi/src/main/java/org/eclipse/tractusx/edc/spi/callback/InProcessCallbackRegistry.java index 6cffe8d46..a5da4b3fa 100644 --- a/spi/callback-spi/src/main/java/org/eclipse/tractusx/edc/spi/callback/InProcessCallbackRegistry.java +++ b/spi/callback-spi/src/main/java/org/eclipse/tractusx/edc/spi/callback/InProcessCallbackRegistry.java @@ -20,7 +20,7 @@ package org.eclipse.tractusx.edc.spi.callback; -import org.eclipse.edc.connector.spi.callback.CallbackEventRemoteMessage; +import org.eclipse.edc.connector.controlplane.services.spi.callback.CallbackEventRemoteMessage; import org.eclipse.edc.runtime.metamodel.annotation.ExtensionPoint; import org.eclipse.edc.spi.event.Event; import org.eclipse.edc.spi.result.Result; diff --git a/spi/core-spi/src/main/java/org/eclipse/tractusx/edc/edr/spi/CoreConstants.java b/spi/core-spi/src/main/java/org/eclipse/tractusx/edc/edr/spi/CoreConstants.java index 29d3c7a32..91b38e24c 100644 --- a/spi/core-spi/src/main/java/org/eclipse/tractusx/edc/edr/spi/CoreConstants.java +++ b/spi/core-spi/src/main/java/org/eclipse/tractusx/edc/edr/spi/CoreConstants.java @@ -19,7 +19,8 @@ package org.eclipse.tractusx.edc.edr.spi; -import static org.eclipse.edc.spi.CoreConstants.EDC_NAMESPACE; + +import static org.eclipse.edc.spi.constants.CoreConstants.EDC_NAMESPACE; public final class CoreConstants { diff --git a/spi/edr-spi/build.gradle.kts b/spi/edr-spi/build.gradle.kts index 608bf4329..0096d50ca 100644 --- a/spi/edr-spi/build.gradle.kts +++ b/spi/edr-spi/build.gradle.kts @@ -25,6 +25,7 @@ plugins { dependencies { implementation(project(":spi:core-spi")) implementation(libs.edc.spi.core) + implementation(libs.edc.spi.contract) implementation(libs.edc.spi.edrstore) testFixturesImplementation(libs.edc.junit) diff --git a/spi/edr-spi/src/main/java/org/eclipse/tractusx/edc/edr/spi/types/NegotiateEdrRequest.java b/spi/edr-spi/src/main/java/org/eclipse/tractusx/edc/edr/spi/types/NegotiateEdrRequest.java index 71cc862f4..efd5299a5 100644 --- a/spi/edr-spi/src/main/java/org/eclipse/tractusx/edc/edr/spi/types/NegotiateEdrRequest.java +++ b/spi/edr-spi/src/main/java/org/eclipse/tractusx/edc/edr/spi/types/NegotiateEdrRequest.java @@ -19,8 +19,8 @@ package org.eclipse.tractusx.edc.edr.spi.types; +import org.eclipse.edc.connector.controlplane.contract.spi.types.offer.ContractOffer; import org.eclipse.edc.spi.types.domain.callback.CallbackAddress; -import org.eclipse.edc.spi.types.domain.offer.ContractOffer; import java.util.ArrayList; import java.util.List; @@ -68,6 +68,10 @@ private Builder() { entity = new NegotiateEdrRequest(); } + public static Builder newInstance() { + return new Builder(); + } + public Builder connectorAddress(String connectorAddress) { entity.connectorAddress = connectorAddress; return this; @@ -99,9 +103,5 @@ public NegotiateEdrRequest build() { Objects.requireNonNull(entity.offer, "offer should not be null"); return entity; } - - public static Builder newInstance() { - return new Builder(); - } } } From 62600ad9f08d79597c710370d1a8e590e9ea3a43 Mon Sep 17 00:00:00 2001 From: Enrico Risa Date: Sat, 30 Mar 2024 18:51:57 +0100 Subject: [PATCH 083/100] chore: use of ContractRequest in edrs API + old edrs schema and migration removal (#1172) --- .../tractusx/edc/api/edr/v2/EdrCacheApi.java | 4 +- .../edc/api/edr/v2/EdrCacheApiController.java | 18 +- .../edc/api/edr/v2/EdrCacheApiExtension.java | 7 - .../edr/v2/dto/NegotiateEdrRequestDto.java | 120 ----------- .../edc/api/edr/v2/schema/EdrSchema.java | 109 ---------- ...ctToNegotiateEdrRequestDtoTransformer.java | 87 -------- ...tDtoToNegotiatedEdrRequestTransformer.java | 63 ------ .../NegotiateEdrRequestDtoValidator.java | 51 ----- .../api/edr/v2/EdrCacheApiControllerTest.java | 27 ++- .../edc/api/edr/v2/TestFunctions.java | 46 +--- ...NegotiateEdrRequestDtoTransformerTest.java | 155 ------------- ...oToNegotiateEdrRequestTransformerTest.java | 99 --------- .../NegotiateEdrRequestDtoValidatorTest.java | 100 --------- .../callback/ContractNegotiationCallback.java | 4 +- .../EdrPostgresqlMigrationExtension.java | 28 --- ...rg.eclipse.edc.spi.system.ServiceExtension | 1 - .../edr/V0_0_1__Init_Edr_Database_Schema.sql | 34 --- .../edr/V0_0_2__Add_ProviderId_Column.sql | 19 -- .../V0_0_3__Add_StatefulEntity_Columns.sql | 24 --- ..._0_4__Add_ContractNegotiationId_Column.sql | 19 -- .../tests/edrv2/AbstractNegotiateEdrTest.java | 166 -------------- .../tests/edrv2/NegotiateEdrInMemoryTest.java | 46 ---- .../edc/tests/edrv2/NegotiateEdrTest.java | 204 ++++++++++++++++++ .../EdrNegotiationHelperFunctions.java | 4 +- .../tests/runtimes/PgParticipantRuntime.java | 2 +- .../edr/spi/types/NegotiateEdrRequest.java | 107 --------- 26 files changed, 241 insertions(+), 1303 deletions(-) delete mode 100644 edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/dto/NegotiateEdrRequestDto.java delete mode 100644 edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/schema/EdrSchema.java delete mode 100644 edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/transform/JsonObjectToNegotiateEdrRequestDtoTransformer.java delete mode 100644 edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/transform/NegotiateEdrRequestDtoToNegotiatedEdrRequestTransformer.java delete mode 100644 edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/validation/NegotiateEdrRequestDtoValidator.java delete mode 100644 edc-extensions/edr/edr-api-v2/src/test/java/org/eclipse/tractusx/edc/api/edr/v2/transform/JsonObjectToNegotiateEdrRequestDtoTransformerTest.java delete mode 100644 edc-extensions/edr/edr-api-v2/src/test/java/org/eclipse/tractusx/edc/api/edr/v2/transform/NegotiateEdrRequestDtoToNegotiateEdrRequestTransformerTest.java delete mode 100644 edc-extensions/edr/edr-api-v2/src/test/java/org/eclipse/tractusx/edc/api/edr/v2/validation/NegotiateEdrRequestDtoValidatorTest.java delete mode 100644 edc-extensions/postgresql-migration/src/main/java/org/eclipse/tractusx/edc/postgresql/migration/EdrPostgresqlMigrationExtension.java delete mode 100644 edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/edr/V0_0_1__Init_Edr_Database_Schema.sql delete mode 100644 edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/edr/V0_0_2__Add_ProviderId_Column.sql delete mode 100644 edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/edr/V0_0_3__Add_StatefulEntity_Columns.sql delete mode 100644 edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/edr/V0_0_4__Add_ContractNegotiationId_Column.sql delete mode 100644 edc-tests/edc-controlplane/edr-api-tests/src/test/java/org/eclipse/tractusx/edc/tests/edrv2/AbstractNegotiateEdrTest.java delete mode 100644 edc-tests/edc-controlplane/edr-api-tests/src/test/java/org/eclipse/tractusx/edc/tests/edrv2/NegotiateEdrInMemoryTest.java create mode 100644 edc-tests/edc-controlplane/edr-api-tests/src/test/java/org/eclipse/tractusx/edc/tests/edrv2/NegotiateEdrTest.java delete mode 100644 spi/edr-spi/src/main/java/org/eclipse/tractusx/edc/edr/spi/types/NegotiateEdrRequest.java diff --git a/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/EdrCacheApi.java b/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/EdrCacheApi.java index 19ee52186..29dd28843 100644 --- a/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/EdrCacheApi.java +++ b/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/EdrCacheApi.java @@ -32,9 +32,9 @@ import jakarta.json.JsonObject; import org.eclipse.edc.api.model.ApiCoreSchema; import org.eclipse.edc.connector.api.management.configuration.ManagementApiSchema; +import org.eclipse.edc.connector.controlplane.api.management.contractnegotiation.ContractNegotiationApi; import org.eclipse.edc.edr.spi.types.EndpointDataReferenceEntry; import org.eclipse.edc.web.spi.ApiErrorDetail; -import org.eclipse.tractusx.edc.api.edr.v2.schema.EdrSchema; import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.ID; import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.TYPE; @@ -51,7 +51,7 @@ public interface EdrCacheApi { @ApiResponse(responseCode = "400", description = "Request body was malformed", content = @Content(array = @ArraySchema(schema = @Schema(implementation = ApiErrorDetail.class)))), }) - JsonObject initiateEdrNegotiation(@Schema(implementation = EdrSchema.NegotiateEdrRequestSchema.class) JsonObject dto); + JsonObject initiateEdrNegotiation(@Schema(implementation = ContractNegotiationApi.ContractRequestSchema.class) JsonObject dto); @Operation(description = "Request all Edr entries according to a particular query", requestBody = @RequestBody( diff --git a/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/EdrCacheApiController.java b/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/EdrCacheApiController.java index 415b936da..ea201d0af 100644 --- a/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/EdrCacheApiController.java +++ b/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/EdrCacheApiController.java @@ -45,15 +45,14 @@ import org.eclipse.edc.validator.spi.JsonObjectValidatorRegistry; import org.eclipse.edc.web.spi.exception.InvalidRequestException; import org.eclipse.edc.web.spi.exception.ValidationFailureException; -import org.eclipse.tractusx.edc.api.edr.v2.dto.NegotiateEdrRequestDto; import org.eclipse.tractusx.edc.edr.spi.service.EdrService; -import org.eclipse.tractusx.edc.edr.spi.types.NegotiateEdrRequest; import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; import static jakarta.json.stream.JsonCollectors.toJsonArray; +import static org.eclipse.edc.connector.controlplane.contract.spi.types.negotiation.ContractRequest.CONTRACT_REQUEST_TYPE; import static org.eclipse.edc.spi.query.QuerySpec.EDC_QUERY_SPEC_TYPE; import static org.eclipse.edc.web.spi.exception.ServiceResultHandler.exceptionMapper; import static org.eclipse.tractusx.edc.edr.spi.types.RefreshMode.AUTO_REFRESH; @@ -95,13 +94,14 @@ public EdrCacheApiController(EndpointDataReferenceStore edrStore, @POST @Override public JsonObject initiateEdrNegotiation(JsonObject requestObject) { - validator.validate(NegotiateEdrRequestDto.EDR_REQUEST_DTO_TYPE, requestObject).orElseThrow(ValidationFailureException::new); - var edrNegotiationRequest = transformerRegistry.transform(requestObject, NegotiateEdrRequestDto.class) - .compose(dto -> transformerRegistry.transform(dto, NegotiateEdrRequest.class)) + validator.validate(CONTRACT_REQUEST_TYPE, requestObject) + .orElseThrow(ValidationFailureException::new); + + var contractRequest = transformerRegistry.transform(requestObject, ContractRequest.class) .orElseThrow(InvalidRequestException::new); - var contractNegotiation = contractNegotiationService.initiateNegotiation(createContractRequest(edrNegotiationRequest)); + var contractNegotiation = contractNegotiationService.initiateNegotiation(enrichContractRequest(contractRequest)); var idResponse = IdResponse.Builder.newInstance() .id(contractNegotiation.getId()) @@ -170,12 +170,12 @@ public JsonObject refreshEdr(@PathParam("transferProcessId") String transferProc .orElseThrow(f -> new EdcException(f.getFailureDetail())); } - private ContractRequest createContractRequest(NegotiateEdrRequest request) { + private ContractRequest enrichContractRequest(ContractRequest request) { var callbacks = Stream.concat(request.getCallbackAddresses().stream(), Stream.of(LOCAL_CALLBACK)).collect(Collectors.toList()); return ContractRequest.Builder.newInstance() - .counterPartyAddress(request.getConnectorAddress()) - .contractOffer(request.getOffer()) + .counterPartyAddress(request.getCounterPartyAddress()) + .contractOffer(request.getContractOffer()) .protocol(request.getProtocol()) .callbackAddresses(callbacks).build(); } diff --git a/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/EdrCacheApiExtension.java b/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/EdrCacheApiExtension.java index b90d2f045..585c0fcc7 100644 --- a/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/EdrCacheApiExtension.java +++ b/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/EdrCacheApiExtension.java @@ -31,11 +31,7 @@ import org.eclipse.edc.transform.spi.TypeTransformerRegistry; import org.eclipse.edc.validator.spi.JsonObjectValidatorRegistry; import org.eclipse.edc.web.spi.WebService; -import org.eclipse.tractusx.edc.api.edr.v2.dto.NegotiateEdrRequestDto; import org.eclipse.tractusx.edc.api.edr.v2.transform.JsonObjectFromEndpointDataReferenceEntryTransformer; -import org.eclipse.tractusx.edc.api.edr.v2.transform.JsonObjectToNegotiateEdrRequestDtoTransformer; -import org.eclipse.tractusx.edc.api.edr.v2.transform.NegotiateEdrRequestDtoToNegotiatedEdrRequestTransformer; -import org.eclipse.tractusx.edc.api.edr.v2.validation.NegotiateEdrRequestDtoValidator; import org.eclipse.tractusx.edc.edr.spi.service.EdrService; import java.util.Map; @@ -74,10 +70,7 @@ public class EdrCacheApiExtension implements ServiceExtension { public void initialize(ServiceExtensionContext context) { jsonLdService.registerNamespace(TX_PREFIX, TX_NAMESPACE); var mgmtApiTransformerRegistry = transformerRegistry.forContext("management-api"); - mgmtApiTransformerRegistry.register(new NegotiateEdrRequestDtoToNegotiatedEdrRequestTransformer()); - mgmtApiTransformerRegistry.register(new JsonObjectToNegotiateEdrRequestDtoTransformer()); mgmtApiTransformerRegistry.register(new JsonObjectFromEndpointDataReferenceEntryTransformer(Json.createBuilderFactory(Map.of()))); - validatorRegistry.register(NegotiateEdrRequestDto.EDR_REQUEST_DTO_TYPE, NegotiateEdrRequestDtoValidator.instance()); webService.registerResource(apiConfig.getContextAlias(), new EdrCacheApiController(edrStore, mgmtApiTransformerRegistry, validatorRegistry, monitor, edrService, contractNegotiationService)); } } diff --git a/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/dto/NegotiateEdrRequestDto.java b/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/dto/NegotiateEdrRequestDto.java deleted file mode 100644 index 46760d228..000000000 --- a/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/dto/NegotiateEdrRequestDto.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -package org.eclipse.tractusx.edc.api.edr.v2.dto; - -import org.eclipse.edc.connector.controlplane.api.management.contractnegotiation.model.ContractOfferDescription; -import org.eclipse.edc.spi.types.domain.callback.CallbackAddress; - -import java.util.ArrayList; -import java.util.List; - -import static org.eclipse.edc.spi.constants.CoreConstants.EDC_NAMESPACE; -import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.TX_NAMESPACE; - -public class NegotiateEdrRequestDto { - - public static final String EDR_REQUEST_SIMPLE_DTO_TYPE = "NegotiateEdrRequestDto"; - public static final String EDR_REQUEST_DTO_TYPE = TX_NAMESPACE + EDR_REQUEST_SIMPLE_DTO_TYPE; - public static final String EDR_REQUEST_DTO_COUNTERPARTY_ADDRESS = EDC_NAMESPACE + "counterPartyAddress"; - public static final String EDR_REQUEST_DTO_PROTOCOL = EDC_NAMESPACE + "protocol"; - public static final String EDR_REQUEST_DTO_COUNTERPARTY_ID = EDC_NAMESPACE + "counterPartyId"; - public static final String EDR_REQUEST_DTO_PROVIDER_ID = EDC_NAMESPACE + "providerId"; - public static final String EDR_REQUEST_DTO_OFFER = EDC_NAMESPACE + "offer"; - public static final String EDR_REQUEST_DTO_CALLBACK_ADDRESSES = EDC_NAMESPACE + "callbackAddresses"; - - private String counterPartyAddress; - private String protocol = "ids-multipart"; - private String counterPartyId; - - private String providerId; - - private ContractOfferDescription offer; - private List callbackAddresses = new ArrayList<>(); - - private NegotiateEdrRequestDto() { - - } - - public String getCounterPartyAddress() { - return counterPartyAddress; - } - - public String getProtocol() { - return protocol; - } - - public String getCounterPartyId() { - return counterPartyId; - } - - public List getCallbackAddresses() { - return callbackAddresses; - } - - public ContractOfferDescription getOffer() { - return offer; - } - - public static final class Builder { - private final NegotiateEdrRequestDto dto; - - private Builder() { - dto = new NegotiateEdrRequestDto(); - } - - public static Builder newInstance() { - return new Builder(); - } - - public Builder connectorAddress(String connectorAddress) { - dto.counterPartyAddress = connectorAddress; - return this; - } - - public Builder protocol(String protocol) { - dto.protocol = protocol; - return this; - } - - public Builder counterPartyId(String connectorId) { - dto.counterPartyId = connectorId; - return this; - } - - public Builder offer(ContractOfferDescription offer) { - dto.offer = offer; - return this; - } - - public Builder providerId(String providerId) { - dto.providerId = providerId; - return this; - } - - public Builder callbackAddresses(List callbackAddresses) { - dto.callbackAddresses = callbackAddresses; - return this; - } - - public NegotiateEdrRequestDto build() { - return dto; - } - } -} diff --git a/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/schema/EdrSchema.java b/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/schema/EdrSchema.java deleted file mode 100644 index e62ac0d03..000000000 --- a/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/schema/EdrSchema.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -package org.eclipse.tractusx.edc.api.edr.v2.schema; - -import io.swagger.v3.oas.annotations.media.Schema; -import org.eclipse.edc.connector.api.management.configuration.ManagementApiSchema; -import org.eclipse.edc.connector.controlplane.api.management.contractnegotiation.ContractNegotiationApi; -import org.eclipse.edc.edr.spi.types.EndpointDataReferenceEntry; -import org.eclipse.tractusx.edc.api.edr.v2.dto.NegotiateEdrRequestDto; - -import java.util.List; - -import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.TYPE; -import static org.eclipse.tractusx.edc.api.edr.v2.schema.EdrSchema.EndpointDataReferenceEntrySchema.ENDPOINT_DATA_REFERENCE_ENTRY_EXAMPLE; -import static org.eclipse.tractusx.edc.api.edr.v2.schema.EdrSchema.NegotiateEdrRequestSchema.NEGOTIATE_EDR_REQUEST_EXAMPLE; - -public class EdrSchema { - - @Schema(name = "NegotiateEdrRequest", example = NEGOTIATE_EDR_REQUEST_EXAMPLE) - public record NegotiateEdrRequestSchema( - @Schema(name = TYPE, example = NegotiateEdrRequestDto.EDR_REQUEST_DTO_TYPE) - String type, - String protocol, - String connectorAddress, - @Deprecated(since = "0.1.3") - @Schema(deprecated = true, description = "please use providerId instead") - String connectorId, - String providerId, - ContractNegotiationApi.ContractOfferDescriptionSchema offer, - List callbackAddresses) { - - public static final String NEGOTIATE_EDR_REQUEST_EXAMPLE = """ - { - "@context": { "edc": "https://w3id.org/edc/v0.0.1/ns/" }, - "@type": "NegotiateEdrRequestDto", - "counterPartyAddress": "http://provider-address", - "protocol": "dataspace-protocol-http", - "providerId": "provider-id", - "offer": { - "offerId": "offer-id", - "assetId": "asset-id", - "policy": { - "@context": "http://www.w3.org/ns/odrl.jsonld", - "@type": "Set", - "@id": "offer-id", - "permission": [{ - "target": "asset-id", - "action": "display" - }] - } - }, - "callbackAddresses": [{ - "transactional": false, - "uri": "http://callback/url", - "events": ["contract.negotiation", "transfer.process"] - }] - } - """; - } - - @Schema(name = "EndpointDataReferenceEntry", example = ENDPOINT_DATA_REFERENCE_ENTRY_EXAMPLE) - public record EndpointDataReferenceEntrySchema( - @Schema(name = TYPE, example = EndpointDataReferenceEntry.SIMPLE_TYPE) - String type, - String agreementId, - String assetId, - String providerId, - String edrState, - Long expirationDate - ) { - public static final String ENDPOINT_DATA_REFERENCE_ENTRY_EXAMPLE = """ - { - "@type": "tx:EndpointDataReferenceEntry", - "agreementId": "MQ==:MQ==:ZTY3MzQ4YWEtNTdmZC00YzA0LTg2ZmQtMGMxNzk0MWM3OTkw", - "transferProcessId": "78a66945-d638-4c0a-be71-b35a0318a410", - "assetId": "1", - "providerId": "BPNL00DATAP00001", - "tx:edrState": "NEGOTIATED", - "tx:expirationDate": 1690811364000, - "@context": { - "dct": "https://purl.org/dc/terms/", - "tx": "https://w3id.org/tractusx/v0.0.1/ns/", - "edc": "https://w3id.org/edc/v0.0.1/ns/", - "dcat": "https://www.w3.org/ns/dcat/", - "odrl": "http://www.w3.org/ns/odrl/2/", - "dspace": "https://w3id.org/dspace/v0.8/" - } - } - """; - } - -} diff --git a/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/transform/JsonObjectToNegotiateEdrRequestDtoTransformer.java b/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/transform/JsonObjectToNegotiateEdrRequestDtoTransformer.java deleted file mode 100644 index ea630cdc5..000000000 --- a/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/transform/JsonObjectToNegotiateEdrRequestDtoTransformer.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -package org.eclipse.tractusx.edc.api.edr.v2.transform; - -import jakarta.json.JsonObject; -import jakarta.json.JsonValue; -import org.eclipse.edc.connector.controlplane.api.management.contractnegotiation.model.ContractOfferDescription; -import org.eclipse.edc.jsonld.spi.transformer.AbstractJsonLdTransformer; -import org.eclipse.edc.spi.types.domain.callback.CallbackAddress; -import org.eclipse.edc.transform.spi.TransformerContext; -import org.eclipse.tractusx.edc.api.edr.v2.dto.NegotiateEdrRequestDto; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.ArrayList; - - -public class JsonObjectToNegotiateEdrRequestDtoTransformer extends AbstractJsonLdTransformer { - - public JsonObjectToNegotiateEdrRequestDtoTransformer() { - super(JsonObject.class, NegotiateEdrRequestDto.class); - } - - @Override - public @Nullable NegotiateEdrRequestDto transform(@NotNull JsonObject jsonObject, @NotNull TransformerContext context) { - var builder = NegotiateEdrRequestDto.Builder.newInstance(); - - visitProperties(jsonObject, (k, v) -> setProperties(k, v, builder, context)); - return builder.build(); - } - - private void setProperties(String key, JsonValue value, NegotiateEdrRequestDto.Builder builder, TransformerContext context) { - switch (key) { - case NegotiateEdrRequestDto.EDR_REQUEST_DTO_COUNTERPARTY_ADDRESS: - transformString(value, builder::connectorAddress, context); - break; - case NegotiateEdrRequestDto.EDR_REQUEST_DTO_PROTOCOL: - transformString(value, builder::protocol, context); - break; - case NegotiateEdrRequestDto.EDR_REQUEST_DTO_COUNTERPARTY_ID: - transformString(value, builder::counterPartyId, context); - break; - case NegotiateEdrRequestDto.EDR_REQUEST_DTO_PROVIDER_ID: - transformString(value, builder::providerId, context); - break; - case NegotiateEdrRequestDto.EDR_REQUEST_DTO_CALLBACK_ADDRESSES: - var addresses = new ArrayList(); - transformArrayOrObject(value, CallbackAddress.class, addresses::add, context); - builder.callbackAddresses(addresses); - break; - case NegotiateEdrRequestDto.EDR_REQUEST_DTO_OFFER: - transformArrayOrObject(value, ContractOfferDescription.class, builder::offer, context); - break; - default: - context.problem() - .unexpectedType() - .type(NegotiateEdrRequestDto.EDR_REQUEST_DTO_TYPE) - .property(key) - .actual(key) - .expected(NegotiateEdrRequestDto.EDR_REQUEST_DTO_COUNTERPARTY_ADDRESS) - .expected(NegotiateEdrRequestDto.EDR_REQUEST_DTO_PROTOCOL) - .expected(NegotiateEdrRequestDto.EDR_REQUEST_DTO_COUNTERPARTY_ID) - .expected(NegotiateEdrRequestDto.EDR_REQUEST_DTO_PROVIDER_ID) - .expected(NegotiateEdrRequestDto.EDR_REQUEST_DTO_CALLBACK_ADDRESSES) - .expected(NegotiateEdrRequestDto.EDR_REQUEST_DTO_OFFER) - .report(); - break; - } - } -} diff --git a/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/transform/NegotiateEdrRequestDtoToNegotiatedEdrRequestTransformer.java b/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/transform/NegotiateEdrRequestDtoToNegotiatedEdrRequestTransformer.java deleted file mode 100644 index cb1f62d63..000000000 --- a/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/transform/NegotiateEdrRequestDtoToNegotiatedEdrRequestTransformer.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -package org.eclipse.tractusx.edc.api.edr.v2.transform; - -import org.eclipse.edc.connector.controlplane.contract.spi.types.offer.ContractOffer; -import org.eclipse.edc.transform.spi.TransformerContext; -import org.eclipse.edc.transform.spi.TypeTransformer; -import org.eclipse.tractusx.edc.api.edr.v2.dto.NegotiateEdrRequestDto; -import org.eclipse.tractusx.edc.edr.spi.types.NegotiateEdrRequest; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -public class NegotiateEdrRequestDtoToNegotiatedEdrRequestTransformer implements TypeTransformer { - - @Override - public Class getInputType() { - return NegotiateEdrRequestDto.class; - } - - @Override - public Class getOutputType() { - return NegotiateEdrRequest.class; - } - - @Override - public @Nullable NegotiateEdrRequest transform(@NotNull NegotiateEdrRequestDto object, @NotNull TransformerContext context) { - var contractOffer = ContractOffer.Builder.newInstance() - .id(object.getOffer().getOfferId()) - .assetId(object.getOffer().getAssetId()) - .policy(object.getOffer().getPolicy()) - .build(); - - return NegotiateEdrRequest.Builder.newInstance() - .connectorId(object.getCounterPartyId()) - .connectorAddress(object.getCounterPartyAddress()) - .protocol(object.getProtocol()) - .offer(contractOffer) - .callbackAddresses(object.getCallbackAddresses()) - .build(); - } - - private String getId(String value, String defaultValue) { - return value != null ? value : defaultValue; - } - -} diff --git a/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/validation/NegotiateEdrRequestDtoValidator.java b/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/validation/NegotiateEdrRequestDtoValidator.java deleted file mode 100644 index a7086bd39..000000000 --- a/edc-extensions/edr/edr-api-v2/src/main/java/org/eclipse/tractusx/edc/api/edr/v2/validation/NegotiateEdrRequestDtoValidator.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -package org.eclipse.tractusx.edc.api.edr.v2.validation; - -import jakarta.json.JsonObject; -import org.eclipse.edc.validator.jsonobject.JsonObjectValidator; -import org.eclipse.edc.validator.jsonobject.validators.MandatoryObject; -import org.eclipse.edc.validator.jsonobject.validators.MandatoryValue; -import org.eclipse.edc.validator.spi.Validator; -import org.eclipse.tractusx.edc.api.edr.v2.dto.NegotiateEdrRequestDto; - -import static org.eclipse.edc.connector.controlplane.api.management.contractnegotiation.model.ContractOfferDescription.ASSET_ID; -import static org.eclipse.edc.connector.controlplane.api.management.contractnegotiation.model.ContractOfferDescription.OFFER_ID; -import static org.eclipse.edc.connector.controlplane.api.management.contractnegotiation.model.ContractOfferDescription.POLICY; - - -public class NegotiateEdrRequestDtoValidator { - - private NegotiateEdrRequestDtoValidator() { - } - - public static Validator instance() { - return JsonObjectValidator.newValidator() - .verify(NegotiateEdrRequestDto.EDR_REQUEST_DTO_COUNTERPARTY_ADDRESS, MandatoryValue::new) - .verify(NegotiateEdrRequestDto.EDR_REQUEST_DTO_PROTOCOL, MandatoryValue::new) - .verify(NegotiateEdrRequestDto.EDR_REQUEST_DTO_OFFER, MandatoryObject::new) - .verifyObject(NegotiateEdrRequestDto.EDR_REQUEST_DTO_OFFER, v -> v - .verify(OFFER_ID, MandatoryValue::new) - .verify(ASSET_ID, MandatoryValue::new) - .verify(POLICY, MandatoryObject::new) - ) - .build(); - } -} diff --git a/edc-extensions/edr/edr-api-v2/src/test/java/org/eclipse/tractusx/edc/api/edr/v2/EdrCacheApiControllerTest.java b/edc-extensions/edr/edr-api-v2/src/test/java/org/eclipse/tractusx/edc/api/edr/v2/EdrCacheApiControllerTest.java index 6d8fce426..ae7017dfa 100644 --- a/edc-extensions/edr/edr-api-v2/src/test/java/org/eclipse/tractusx/edc/api/edr/v2/EdrCacheApiControllerTest.java +++ b/edc-extensions/edr/edr-api-v2/src/test/java/org/eclipse/tractusx/edc/api/edr/v2/EdrCacheApiControllerTest.java @@ -24,10 +24,13 @@ import jakarta.json.JsonObject; import jakarta.json.JsonObjectBuilder; import org.eclipse.edc.api.model.IdResponse; +import org.eclipse.edc.connector.controlplane.contract.spi.types.negotiation.ContractRequest; +import org.eclipse.edc.connector.controlplane.contract.spi.types.offer.ContractOffer; import org.eclipse.edc.connector.controlplane.services.spi.contractnegotiation.ContractNegotiationService; import org.eclipse.edc.edr.spi.store.EndpointDataReferenceStore; import org.eclipse.edc.edr.spi.types.EndpointDataReferenceEntry; import org.eclipse.edc.junit.annotations.ApiTest; +import org.eclipse.edc.policy.model.Policy; import org.eclipse.edc.spi.query.QuerySpec; import org.eclipse.edc.spi.result.Result; import org.eclipse.edc.spi.result.ServiceResult; @@ -37,9 +40,7 @@ import org.eclipse.edc.validator.spi.JsonObjectValidatorRegistry; import org.eclipse.edc.validator.spi.ValidationResult; import org.eclipse.edc.web.jersey.testfixtures.RestControllerTestBase; -import org.eclipse.tractusx.edc.api.edr.v2.dto.NegotiateEdrRequestDto; import org.eclipse.tractusx.edc.edr.spi.service.EdrService; -import org.eclipse.tractusx.edc.edr.spi.types.NegotiateEdrRequest; import org.junit.jupiter.api.Test; import java.util.List; @@ -47,6 +48,7 @@ import static io.restassured.RestAssured.given; import static io.restassured.http.ContentType.JSON; import static jakarta.json.Json.createObjectBuilder; +import static java.util.UUID.randomUUID; import static org.eclipse.edc.api.model.IdResponse.ID_RESPONSE_TYPE; import static org.eclipse.edc.edr.spi.types.EndpointDataReferenceEntry.EDR_ENTRY_AGREEMENT_ID; import static org.eclipse.edc.edr.spi.types.EndpointDataReferenceEntry.EDR_ENTRY_ASSET_ID; @@ -62,7 +64,6 @@ import static org.eclipse.edc.spi.constants.CoreConstants.EDC_PREFIX; import static org.eclipse.tractusx.edc.api.edr.v2.TestFunctions.createContractNegotiation; import static org.eclipse.tractusx.edc.api.edr.v2.TestFunctions.negotiationRequest; -import static org.eclipse.tractusx.edc.api.edr.v2.TestFunctions.openRequest; import static org.eclipse.tractusx.edc.edr.spi.types.RefreshMode.AUTO_REFRESH; import static org.eclipse.tractusx.edc.edr.spi.types.RefreshMode.NO_REFRESH; import static org.hamcrest.Matchers.equalTo; @@ -96,12 +97,10 @@ public class EdrCacheApiControllerTest extends RestControllerTestBase { void initEdrNegotiation_shouldWork_whenValidRequest() { when(validator.validate(any(), any())).thenReturn(ValidationResult.success()); - var openRequest = openRequest(); var contractNegotiation = createContractNegotiation(); var responseBody = Json.createObjectBuilder().add(TYPE, ID_RESPONSE_TYPE).add(ID, contractNegotiation.getId()).build(); - when(transformerRegistry.transform(any(JsonObject.class), eq(NegotiateEdrRequestDto.class))).thenReturn(Result.success(NegotiateEdrRequestDto.Builder.newInstance().build())); - when(transformerRegistry.transform(any(), eq(NegotiateEdrRequest.class))).thenReturn(Result.success(openRequest)); + when(transformerRegistry.transform(any(JsonObject.class), eq(ContractRequest.class))).thenReturn(Result.success(createContractRequest())); when(contractNegotiationService.initiateNegotiation(any())).thenReturn(contractNegotiation); when(transformerRegistry.transform(any(IdResponse.class), eq(JsonObject.class))).thenReturn(Result.success(responseBody)); @@ -121,12 +120,11 @@ void initEdrNegotiation_shouldWork_whenValidRequest() { void initEdrNegotiation_shouldReturnBadRequest_whenValidInvalidRequest() { when(validator.validate(any(), any())).thenReturn(ValidationResult.success()); - var request = NegotiateEdrRequestDto.Builder.newInstance().build(); - when(transformerRegistry.transform(any(JsonObject.class), eq(NegotiateEdrRequestDto.class))).thenReturn(Result.failure("fail")); + when(transformerRegistry.transform(any(JsonObject.class), eq(ContractRequest.class))).thenReturn(Result.failure("fail")); baseRequest() .contentType(JSON) - .body(request) + .body(Json.createObjectBuilder().build()) .post("/v2/edrs") .then() .statusCode(400); @@ -296,6 +294,17 @@ private JsonObjectBuilder createContextBuilder() { .add(EDC_PREFIX, EDC_NAMESPACE); } + private ContractRequest createContractRequest() { + return ContractRequest.Builder.newInstance() + .protocol("test-protocol") + .counterPartyAddress("test-cb") + .contractOffer(ContractOffer.Builder.newInstance() + .id("test-offer-id") + .assetId(randomUUID().toString()) + .policy(Policy.Builder.newInstance().build()) + .build()) + .build(); + } private RequestSpecification baseRequest() { return given() diff --git a/edc-extensions/edr/edr-api-v2/src/test/java/org/eclipse/tractusx/edc/api/edr/v2/TestFunctions.java b/edc-extensions/edr/edr-api-v2/src/test/java/org/eclipse/tractusx/edc/api/edr/v2/TestFunctions.java index 44837c176..45ac84014 100644 --- a/edc-extensions/edr/edr-api-v2/src/test/java/org/eclipse/tractusx/edc/api/edr/v2/TestFunctions.java +++ b/edc-extensions/edr/edr-api-v2/src/test/java/org/eclipse/tractusx/edc/api/edr/v2/TestFunctions.java @@ -21,47 +21,17 @@ import jakarta.json.Json; import jakarta.json.JsonObject; -import org.eclipse.edc.connector.controlplane.api.management.contractnegotiation.model.ContractOfferDescription; import org.eclipse.edc.connector.controlplane.contract.spi.types.negotiation.ContractNegotiation; -import org.eclipse.edc.connector.controlplane.contract.spi.types.offer.ContractOffer; -import org.eclipse.edc.policy.model.Policy; -import org.eclipse.tractusx.edc.api.edr.v2.dto.NegotiateEdrRequestDto; -import org.eclipse.tractusx.edc.edr.spi.types.NegotiateEdrRequest; - -import java.util.UUID; +import org.eclipse.edc.connector.controlplane.contract.spi.types.negotiation.ContractRequest; import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.TYPE; import static org.eclipse.edc.spi.constants.CoreConstants.EDC_NAMESPACE; public class TestFunctions { - public static ContractOfferDescription createOffer(String offerId, String assetId) { - return ContractOfferDescription.Builder.newInstance() - .offerId(offerId) - .assetId(assetId) - .policy(Policy.Builder.newInstance().build()) - .build(); - } - - public static ContractOfferDescription createOffer(Policy policy) { - return ContractOfferDescription.Builder.newInstance() - .offerId(UUID.randomUUID().toString()) - .assetId(UUID.randomUUID().toString()) - .policy(policy) - .build(); - } - - public static ContractOfferDescription createOffer(String offerId) { - return createOffer(offerId, UUID.randomUUID().toString()); - } - - public static ContractOfferDescription createOffer() { - return createOffer(UUID.randomUUID().toString(), UUID.randomUUID().toString()); - } - public static JsonObject negotiationRequest() { return Json.createObjectBuilder() - .add(TYPE, NegotiateEdrRequestDto.EDR_REQUEST_DTO_TYPE) + .add(TYPE, ContractRequest.CONTRACT_REQUEST_TYPE) .add(EDC_NAMESPACE + "connectorId", "test") .add(EDC_NAMESPACE + "providerId", "test") .add(EDC_NAMESPACE + "connectorAddress", "test") @@ -74,18 +44,6 @@ public static JsonObject negotiationRequest() { .build(); } - public static NegotiateEdrRequest openRequest() { - return NegotiateEdrRequest.Builder.newInstance() - .connectorAddress("test") - .connectorId("id") - .protocol("test-protocol") - .offer(ContractOffer.Builder.newInstance() - .id("offerId") - .assetId("assetId") - .policy(Policy.Builder.newInstance().build()).build()) - .build(); - } - public static ContractNegotiation createContractNegotiation() { return ContractNegotiation.Builder.newInstance() .id("id") diff --git a/edc-extensions/edr/edr-api-v2/src/test/java/org/eclipse/tractusx/edc/api/edr/v2/transform/JsonObjectToNegotiateEdrRequestDtoTransformerTest.java b/edc-extensions/edr/edr-api-v2/src/test/java/org/eclipse/tractusx/edc/api/edr/v2/transform/JsonObjectToNegotiateEdrRequestDtoTransformerTest.java deleted file mode 100644 index d48b3943e..000000000 --- a/edc-extensions/edr/edr-api-v2/src/test/java/org/eclipse/tractusx/edc/api/edr/v2/transform/JsonObjectToNegotiateEdrRequestDtoTransformerTest.java +++ /dev/null @@ -1,155 +0,0 @@ -/* - * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -package org.eclipse.tractusx.edc.api.edr.v2.transform; - -import jakarta.json.Json; -import jakarta.json.JsonArrayBuilder; -import jakarta.json.JsonObject; -import jakarta.json.JsonValue; -import org.eclipse.edc.connector.controlplane.api.management.contractnegotiation.model.ContractOfferDescription; -import org.eclipse.edc.jsonld.TitaniumJsonLd; -import org.eclipse.edc.jsonld.spi.JsonLd; -import org.eclipse.edc.spi.monitor.Monitor; -import org.eclipse.edc.spi.types.domain.callback.CallbackAddress; -import org.eclipse.edc.transform.spi.ProblemBuilder; -import org.eclipse.edc.transform.spi.TransformerContext; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import java.util.Set; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.eclipse.edc.connector.controlplane.api.management.contractnegotiation.model.ContractOfferDescription.OFFER_ID; -import static org.eclipse.edc.connector.controlplane.contract.spi.types.negotiation.ContractRequest.CALLBACK_ADDRESSES; -import static org.eclipse.edc.connector.controlplane.contract.spi.types.negotiation.ContractRequest.CONTRACT_REQUEST_TYPE; -import static org.eclipse.edc.connector.controlplane.contract.spi.types.negotiation.ContractRequest.OFFER; -import static org.eclipse.edc.connector.controlplane.contract.spi.types.negotiation.ContractRequest.POLICY; -import static org.eclipse.edc.connector.controlplane.contract.spi.types.negotiation.ContractRequest.PROTOCOL; -import static org.eclipse.edc.edr.spi.types.EndpointDataReferenceEntry.ASSET_ID; -import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.TYPE; -import static org.eclipse.edc.jsonld.spi.PropertyAndTypeNames.ODRL_OBLIGATION_ATTRIBUTE; -import static org.eclipse.edc.jsonld.spi.PropertyAndTypeNames.ODRL_PERMISSION_ATTRIBUTE; -import static org.eclipse.edc.jsonld.spi.PropertyAndTypeNames.ODRL_POLICY_TYPE_SET; -import static org.eclipse.edc.jsonld.spi.PropertyAndTypeNames.ODRL_PROHIBITION_ATTRIBUTE; -import static org.eclipse.edc.spi.constants.CoreConstants.EDC_NAMESPACE; -import static org.eclipse.edc.spi.types.domain.callback.CallbackAddress.EVENTS; -import static org.eclipse.edc.spi.types.domain.callback.CallbackAddress.IS_TRANSACTIONAL; -import static org.eclipse.edc.spi.types.domain.callback.CallbackAddress.URI; -import static org.eclipse.tractusx.edc.api.edr.v2.dto.NegotiateEdrRequestDto.EDR_REQUEST_DTO_COUNTERPARTY_ADDRESS; -import static org.eclipse.tractusx.edc.api.edr.v2.dto.NegotiateEdrRequestDto.EDR_REQUEST_DTO_COUNTERPARTY_ID; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -class JsonObjectToNegotiateEdrRequestDtoTransformerTest { - - private final JsonLd jsonLd = new TitaniumJsonLd(mock(Monitor.class)); - private final TransformerContext context = mock(TransformerContext.class); - private JsonObjectToNegotiateEdrRequestDtoTransformer transformer; - - @BeforeEach - void setUp() { - transformer = new JsonObjectToNegotiateEdrRequestDtoTransformer(); - } - - @Test - void transform() { - var jsonObject = Json.createObjectBuilder() - .add(TYPE, CONTRACT_REQUEST_TYPE) - .add(EDR_REQUEST_DTO_COUNTERPARTY_ADDRESS, "test-address") - .add(EDR_REQUEST_DTO_COUNTERPARTY_ID, "test-conn-id") - .add(PROTOCOL, "test-protocol") - .add(CALLBACK_ADDRESSES, createCallbackAddress()) - .add(OFFER, Json.createObjectBuilder() - .add(OFFER_ID, "test-offer-id") - .add(ASSET_ID, "test-asset") - .add(POLICY, createPolicy()) - .build()) - .build(); - - when(context.transform(any(JsonValue.class), eq(ContractOfferDescription.class))).thenReturn(ContractOfferDescription.Builder.newInstance().build()); - - when(context.transform(any(JsonObject.class), eq(CallbackAddress.class))).thenReturn(CallbackAddress.Builder.newInstance() - .uri("http://test.local") - .events(Set.of("foo", "bar")) - .transactional(true) - .build()); - when(context.transform(any(CallbackAddress.class), eq(CallbackAddress.class))).thenReturn(CallbackAddress.Builder.newInstance() - .uri("http://test.local") - .events(Set.of("foo", "bar")) - .transactional(true) - .build()); - var dto = transformer.transform(jsonLd.expand(jsonObject).getContent(), context); - - assertThat(dto).isNotNull(); - assertThat(dto.getCallbackAddresses()).isNotEmpty(); - assertThat(dto.getProtocol()).isEqualTo("test-protocol"); - assertThat(dto.getCounterPartyAddress()).isEqualTo("test-address"); - assertThat(dto.getCounterPartyId()).isEqualTo("test-conn-id"); - assertThat(dto.getOffer()).isNotNull(); - - } - - @Test - void transform_reportErrors() { - - when(context.problem()).thenReturn(new ProblemBuilder(context)); - - var jsonObject = Json.createObjectBuilder() - .add(TYPE, CONTRACT_REQUEST_TYPE) - .add(EDC_NAMESPACE + "notFound", "test-address") - .build(); - - var dto = transformer.transform(jsonLd.expand(jsonObject).getContent(), context); - - assertThat(dto).isNotNull(); - verify(context, times(1)).reportProblem(anyString()); - } - - private JsonArrayBuilder createCallbackAddress() { - var builder = Json.createArrayBuilder(); - return builder.add(Json.createObjectBuilder() - .add(IS_TRANSACTIONAL, true) - .add(URI, "http://test.local/") - .add(EVENTS, Json.createArrayBuilder().build())); - } - - private JsonObject createPolicy() { - var permissionJson = getJsonObject("permission"); - var prohibitionJson = getJsonObject("prohibition"); - var dutyJson = getJsonObject("duty"); - return Json.createObjectBuilder() - .add(TYPE, ODRL_POLICY_TYPE_SET) - .add(ODRL_PERMISSION_ATTRIBUTE, permissionJson) - .add(ODRL_PROHIBITION_ATTRIBUTE, prohibitionJson) - .add(ODRL_OBLIGATION_ATTRIBUTE, dutyJson) - .build(); - } - - private JsonObject getJsonObject(String type) { - return Json.createObjectBuilder() - .add(TYPE, type) - .build(); - } -} diff --git a/edc-extensions/edr/edr-api-v2/src/test/java/org/eclipse/tractusx/edc/api/edr/v2/transform/NegotiateEdrRequestDtoToNegotiateEdrRequestTransformerTest.java b/edc-extensions/edr/edr-api-v2/src/test/java/org/eclipse/tractusx/edc/api/edr/v2/transform/NegotiateEdrRequestDtoToNegotiateEdrRequestTransformerTest.java deleted file mode 100644 index 24a31450c..000000000 --- a/edc-extensions/edr/edr-api-v2/src/test/java/org/eclipse/tractusx/edc/api/edr/v2/transform/NegotiateEdrRequestDtoToNegotiateEdrRequestTransformerTest.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -package org.eclipse.tractusx.edc.api.edr.v2.transform; - -import org.eclipse.edc.spi.types.domain.callback.CallbackAddress; -import org.eclipse.edc.transform.spi.TransformerContext; -import org.eclipse.tractusx.edc.api.edr.v2.dto.NegotiateEdrRequestDto; -import org.junit.jupiter.api.Test; - -import java.util.List; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.eclipse.tractusx.edc.api.edr.v2.TestFunctions.createOffer; -import static org.mockito.Mockito.mock; - -public class NegotiateEdrRequestDtoToNegotiateEdrRequestTransformerTest { - - private final NegotiateEdrRequestDtoToNegotiatedEdrRequestTransformer transformer = new NegotiateEdrRequestDtoToNegotiatedEdrRequestTransformer(); - - private final TransformerContext context = mock(TransformerContext.class); - - @Test - void inputOutputType() { - assertThat(transformer.getInputType()).isNotNull(); - assertThat(transformer.getOutputType()).isNotNull(); - } - - @Test - void verify_transform() { - var callback = CallbackAddress.Builder.newInstance() - .uri("local://test") - .build(); - var dto = NegotiateEdrRequestDto.Builder.newInstance() - .counterPartyId("connectorId") - .connectorAddress("address") - .protocol("protocol") - .providerId("test-provider") - .offer(createOffer("offerId", "assetId")) - .callbackAddresses(List.of(callback)) - .build(); - - var request = transformer.transform(dto, context); - - assertThat(request).isNotNull(); - assertThat(request.getConnectorId()).isEqualTo("connectorId"); - assertThat(request.getConnectorAddress()).isEqualTo("address"); - assertThat(request.getProtocol()).isEqualTo("protocol"); - assertThat(request.getOffer().getId()).isEqualTo("offerId"); - assertThat(request.getOffer().getPolicy()).isNotNull(); - assertThat(request.getCallbackAddresses()).hasSize(1); - } - - @Test - void verify_transfor_withNoProviderId() { - var dto = NegotiateEdrRequestDto.Builder.newInstance() - .counterPartyId("connectorId") - .connectorAddress("address") - .protocol("protocol") - // do not set provider ID - .offer(createOffer("offerId", "assetId")) - .build(); - - var request = transformer.transform(dto, context); - - assertThat(request).isNotNull(); - } - - @Test - void verify_transform_withNoConsumerId() { - var dto = NegotiateEdrRequestDto.Builder.newInstance() - .counterPartyId("connectorId") - .connectorAddress("address") - .protocol("protocol") - // do not set consumer ID - .providerId("urn:connector:test-provider") - .offer(createOffer("offerId", "assetId")) - .build(); - - var request = transformer.transform(dto, context); - assertThat(request).isNotNull(); - } -} diff --git a/edc-extensions/edr/edr-api-v2/src/test/java/org/eclipse/tractusx/edc/api/edr/v2/validation/NegotiateEdrRequestDtoValidatorTest.java b/edc-extensions/edr/edr-api-v2/src/test/java/org/eclipse/tractusx/edc/api/edr/v2/validation/NegotiateEdrRequestDtoValidatorTest.java deleted file mode 100644 index 8f75402e0..000000000 --- a/edc-extensions/edr/edr-api-v2/src/test/java/org/eclipse/tractusx/edc/api/edr/v2/validation/NegotiateEdrRequestDtoValidatorTest.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -package org.eclipse.tractusx.edc.api.edr.v2.validation; - -import jakarta.json.Json; -import jakarta.json.JsonArrayBuilder; -import jakarta.json.JsonObject; -import org.eclipse.edc.validator.spi.ValidationFailure; -import org.eclipse.edc.validator.spi.Validator; -import org.eclipse.edc.validator.spi.Violation; -import org.junit.jupiter.api.Test; - -import static jakarta.json.Json.createArrayBuilder; -import static jakarta.json.Json.createObjectBuilder; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.InstanceOfAssertFactories.list; -import static org.eclipse.edc.connector.controlplane.api.management.contractnegotiation.model.ContractOfferDescription.ASSET_ID; -import static org.eclipse.edc.connector.controlplane.api.management.contractnegotiation.model.ContractOfferDescription.OFFER_ID; -import static org.eclipse.edc.connector.controlplane.api.management.contractnegotiation.model.ContractOfferDescription.POLICY; -import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.VALUE; -import static org.eclipse.edc.junit.assertions.AbstractResultAssert.assertThat; -import static org.eclipse.tractusx.edc.api.edr.v2.dto.NegotiateEdrRequestDto.EDR_REQUEST_DTO_COUNTERPARTY_ADDRESS; -import static org.eclipse.tractusx.edc.api.edr.v2.dto.NegotiateEdrRequestDto.EDR_REQUEST_DTO_OFFER; -import static org.eclipse.tractusx.edc.api.edr.v2.dto.NegotiateEdrRequestDto.EDR_REQUEST_DTO_PROTOCOL; -import static org.eclipse.tractusx.edc.api.edr.v2.dto.NegotiateEdrRequestDto.EDR_REQUEST_DTO_PROVIDER_ID; - -public class NegotiateEdrRequestDtoValidatorTest { - - private final Validator validator = NegotiateEdrRequestDtoValidator.instance(); - - @Test - void shouldSuccess_whenObjectIsValid() { - var input = Json.createObjectBuilder() - .add(EDR_REQUEST_DTO_COUNTERPARTY_ADDRESS, value("http://connector-address")) - .add(EDR_REQUEST_DTO_PROTOCOL, value("protocol")) - .add(EDR_REQUEST_DTO_PROVIDER_ID, value("connector-id")) - .add(EDR_REQUEST_DTO_OFFER, createArrayBuilder().add(createObjectBuilder() - .add(OFFER_ID, value("offerId")) - .add(ASSET_ID, value("offerId")) - .add(POLICY, createArrayBuilder().add(createObjectBuilder())) - )) - .build(); - - var result = validator.validate(input); - - assertThat(result).isSucceeded(); - } - - @Test - void shouldFail_whenMandatoryPropertiesAreMissing() { - var input = Json.createObjectBuilder().build(); - - var result = validator.validate(input); - - assertThat(result).isFailed().extracting(ValidationFailure::getViolations).asInstanceOf(list(Violation.class)) - .isNotEmpty() - .anySatisfy(violation -> assertThat(violation.path()).isEqualTo(EDR_REQUEST_DTO_COUNTERPARTY_ADDRESS)) - .anySatisfy(violation -> assertThat(violation.path()).isEqualTo(EDR_REQUEST_DTO_PROTOCOL)) - .anySatisfy(violation -> assertThat(violation.path()).isEqualTo(EDR_REQUEST_DTO_OFFER)); - } - - @Test - void shouldFail_whenOfferMandatoryPropertiesAreMissing() { - var input = Json.createObjectBuilder() - .add(EDR_REQUEST_DTO_COUNTERPARTY_ADDRESS, value("http://connector-address")) - .add(EDR_REQUEST_DTO_PROTOCOL, value("protocol")) - .add(EDR_REQUEST_DTO_PROVIDER_ID, value("connector-id")) - .add(EDR_REQUEST_DTO_OFFER, createArrayBuilder().add(createObjectBuilder())) - .build(); - - var result = validator.validate(input); - - assertThat(result).isFailed().extracting(ValidationFailure::getViolations).asInstanceOf(list(Violation.class)) - .isNotEmpty() - .anySatisfy(violation -> assertThat(violation.path()).isEqualTo(EDR_REQUEST_DTO_OFFER + "/" + OFFER_ID)) - .anySatisfy(violation -> assertThat(violation.path()).isEqualTo(EDR_REQUEST_DTO_OFFER + "/" + ASSET_ID)) - .anySatisfy(violation -> assertThat(violation.path()).isEqualTo(EDR_REQUEST_DTO_OFFER + "/" + POLICY)); - } - - private JsonArrayBuilder value(String value) { - return createArrayBuilder().add(createObjectBuilder().add(VALUE, value)); - } -} diff --git a/edc-extensions/edr/edr-callback/src/main/java/org/eclipse/tractusx/edc/callback/ContractNegotiationCallback.java b/edc-extensions/edr/edr-callback/src/main/java/org/eclipse/tractusx/edc/callback/ContractNegotiationCallback.java index 015bf53ab..b9e2afda0 100644 --- a/edc-extensions/edr/edr-callback/src/main/java/org/eclipse/tractusx/edc/callback/ContractNegotiationCallback.java +++ b/edc-extensions/edr/edr-callback/src/main/java/org/eclipse/tractusx/edc/callback/ContractNegotiationCallback.java @@ -35,7 +35,8 @@ public class ContractNegotiationCallback implements InProcessCallback { - public static final DataAddress DATA_DESTINATION = DataAddress.Builder.newInstance().type("HttpProxy-PULL").build(); + public static final DataAddress DATA_DESTINATION = DataAddress.Builder.newInstance().type("HttpProxy").build(); + private static final String TRANSFER_TYPE = "HttpData-PULL"; private final TransferProcessService transferProcessService; private final Monitor monitor; @@ -62,6 +63,7 @@ private Result initiateTransfer(ContractNegotiationFinalized negotiationFi .counterPartyAddress(negotiationFinalized.getCounterPartyAddress()) .protocol(negotiationFinalized.getProtocol()) .dataDestination(DATA_DESTINATION) + .transferType(TRANSFER_TYPE) .callbackAddresses(negotiationFinalized.getCallbackAddresses()) .build(); diff --git a/edc-extensions/postgresql-migration/src/main/java/org/eclipse/tractusx/edc/postgresql/migration/EdrPostgresqlMigrationExtension.java b/edc-extensions/postgresql-migration/src/main/java/org/eclipse/tractusx/edc/postgresql/migration/EdrPostgresqlMigrationExtension.java deleted file mode 100644 index cbf82303d..000000000 --- a/edc-extensions/postgresql-migration/src/main/java/org/eclipse/tractusx/edc/postgresql/migration/EdrPostgresqlMigrationExtension.java +++ /dev/null @@ -1,28 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.postgresql.migration; - -public class EdrPostgresqlMigrationExtension extends AbstractPostgresqlMigrationExtension { - private static final String NAME_SUBSYSTEM = "edr"; - - protected String getSubsystemName() { - return NAME_SUBSYSTEM; - } -} diff --git a/edc-extensions/postgresql-migration/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension b/edc-extensions/postgresql-migration/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension index d89bb3f09..1d524a071 100644 --- a/edc-extensions/postgresql-migration/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension +++ b/edc-extensions/postgresql-migration/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension @@ -25,5 +25,4 @@ org.eclipse.tractusx.edc.postgresql.migration.ContractNegotiationPostgresqlMigra org.eclipse.tractusx.edc.postgresql.migration.PolicyPostgresqlMigrationExtension org.eclipse.tractusx.edc.postgresql.migration.PolicyMonitorPostgresqlMigrationExtension org.eclipse.tractusx.edc.postgresql.migration.TransferProcessPostgresqlMigrationExtension -org.eclipse.tractusx.edc.postgresql.migration.EdrPostgresqlMigrationExtension org.eclipse.tractusx.edc.postgresql.migration.BusinessGroupPostgresMigrationExtension diff --git a/edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/edr/V0_0_1__Init_Edr_Database_Schema.sql b/edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/edr/V0_0_1__Init_Edr_Database_Schema.sql deleted file mode 100644 index 0e166045b..000000000 --- a/edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/edr/V0_0_1__Init_Edr_Database_Schema.sql +++ /dev/null @@ -1,34 +0,0 @@ --- --- Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) --- --- This program and the accompanying materials are made available under the --- terms of the Apache License, Version 2.0 which is available at --- https://www.apache.org/licenses/LICENSE-2.0 --- --- SPDX-License-Identifier: Apache-2.0 --- --- Contributors: --- Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - initial API and implementation --- - --- Statements are designed for and tested with Postgres only! - - -CREATE TABLE IF NOT EXISTS edc_edr_cache -( - transfer_process_id VARCHAR NOT NULL PRIMARY KEY, - agreement_id VARCHAR NOT NULL, - asset_id VARCHAR NOT NULL, - edr_id VARCHAR NOT NULL, - created_at BIGINT NOT NULL, - updated_at BIGINT NOT NULL -); - - -CREATE INDEX IF NOT EXISTS edc_edr_asset_id_index - ON edc_edr_cache (asset_id); - - -CREATE INDEX IF NOT EXISTS edc_edr_agreement_id_index - ON edc_edr_cache (agreement_id); - diff --git a/edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/edr/V0_0_2__Add_ProviderId_Column.sql b/edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/edr/V0_0_2__Add_ProviderId_Column.sql deleted file mode 100644 index ee20b3990..000000000 --- a/edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/edr/V0_0_2__Add_ProviderId_Column.sql +++ /dev/null @@ -1,19 +0,0 @@ --- --- Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) --- --- This program and the accompanying materials are made available under the --- terms of the Apache License, Version 2.0 which is available at --- https://www.apache.org/licenses/LICENSE-2.0 --- --- SPDX-License-Identifier: Apache-2.0 --- --- Contributors: --- Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - initial API and implementation --- - --- Statements are designed for and tested with Postgres only! - - --- add column -ALTER TABLE edc_edr_cache ADD COLUMN provider_id VARCHAR; - diff --git a/edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/edr/V0_0_3__Add_StatefulEntity_Columns.sql b/edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/edr/V0_0_3__Add_StatefulEntity_Columns.sql deleted file mode 100644 index a3442e00b..000000000 --- a/edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/edr/V0_0_3__Add_StatefulEntity_Columns.sql +++ /dev/null @@ -1,24 +0,0 @@ --- --- Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) --- --- This program and the accompanying materials are made available under the --- terms of the Apache License, Version 2.0 which is available at --- https://www.apache.org/licenses/LICENSE-2.0 --- --- SPDX-License-Identifier: Apache-2.0 --- --- Contributors: --- Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - initial API and implementation --- - --- Statements are designed for and tested with Postgres only! - - --- add column -ALTER TABLE edc_edr_cache ADD COLUMN expiration_timestamp BIGINT; -ALTER TABLE edc_edr_cache ADD COLUMN state INTEGER DEFAULT 50 NOT NULL; -ALTER TABLE edc_edr_cache ADD COLUMN state_count INTEGER DEFAULT 0; -ALTER TABLE edc_edr_cache ADD COLUMN state_timestamp BIGINT; -ALTER TABLE edc_edr_cache ADD COLUMN error_detail VARCHAR; -ALTER TABLE edc_edr_cache ADD COLUMN lease_id VARCHAR CONSTRAINT edc_edr_cache_lease_lease_id_fk REFERENCES edc_lease ON DELETE SET NULL; - diff --git a/edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/edr/V0_0_4__Add_ContractNegotiationId_Column.sql b/edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/edr/V0_0_4__Add_ContractNegotiationId_Column.sql deleted file mode 100644 index 291f325c3..000000000 --- a/edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/edr/V0_0_4__Add_ContractNegotiationId_Column.sql +++ /dev/null @@ -1,19 +0,0 @@ --- --- Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) --- --- This program and the accompanying materials are made available under the --- terms of the Apache License, Version 2.0 which is available at --- https://www.apache.org/licenses/LICENSE-2.0 --- --- SPDX-License-Identifier: Apache-2.0 --- --- Contributors: --- Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - initial API and implementation --- - --- Statements are designed for and tested with Postgres only! - - --- add column -ALTER TABLE edc_edr_cache ADD COLUMN contract_negotiation_id VARCHAR; - diff --git a/edc-tests/edc-controlplane/edr-api-tests/src/test/java/org/eclipse/tractusx/edc/tests/edrv2/AbstractNegotiateEdrTest.java b/edc-tests/edc-controlplane/edr-api-tests/src/test/java/org/eclipse/tractusx/edc/tests/edrv2/AbstractNegotiateEdrTest.java deleted file mode 100644 index 4443d84f5..000000000 --- a/edc-tests/edc-controlplane/edr-api-tests/src/test/java/org/eclipse/tractusx/edc/tests/edrv2/AbstractNegotiateEdrTest.java +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -package org.eclipse.tractusx.edc.tests.edrv2; - -import jakarta.json.Json; -import okhttp3.mockwebserver.MockResponse; -import okhttp3.mockwebserver.MockWebServer; -import org.eclipse.edc.connector.controlplane.contract.spi.event.contractnegotiation.ContractNegotiationAgreed; -import org.eclipse.edc.connector.controlplane.contract.spi.event.contractnegotiation.ContractNegotiationFinalized; -import org.eclipse.edc.connector.controlplane.contract.spi.event.contractnegotiation.ContractNegotiationInitiated; -import org.eclipse.edc.connector.controlplane.contract.spi.event.contractnegotiation.ContractNegotiationRequested; -import org.eclipse.edc.connector.controlplane.contract.spi.event.contractnegotiation.ContractNegotiationVerified; -import org.eclipse.edc.connector.controlplane.transfer.spi.event.TransferProcessInitiated; -import org.eclipse.edc.connector.controlplane.transfer.spi.event.TransferProcessProvisioned; -import org.eclipse.edc.connector.controlplane.transfer.spi.event.TransferProcessRequested; -import org.eclipse.edc.connector.controlplane.transfer.spi.event.TransferProcessStarted; -import org.eclipse.edc.policy.model.Operator; -import org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration; -import org.eclipse.tractusx.edc.tests.helpers.EdrNegotiationHelperFunctions; -import org.eclipse.tractusx.edc.tests.helpers.PolicyHelperFunctions; -import org.eclipse.tractusx.edc.tests.participant.TransferParticipant; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; - -import java.io.IOException; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.stream.Collectors; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.awaitility.Awaitility.await; -import static org.eclipse.tractusx.edc.tests.helpers.EdrNegotiationHelperFunctions.createEvent; -import static org.eclipse.tractusx.edc.tests.helpers.Functions.waitForEvent; -import static org.eclipse.tractusx.edc.tests.participant.TractusxParticipantBase.ASYNC_POLL_INTERVAL; -import static org.eclipse.tractusx.edc.tests.participant.TractusxParticipantBase.ASYNC_TIMEOUT; - -public abstract class AbstractNegotiateEdrTest { - - protected static final TransferParticipant SOKRATES = TransferParticipant.Builder.newInstance() - .name(TestRuntimeConfiguration.SOKRATES_NAME) - .id(TestRuntimeConfiguration.SOKRATES_BPN) - .build(); - - protected static final TransferParticipant PLATO = TransferParticipant.Builder.newInstance() - .name(TestRuntimeConfiguration.PLATO_NAME) - .id(TestRuntimeConfiguration.PLATO_BPN) - .build(); - - MockWebServer server; - - @BeforeEach - void setup() { - server = new MockWebServer(); - } - - @Test - @DisplayName("Verify that the callbacks are invoked when negotiating an EDR") - void negotiateEdr_shouldInvokeCallbacks() throws IOException { - - var expectedEvents = List.of( - createEvent(ContractNegotiationInitiated.class), - createEvent(ContractNegotiationRequested.class), - createEvent(ContractNegotiationAgreed.class), - createEvent(ContractNegotiationFinalized.class), - createEvent(ContractNegotiationVerified.class), - createEvent(TransferProcessInitiated.class), - createEvent(TransferProcessProvisioned.class), - createEvent(TransferProcessRequested.class), - createEvent(TransferProcessStarted.class)); - - var assetId = "api-asset-1"; - var url = server.url("/mock/api"); - server.start(); - - var authCodeHeaderName = "test-authkey"; - var authCode = "test-authcode"; - Map dataAddress = Map.of( - "name", "transfer-test", - "baseUrl", url.toString(), - "type", "HttpData", - "contentType", "application/json", - "authKey", authCodeHeaderName, - "authCode", authCode - ); - - PLATO.createAsset(assetId, Map.of(), dataAddress); - - PLATO.storeBusinessPartner(SOKRATES.getBpn(), "test-group1", "test-group2"); - var accessPolicy = PLATO.createPolicyDefinition(PolicyHelperFunctions.bpnGroupPolicy(Operator.IS_NONE_OF, "forbidden-policy")); - var contractPolicy = PLATO.createPolicyDefinition(PolicyHelperFunctions.bpnGroupPolicy(Operator.IS_ALL_OF, "test-group1", "test-group2")); - PLATO.createContractDefinition(assetId, "def-1", accessPolicy, contractPolicy); - - - expectedEvents.forEach(event -> server.enqueue(new MockResponse())); - - var callbacks = Json.createArrayBuilder() - .add(EdrNegotiationHelperFunctions.createCallback(url.toString(), true, Set.of("contract.negotiation", "transfer.process"))) - .build(); - - var contractNegotiationId = SOKRATES.edrs().negotiateEdr(PLATO, assetId, callbacks); - - var events = expectedEvents.stream() - .map(receivedEvent -> waitForEvent(server)) - .collect(Collectors.toList()); - - - await().pollInterval(ASYNC_POLL_INTERVAL) - .atMost(ASYNC_TIMEOUT) - .untilAsserted(() -> { - var edrCaches = SOKRATES.edrs().getEdrEntriesByAssetId(assetId); - assertThat(edrCaches).hasSize(1); - }); - - assertThat(expectedEvents).usingRecursiveFieldByFieldElementComparator().containsAll(events); - - var edrCaches = SOKRATES.edrs().getEdrEntriesByAssetId(assetId); - - assertThat(edrCaches).hasSize(1); - - assertThat(SOKRATES.edrs().getEdrEntriesByContractNegotiationId(contractNegotiationId)).hasSize(1); - - assertThat(edrCaches).hasSize(1); - - var transferProcessId = edrCaches.get(0).asJsonObject().getString("transferProcessId"); - var cnId = edrCaches.get(0).asJsonObject().getString("contractNegotiationId"); - var agreementId = edrCaches.get(0).asJsonObject().getString("agreementId"); - - assertThat(cnId).isEqualTo(contractNegotiationId); - assertThat(SOKRATES.edrs().getEdrEntriesByAgreementId(agreementId)).hasSize(1); - - - var edr = SOKRATES.edrs().getEdr(transferProcessId); - - assertThat(edr.getJsonString("type").getString()).isEqualTo("https://w3id.org/idsa/v4.1/HTTP"); - assertThat(edr.getJsonString("endpoint").getString()).isNotNull(); - assertThat(edr.getJsonString("endpointType").getString()).isEqualTo(edr.getJsonString("type").getString()); - assertThat(edr.getJsonString("authorization").getString()).isNotNull(); - - } - - @AfterEach - void teardown() throws IOException { - server.shutdown(); - } - -} diff --git a/edc-tests/edc-controlplane/edr-api-tests/src/test/java/org/eclipse/tractusx/edc/tests/edrv2/NegotiateEdrInMemoryTest.java b/edc-tests/edc-controlplane/edr-api-tests/src/test/java/org/eclipse/tractusx/edc/tests/edrv2/NegotiateEdrInMemoryTest.java deleted file mode 100644 index dd25e45e1..000000000 --- a/edc-tests/edc-controlplane/edr-api-tests/src/test/java/org/eclipse/tractusx/edc/tests/edrv2/NegotiateEdrInMemoryTest.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -package org.eclipse.tractusx.edc.tests.edrv2; - - -import org.eclipse.edc.junit.annotations.EndToEndTest; -import org.eclipse.tractusx.edc.tests.runtimes.ParticipantRuntime; -import org.junit.jupiter.api.extension.RegisterExtension; - -@EndToEndTest -public class NegotiateEdrInMemoryTest extends AbstractNegotiateEdrTest { - - @RegisterExtension - protected static final ParticipantRuntime SOKRATES_RUNTIME = new ParticipantRuntime( - ":edc-tests:runtime:runtime-memory", - SOKRATES.getName(), - SOKRATES.getBpn(), - SOKRATES.getConfiguration() - ); - - @RegisterExtension - protected static final ParticipantRuntime PLATO_RUNTIME = new ParticipantRuntime( - ":edc-tests:runtime:runtime-memory", - PLATO.getName(), - PLATO.getBpn(), - PLATO.getConfiguration() - ); - -} diff --git a/edc-tests/edc-controlplane/edr-api-tests/src/test/java/org/eclipse/tractusx/edc/tests/edrv2/NegotiateEdrTest.java b/edc-tests/edc-controlplane/edr-api-tests/src/test/java/org/eclipse/tractusx/edc/tests/edrv2/NegotiateEdrTest.java new file mode 100644 index 000000000..fa91ed005 --- /dev/null +++ b/edc-tests/edc-controlplane/edr-api-tests/src/test/java/org/eclipse/tractusx/edc/tests/edrv2/NegotiateEdrTest.java @@ -0,0 +1,204 @@ +/******************************************************************************** + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +package org.eclipse.tractusx.edc.tests.edrv2; + +import jakarta.json.Json; +import okhttp3.mockwebserver.MockResponse; +import okhttp3.mockwebserver.MockWebServer; +import org.eclipse.edc.connector.controlplane.contract.spi.event.contractnegotiation.ContractNegotiationAgreed; +import org.eclipse.edc.connector.controlplane.contract.spi.event.contractnegotiation.ContractNegotiationFinalized; +import org.eclipse.edc.connector.controlplane.contract.spi.event.contractnegotiation.ContractNegotiationInitiated; +import org.eclipse.edc.connector.controlplane.contract.spi.event.contractnegotiation.ContractNegotiationRequested; +import org.eclipse.edc.connector.controlplane.contract.spi.event.contractnegotiation.ContractNegotiationVerified; +import org.eclipse.edc.connector.controlplane.transfer.spi.event.TransferProcessInitiated; +import org.eclipse.edc.connector.controlplane.transfer.spi.event.TransferProcessProvisioned; +import org.eclipse.edc.connector.controlplane.transfer.spi.event.TransferProcessRequested; +import org.eclipse.edc.connector.controlplane.transfer.spi.event.TransferProcessStarted; +import org.eclipse.edc.junit.annotations.EndToEndTest; +import org.eclipse.edc.junit.annotations.PostgresqlIntegrationTest; +import org.eclipse.edc.policy.model.Operator; +import org.eclipse.tractusx.edc.tests.helpers.EdrNegotiationHelperFunctions; +import org.eclipse.tractusx.edc.tests.helpers.PolicyHelperFunctions; +import org.eclipse.tractusx.edc.tests.participant.TransferParticipant; +import org.eclipse.tractusx.edc.tests.runtimes.ParticipantRuntime; +import org.eclipse.tractusx.edc.tests.runtimes.PgParticipantRuntime; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import java.io.IOException; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.awaitility.Awaitility.await; +import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.PLATO_BPN; +import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.PLATO_NAME; +import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.SOKRATES_BPN; +import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.SOKRATES_NAME; +import static org.eclipse.tractusx.edc.tests.helpers.EdrNegotiationHelperFunctions.createEvent; +import static org.eclipse.tractusx.edc.tests.helpers.Functions.waitForEvent; +import static org.eclipse.tractusx.edc.tests.participant.TractusxParticipantBase.ASYNC_POLL_INTERVAL; +import static org.eclipse.tractusx.edc.tests.participant.TractusxParticipantBase.ASYNC_TIMEOUT; +import static org.eclipse.tractusx.edc.tests.runtimes.Runtimes.memoryRuntime; +import static org.eclipse.tractusx.edc.tests.runtimes.Runtimes.pgRuntime; + +public class NegotiateEdrTest { + + protected static final TransferParticipant SOKRATES = TransferParticipant.Builder.newInstance() + .name(SOKRATES_NAME) + .id(SOKRATES_BPN) + .build(); + + protected static final TransferParticipant PLATO = TransferParticipant.Builder.newInstance() + .name(PLATO_NAME) + .id(PLATO_BPN) + .build(); + + + abstract static class Tests { + + MockWebServer server; + + @BeforeEach + void setup() { + server = new MockWebServer(); + } + + @Test + @DisplayName("Verify that the callbacks are invoked when negotiating an EDR") + void negotiateEdr_shouldInvokeCallbacks() throws IOException { + + var expectedEvents = List.of( + createEvent(ContractNegotiationInitiated.class), + createEvent(ContractNegotiationRequested.class), + createEvent(ContractNegotiationAgreed.class), + createEvent(ContractNegotiationFinalized.class), + createEvent(ContractNegotiationVerified.class), + createEvent(TransferProcessInitiated.class), + createEvent(TransferProcessProvisioned.class), + createEvent(TransferProcessRequested.class), + createEvent(TransferProcessStarted.class)); + + var assetId = "api-asset-1"; + var url = server.url("/mock/api"); + server.start(); + + var authCodeHeaderName = "test-authkey"; + var authCode = "test-authcode"; + Map dataAddress = Map.of( + "name", "transfer-test", + "baseUrl", url.toString(), + "type", "HttpData", + "contentType", "application/json", + "authKey", authCodeHeaderName, + "authCode", authCode + ); + + PLATO.createAsset(assetId, Map.of(), dataAddress); + + PLATO.storeBusinessPartner(SOKRATES.getBpn(), "test-group1", "test-group2"); + var accessPolicy = PLATO.createPolicyDefinition(PolicyHelperFunctions.bpnGroupPolicy(Operator.IS_NONE_OF, "forbidden-policy")); + var contractPolicy = PLATO.createPolicyDefinition(PolicyHelperFunctions.bpnGroupPolicy(Operator.IS_ALL_OF, "test-group1", "test-group2")); + PLATO.createContractDefinition(assetId, "def-1", accessPolicy, contractPolicy); + + + expectedEvents.forEach(event -> server.enqueue(new MockResponse())); + + var callbacks = Json.createArrayBuilder() + .add(EdrNegotiationHelperFunctions.createCallback(url.toString(), true, Set.of("contract.negotiation", "transfer.process"))) + .build(); + + var contractNegotiationId = SOKRATES.edrs().negotiateEdr(PLATO, assetId, callbacks); + + var events = expectedEvents.stream() + .map(receivedEvent -> waitForEvent(server)) + .collect(Collectors.toList()); + + + await().pollInterval(ASYNC_POLL_INTERVAL) + .atMost(ASYNC_TIMEOUT) + .untilAsserted(() -> { + var edrCaches = SOKRATES.edrs().getEdrEntriesByAssetId(assetId); + assertThat(edrCaches).hasSize(1); + }); + + assertThat(expectedEvents).usingRecursiveFieldByFieldElementComparator().containsAll(events); + + var edrCaches = SOKRATES.edrs().getEdrEntriesByAssetId(assetId); + + assertThat(edrCaches).hasSize(1); + + assertThat(SOKRATES.edrs().getEdrEntriesByContractNegotiationId(contractNegotiationId)).hasSize(1); + + assertThat(edrCaches).hasSize(1); + + var transferProcessId = edrCaches.get(0).asJsonObject().getString("transferProcessId"); + var cnId = edrCaches.get(0).asJsonObject().getString("contractNegotiationId"); + var agreementId = edrCaches.get(0).asJsonObject().getString("agreementId"); + + assertThat(cnId).isEqualTo(contractNegotiationId); + assertThat(SOKRATES.edrs().getEdrEntriesByAgreementId(agreementId)).hasSize(1); + + + var edr = SOKRATES.edrs().getEdr(transferProcessId); + + assertThat(edr.getJsonString("type").getString()).isEqualTo("https://w3id.org/idsa/v4.1/HTTP"); + assertThat(edr.getJsonString("endpoint").getString()).isNotNull(); + assertThat(edr.getJsonString("endpointType").getString()).isEqualTo(edr.getJsonString("type").getString()); + assertThat(edr.getJsonString("authorization").getString()).isNotNull(); + + } + + @AfterEach + void teardown() throws IOException { + server.shutdown(); + } + } + + @Nested + @EndToEndTest + class InMemory extends Tests { + + @RegisterExtension + protected static final ParticipantRuntime SOKRATES_RUNTIME = memoryRuntime(SOKRATES.getName(), SOKRATES.getBpn(), SOKRATES.getConfiguration()); + + @RegisterExtension + protected static final ParticipantRuntime PLATO_RUNTIME = memoryRuntime(PLATO.getName(), PLATO.getBpn(), PLATO.getConfiguration()); + + } + + @Nested + @PostgresqlIntegrationTest + class Postgres extends Tests { + + @RegisterExtension + protected static final PgParticipantRuntime SOKRATES_RUNTIME = pgRuntime(SOKRATES.getName(), SOKRATES.getBpn(), SOKRATES.getConfiguration()); + + @RegisterExtension + protected static final PgParticipantRuntime PLATO_RUNTIME = pgRuntime(PLATO.getName(), PLATO.getBpn(), PLATO.getConfiguration()); + + } +} diff --git a/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/helpers/EdrNegotiationHelperFunctions.java b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/helpers/EdrNegotiationHelperFunctions.java index 76a927708..425331fd9 100644 --- a/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/helpers/EdrNegotiationHelperFunctions.java +++ b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/helpers/EdrNegotiationHelperFunctions.java @@ -23,11 +23,11 @@ import jakarta.json.JsonArray; import jakarta.json.JsonArrayBuilder; import jakarta.json.JsonObject; +import org.eclipse.edc.connector.controlplane.contract.spi.types.negotiation.ContractRequest; import org.eclipse.edc.jsonld.TitaniumJsonLd; import org.eclipse.edc.jsonld.spi.JsonLd; import org.eclipse.edc.spi.event.Event; import org.eclipse.edc.spi.monitor.ConsoleMonitor; -import org.eclipse.tractusx.edc.api.edr.v2.dto.NegotiateEdrRequestDto; import java.util.Set; @@ -40,7 +40,7 @@ public class EdrNegotiationHelperFunctions { public static JsonObject createEdrNegotiationRequest(String connectorAddress, String providerId, String offerId, String assetId, JsonObject policy, JsonArray callbacks) { return Json.createObjectBuilder() - .add(TYPE, NegotiateEdrRequestDto.EDR_REQUEST_DTO_TYPE) + .add(TYPE, ContractRequest.CONTRACT_REQUEST_TYPE) .add(EDC_NAMESPACE + "counterPartyId", providerId) .add(EDC_NAMESPACE + "counterPartyAddress", connectorAddress) .add(EDC_NAMESPACE + "protocol", "dataspace-protocol-http") diff --git a/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/runtimes/PgParticipantRuntime.java b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/runtimes/PgParticipantRuntime.java index 9d720b30f..b3bfe98f4 100644 --- a/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/runtimes/PgParticipantRuntime.java +++ b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/runtimes/PgParticipantRuntime.java @@ -81,7 +81,7 @@ public Map postgresqlConfiguration(String name) { var jdbcUrl = jdbcUrl(name); return new HashMap<>() { { - Stream.of("asset", "contractdefinition", "contractnegotiation", "policy", "transferprocess", "edr", "bpn", "policy-monitor") + Stream.of("asset", "contractdefinition", "contractnegotiation", "policy", "transferprocess", "bpn", "policy-monitor") .forEach(context -> { var group = "edc.datasource." + context; put(group + ".name", context); diff --git a/spi/edr-spi/src/main/java/org/eclipse/tractusx/edc/edr/spi/types/NegotiateEdrRequest.java b/spi/edr-spi/src/main/java/org/eclipse/tractusx/edc/edr/spi/types/NegotiateEdrRequest.java deleted file mode 100644 index efd5299a5..000000000 --- a/spi/edr-spi/src/main/java/org/eclipse/tractusx/edc/edr/spi/types/NegotiateEdrRequest.java +++ /dev/null @@ -1,107 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://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. - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -package org.eclipse.tractusx.edc.edr.spi.types; - -import org.eclipse.edc.connector.controlplane.contract.spi.types.offer.ContractOffer; -import org.eclipse.edc.spi.types.domain.callback.CallbackAddress; - -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; - -public class NegotiateEdrRequest { - - private String connectorAddress; - private String protocol = "ids-multipart"; - private String connectorId; - private ContractOffer offer; - - private List callbackAddresses = new ArrayList<>(); - - private NegotiateEdrRequest() { - - } - - public String getConnectorAddress() { - return connectorAddress; - } - - public String getProtocol() { - return protocol; - } - - public String getConnectorId() { - return connectorId; - } - - - public List getCallbackAddresses() { - return callbackAddresses; - } - - public ContractOffer getOffer() { - return offer; - } - - - public static final class Builder { - private final NegotiateEdrRequest entity; - - private Builder() { - entity = new NegotiateEdrRequest(); - } - - public static Builder newInstance() { - return new Builder(); - } - - public Builder connectorAddress(String connectorAddress) { - entity.connectorAddress = connectorAddress; - return this; - } - - public Builder protocol(String protocol) { - entity.protocol = protocol; - return this; - } - - public Builder connectorId(String connectorId) { - entity.connectorId = connectorId; - return this; - } - - public Builder offer(ContractOffer offer) { - entity.offer = offer; - return this; - } - - public Builder callbackAddresses(List callbackAddresses) { - entity.callbackAddresses = callbackAddresses; - return this; - } - - public NegotiateEdrRequest build() { - Objects.requireNonNull(entity.protocol, "protocol should not be null"); - Objects.requireNonNull(entity.connectorAddress, "connector address should not be null"); - Objects.requireNonNull(entity.offer, "offer should not be null"); - return entity; - } - } -} From 857eaed37d134b95a653bafb06bb62e5a4f1e610 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 2 Apr 2024 07:37:20 +0200 Subject: [PATCH 084/100] chore(deps): bump aws from 2.25.16 to 2.25.21 (#1183) Bumps `aws` from 2.25.16 to 2.25.21. Updates `software.amazon.awssdk:s3` from 2.25.16 to 2.25.21 Updates `software.amazon.awssdk:s3-transfer-manager` from 2.25.16 to 2.25.21 --- updated-dependencies: - dependency-name: software.amazon.awssdk:s3 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:s3-transfer-manager dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 5dd19b8c2..7166df634 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -6,7 +6,7 @@ edc = "0.6.1-SNAPSHOT" apache-sshd = "2.12.1" assertj = "3.25.3" awaitility = "4.2.0" -aws = "2.25.16" +aws = "2.25.21" azure-identity = "1.11.4" bouncyCastle-jdk18on = "1.77" flyway = "10.10.0" From 64bac13087f427ff808ec99e6bdbc38913c0ccdd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 2 Apr 2024 07:37:23 +0200 Subject: [PATCH 085/100] chore(deps): bump org.postgresql:postgresql from 42.7.2 to 42.7.3 (#1182) Bumps [org.postgresql:postgresql](https://github.com/pgjdbc/pgjdbc) from 42.7.2 to 42.7.3. - [Release notes](https://github.com/pgjdbc/pgjdbc/releases) - [Changelog](https://github.com/pgjdbc/pgjdbc/blob/master/CHANGELOG.md) - [Commits](https://github.com/pgjdbc/pgjdbc/compare/REL42.7.2...REL42.7.3) --- updated-dependencies: - dependency-name: org.postgresql:postgresql dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 7166df634..207cad9f6 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -18,7 +18,7 @@ mockwebserver = "5.0.0-alpha.12" nimbus = "9.37.3" netty-mockserver = "5.15.0" okhttp = "4.12.0" -postgres = "42.7.2" +postgres = "42.7.3" restAssured = "5.4.0" rsApi = "3.1.0" slf4j = "2.0.12" From 6feb4617b770787c160c74c3b3dc67eb017b79ad Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 2 Apr 2024 07:37:31 +0200 Subject: [PATCH 086/100] chore(deps): bump aquasecurity/trivy-action from 0.18.0 to 0.19.0 (#1181) Bumps [aquasecurity/trivy-action](https://github.com/aquasecurity/trivy-action) from 0.18.0 to 0.19.0. - [Release notes](https://github.com/aquasecurity/trivy-action/releases) - [Commits](https://github.com/aquasecurity/trivy-action/compare/0.18.0...0.19.0) --- updated-dependencies: - dependency-name: aquasecurity/trivy-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/trivy.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/trivy.yml b/.github/workflows/trivy.yml index 414b0c681..0db9c033a 100644 --- a/.github/workflows/trivy.yml +++ b/.github/workflows/trivy.yml @@ -58,7 +58,7 @@ jobs: steps: - uses: actions/checkout@v4 - name: Run Trivy vulnerability scanner in repo mode - uses: aquasecurity/trivy-action@0.18.0 + uses: aquasecurity/trivy-action@0.19.0 with: scan-type: "config" # ignore-unfixed: true @@ -102,7 +102,7 @@ jobs: ## the next two steps will only execute if the image exists check was successful - name: Run Trivy vulnerability scanner if: success() && steps.imageCheck.outcome != 'failure' - uses: aquasecurity/trivy-action@0.18.0 + uses: aquasecurity/trivy-action@0.19.0 with: image-ref: "tractusx/${{ matrix.image }}:sha-${{ needs.git-sha7.outputs.value }}" format: "sarif" From 8371e8e90e1feb6a46f58e4ccfd2c89bca967519 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 2 Apr 2024 07:37:38 +0200 Subject: [PATCH 087/100] chore(deps): bump eclipse-temurin (#1180) Bumps eclipse-temurin from 21.0.2_13-jre-alpine to 22_36-jre-alpine. --- updated-dependencies: - dependency-name: eclipse-temurin dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .../src/main/docker/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/edc-controlplane/edc-controlplane-postgresql-hashicorp-vault/src/main/docker/Dockerfile b/edc-controlplane/edc-controlplane-postgresql-hashicorp-vault/src/main/docker/Dockerfile index 9a5000861..c66d04b48 100644 --- a/edc-controlplane/edc-controlplane-postgresql-hashicorp-vault/src/main/docker/Dockerfile +++ b/edc-controlplane/edc-controlplane-postgresql-hashicorp-vault/src/main/docker/Dockerfile @@ -20,7 +20,7 @@ ################################################################################# -FROM eclipse-temurin:21.0.2_13-jre-alpine +FROM eclipse-temurin:22_36-jre-alpine ARG JAR ARG OTEL_JAR ARG ADDITIONAL_FILES From 60ee1710beadaf7ac6ffc44a24223a930bd083f7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 2 Apr 2024 07:37:44 +0200 Subject: [PATCH 088/100] chore(deps): bump eclipse-temurin (#1179) Bumps eclipse-temurin from 21.0.2_13-jre-alpine to 22_36-jre-alpine. --- updated-dependencies: - dependency-name: eclipse-temurin dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .../edc-dataplane-azure-vault/src/main/docker/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/edc-dataplane/edc-dataplane-azure-vault/src/main/docker/Dockerfile b/edc-dataplane/edc-dataplane-azure-vault/src/main/docker/Dockerfile index ca47ef4a6..e106fe2a3 100644 --- a/edc-dataplane/edc-dataplane-azure-vault/src/main/docker/Dockerfile +++ b/edc-dataplane/edc-dataplane-azure-vault/src/main/docker/Dockerfile @@ -19,7 +19,7 @@ # SPDX-License-Identifier: Apache-2.0 ################################################################################# -FROM eclipse-temurin:21.0.2_13-jre-alpine +FROM eclipse-temurin:22_36-jre-alpine ARG JAR ARG OTEL_JAR ARG ADDITIONAL_FILES From 6e91b865b7d9ef9aa87e2270122fe5a6f544088b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 2 Apr 2024 07:37:48 +0200 Subject: [PATCH 089/100] chore(deps): bump eclipse-temurin (#1178) Bumps eclipse-temurin from 21.0.2_13-jre-alpine to 22_36-jre-alpine. --- updated-dependencies: - dependency-name: eclipse-temurin dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .../src/main/docker/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/edc-controlplane/edc-controlplane-postgresql-azure-vault/src/main/docker/Dockerfile b/edc-controlplane/edc-controlplane-postgresql-azure-vault/src/main/docker/Dockerfile index 472d1ec68..1bbb81d21 100644 --- a/edc-controlplane/edc-controlplane-postgresql-azure-vault/src/main/docker/Dockerfile +++ b/edc-controlplane/edc-controlplane-postgresql-azure-vault/src/main/docker/Dockerfile @@ -19,7 +19,7 @@ # SPDX-License-Identifier: Apache-2.0 ################################################################################# -FROM eclipse-temurin:21.0.2_13-jre-alpine +FROM eclipse-temurin:22_36-jre-alpine ARG JAR ARG OTEL_JAR ARG ADDITIONAL_FILES From 040252cd7160c3148aa0bbe3282d07f762c40668 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 2 Apr 2024 07:37:53 +0200 Subject: [PATCH 090/100] chore(deps): bump eclipse-temurin (#1177) Bumps eclipse-temurin from 21.0.2_13-jre-alpine to 22_36-jre-alpine. --- updated-dependencies: - dependency-name: eclipse-temurin dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .../edc-dataplane-hashicorp-vault/src/main/docker/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/edc-dataplane/edc-dataplane-hashicorp-vault/src/main/docker/Dockerfile b/edc-dataplane/edc-dataplane-hashicorp-vault/src/main/docker/Dockerfile index 2d0e41b11..6540e9606 100644 --- a/edc-dataplane/edc-dataplane-hashicorp-vault/src/main/docker/Dockerfile +++ b/edc-dataplane/edc-dataplane-hashicorp-vault/src/main/docker/Dockerfile @@ -20,7 +20,7 @@ ################################################################################# -FROM eclipse-temurin:21.0.2_13-jre-alpine +FROM eclipse-temurin:22_36-jre-alpine ARG JAR ARG OTEL_JAR ARG ADDITIONAL_FILES From 3f78a4a854a4e402d417e42d01ee23dc983d2a7d Mon Sep 17 00:00:00 2001 From: Paul Latzelsperger <43503240+paullatzelsperger@users.noreply.github.com> Date: Tue, 2 Apr 2024 19:39:00 +0200 Subject: [PATCH 091/100] chore: update Helm charts (#1185) * update chart "tractusx-connector" * reinstate old config values, needed for upgradeability test * update chart tractusx-connector-azure-vault * update chart tractusx-connector-memory * helm docs * fix inmem chart, remove test preparation * removed values_file from deployemtn test * reenable config values -> upgradeability test --- .../actions/run-deployment-test/action.yml | 9 -- .github/workflows/deployment-test.yaml | 4 - .github/workflows/upgradeability-test.yaml | 3 - DEPENDENCIES | 81 +++++++------ .../tractusx-connector-azure-vault/Chart.yaml | 2 +- .../tractusx-connector-azure-vault/README.md | 21 +++- .../templates/deployment-controlplane.yaml | 70 ++++++----- .../templates/deployment-dataplane.yaml | 109 ++++++++++++------ .../values.yaml | 55 ++++++++- charts/tractusx-connector-memory/README.md | 13 ++- .../templates/deployment-runtime.yaml | 65 ++++++++--- charts/tractusx-connector-memory/values.yaml | 34 +++++- charts/tractusx-connector/Chart.yaml | 4 +- charts/tractusx-connector/README.md | 23 ++-- .../templates/deployment-controlplane.yaml | 54 ++++----- .../templates/deployment-dataplane.yaml | 100 ++++++++++------ charts/tractusx-connector/values.yaml | 55 +++++---- .../src/main/resources/document/dspace.jsonld | 62 ++++++++++ .../dim/DimSecureServiceExtensionTest.java | 10 +- .../tractusx-connector-azure-vault-test.yaml | 23 +++- .../helm/tractusx-connector-memory-test.yaml | 26 +++-- .../helm/tractusx-connector-test.yaml | 50 ++++++-- .../src/main/resources/prepare-test.sh | 37 ------ gradle/libs.versions.toml | 2 - .../multitenancy/MultiTenantRuntime.java | 3 +- 25 files changed, 606 insertions(+), 309 deletions(-) create mode 100644 core/json-ld-core/src/main/resources/document/dspace.jsonld delete mode 100755 edc-tests/deployment/src/main/resources/prepare-test.sh diff --git a/.github/actions/run-deployment-test/action.yml b/.github/actions/run-deployment-test/action.yml index aebe8c38a..0564771c3 100644 --- a/.github/actions/run-deployment-test/action.yml +++ b/.github/actions/run-deployment-test/action.yml @@ -40,10 +40,6 @@ inputs: required: true description: "The directory that contains the docker file, e.g. edc-controlplane/edc-runtime-memory" - values_file: - required: true - description: "A yaml file that contains the values for the test installation. will be modified!" - runs: using: "composite" steps: @@ -76,11 +72,6 @@ runs: ################################################### # Install the test infrastructure ################################################### - - name: "Generate test credentials" - shell: bash - run: |- - sh -c "edc-tests/deployment/src/main/resources/prepare-test.sh \ - ${{ inputs.values_file }}" - name: Install Runtime shell: bash diff --git a/.github/workflows/deployment-test.yaml b/.github/workflows/deployment-test.yaml index e5208e7fa..1ab1187e1 100644 --- a/.github/workflows/deployment-test.yaml +++ b/.github/workflows/deployment-test.yaml @@ -63,11 +63,9 @@ jobs: with: imagename: edc-runtime-memory rootDir: edc-controlplane/edc-runtime-memory - values_file: edc-tests/deployment/src/main/resources/helm/tractusx-connector-memory-test.yaml helm_command: |- helm install tx-inmem charts/tractusx-connector-memory \ -f edc-tests/deployment/src/main/resources/helm/tractusx-connector-memory-test.yaml \ - --set vault.secrets="client-secret:$(cat client.secret)" \ --wait-for-jobs --timeout=120s --dependency-update # wait for the pod to become ready @@ -87,7 +85,6 @@ jobs: with: imagename: "edc-controlplane-postgresql-hashicorp-vault edc-dataplane-hashicorp-vault" rootDir: "." - values_file: edc-tests/deployment/src/main/resources/helm/tractusx-connector-test.yaml helm_command: |- helm install tx-prod charts/tractusx-connector \ -f edc-tests/deployment/src/main/resources/helm/tractusx-connector-test.yaml \ @@ -121,7 +118,6 @@ jobs: with: imagename: "edc-controlplane-postgresql-azure-vault edc-dataplane-azure-vault" rootDir: "." - values_file: edc-tests/deployment/src/main/resources/helm/tractusx-connector-azure-vault-test.yaml helm_command: |- az keyvault secret set --vault-name ${{ secrets.AZURE_VAULT_NAME }} --name aes-keys --value "$(cat aes.key)" > /dev/null az keyvault secret set --vault-name ${{ secrets.AZURE_VAULT_NAME }} --name client-secret --value "$(cat client.secret)" > /dev/null diff --git a/.github/workflows/upgradeability-test.yaml b/.github/workflows/upgradeability-test.yaml index df486e3fd..a7f3749a4 100644 --- a/.github/workflows/upgradeability-test.yaml +++ b/.github/workflows/upgradeability-test.yaml @@ -74,9 +74,6 @@ jobs: - name: "Install latest release" run: | - sh -c "edc-tests/deployment/src/main/resources/prepare-test.sh \ - edc-tests/deployment/src/main/resources/helm/tractusx-connector-test.yaml" - helm upgrade --install tx-prod tractusx/tractusx-connector \ -f edc-tests/deployment/src/main/resources/helm/tractusx-connector-test.yaml \ --set "controlplane.image.tag=$RELEASE" \ diff --git a/DEPENDENCIES b/DEPENDENCIES index d55dd2faf..7b011161f 100644 --- a/DEPENDENCIES +++ b/DEPENDENCIES @@ -26,7 +26,6 @@ maven/mavencentral/com.fasterxml.jackson.core/jackson-annotations/2.14.1, Apache maven/mavencentral/com.fasterxml.jackson.core/jackson-annotations/2.15.1, Apache-2.0, approved, #7947 maven/mavencentral/com.fasterxml.jackson.core/jackson-annotations/2.15.2, Apache-2.0, approved, #7947 maven/mavencentral/com.fasterxml.jackson.core/jackson-annotations/2.15.3, Apache-2.0, approved, #7947 -maven/mavencentral/com.fasterxml.jackson.core/jackson-annotations/2.16.2, Apache-2.0, approved, #11606 maven/mavencentral/com.fasterxml.jackson.core/jackson-annotations/2.17.0, Apache-2.0, approved, #13672 maven/mavencentral/com.fasterxml.jackson.core/jackson-core/2.13.5, Apache-2.0, approved, #2133 maven/mavencentral/com.fasterxml.jackson.core/jackson-core/2.14.1, Apache-2.0 AND MIT, approved, #4303 @@ -41,7 +40,6 @@ maven/mavencentral/com.fasterxml.jackson.core/jackson-databind/2.14.2, Apache-2. maven/mavencentral/com.fasterxml.jackson.core/jackson-databind/2.15.1, Apache-2.0, approved, #7934 maven/mavencentral/com.fasterxml.jackson.core/jackson-databind/2.15.2, Apache-2.0, approved, #7934 maven/mavencentral/com.fasterxml.jackson.core/jackson-databind/2.15.3, Apache-2.0, approved, #7934 -maven/mavencentral/com.fasterxml.jackson.core/jackson-databind/2.16.2, Apache-2.0, approved, #11605 maven/mavencentral/com.fasterxml.jackson.core/jackson-databind/2.17.0, Apache-2.0, approved, #13671 maven/mavencentral/com.fasterxml.jackson.dataformat/jackson-dataformat-toml/2.15.2, Apache-2.0, approved, #9160 maven/mavencentral/com.fasterxml.jackson.dataformat/jackson-dataformat-toml/2.17.0, Apache-2.0, approved, #14192 @@ -51,7 +49,6 @@ maven/mavencentral/com.fasterxml.jackson.dataformat/jackson-dataformat-yaml/2.14 maven/mavencentral/com.fasterxml.jackson.dataformat/jackson-dataformat-yaml/2.15.1, Apache-2.0, approved, #8802 maven/mavencentral/com.fasterxml.jackson.dataformat/jackson-dataformat-yaml/2.15.2, Apache-2.0, approved, #8802 maven/mavencentral/com.fasterxml.jackson.dataformat/jackson-dataformat-yaml/2.17.0, Apache-2.0, approved, #13669 -maven/mavencentral/com.fasterxml.jackson.datatype/jackson-datatype-jakarta-jsonp/2.16.2, Apache-2.0, approved, #11854 maven/mavencentral/com.fasterxml.jackson.datatype/jackson-datatype-jakarta-jsonp/2.17.0, Apache-2.0, approved, #14161 maven/mavencentral/com.fasterxml.jackson.datatype/jackson-datatype-jsr310/2.13.5, Apache-2.0, approved, clearlydefined maven/mavencentral/com.fasterxml.jackson.datatype/jackson-datatype-jsr310/2.14.0, Apache-2.0, approved, #4699 @@ -152,39 +149,39 @@ maven/mavencentral/io.micrometer/micrometer-core/1.12.4, Apache-2.0 AND (Apache- maven/mavencentral/io.micrometer/micrometer-observation/1.12.4, Apache-2.0, approved, #11680 maven/mavencentral/io.netty/netty-buffer/4.1.100.Final, Apache-2.0, approved, CQ21842 maven/mavencentral/io.netty/netty-buffer/4.1.101.Final, Apache-2.0, approved, CQ21842 -maven/mavencentral/io.netty/netty-buffer/4.1.107.Final, Apache-2.0, approved, CQ21842 +maven/mavencentral/io.netty/netty-buffer/4.1.108.Final, Apache-2.0, approved, CQ21842 maven/mavencentral/io.netty/netty-buffer/4.1.86.Final, Apache-2.0, approved, CQ21842 maven/mavencentral/io.netty/netty-codec-dns/4.1.101.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 maven/mavencentral/io.netty/netty-codec-http/4.1.100.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 maven/mavencentral/io.netty/netty-codec-http/4.1.101.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 -maven/mavencentral/io.netty/netty-codec-http/4.1.107.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 +maven/mavencentral/io.netty/netty-codec-http/4.1.108.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 maven/mavencentral/io.netty/netty-codec-http/4.1.86.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 maven/mavencentral/io.netty/netty-codec-http2/4.1.100.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 maven/mavencentral/io.netty/netty-codec-http2/4.1.101.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 -maven/mavencentral/io.netty/netty-codec-http2/4.1.107.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 +maven/mavencentral/io.netty/netty-codec-http2/4.1.108.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 maven/mavencentral/io.netty/netty-codec-http2/4.1.86.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 maven/mavencentral/io.netty/netty-codec-socks/4.1.101.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 maven/mavencentral/io.netty/netty-codec-socks/4.1.86.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 maven/mavencentral/io.netty/netty-codec/4.1.100.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 maven/mavencentral/io.netty/netty-codec/4.1.101.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 -maven/mavencentral/io.netty/netty-codec/4.1.107.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 +maven/mavencentral/io.netty/netty-codec/4.1.108.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 maven/mavencentral/io.netty/netty-codec/4.1.86.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 maven/mavencentral/io.netty/netty-common/4.1.100.Final, Apache-2.0 AND MIT AND CC0-1.0, approved, CQ21843 maven/mavencentral/io.netty/netty-common/4.1.101.Final, Apache-2.0 AND MIT AND CC0-1.0, approved, CQ21843 -maven/mavencentral/io.netty/netty-common/4.1.107.Final, Apache-2.0 AND MIT AND CC0-1.0, approved, CQ21843 +maven/mavencentral/io.netty/netty-common/4.1.108.Final, Apache-2.0 AND MIT AND CC0-1.0, approved, CQ21843 maven/mavencentral/io.netty/netty-common/4.1.86.Final, Apache-2.0 AND MIT AND CC0-1.0, approved, CQ21843 maven/mavencentral/io.netty/netty-handler-proxy/4.1.101.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 maven/mavencentral/io.netty/netty-handler-proxy/4.1.86.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 maven/mavencentral/io.netty/netty-handler/4.1.100.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 maven/mavencentral/io.netty/netty-handler/4.1.101.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 -maven/mavencentral/io.netty/netty-handler/4.1.107.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 +maven/mavencentral/io.netty/netty-handler/4.1.108.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 maven/mavencentral/io.netty/netty-handler/4.1.86.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 maven/mavencentral/io.netty/netty-resolver-dns-classes-macos/4.1.101.Final, Apache-2.0, approved, #6367 maven/mavencentral/io.netty/netty-resolver-dns-native-macos/4.1.101.Final, Apache-2.0, approved, #7004 maven/mavencentral/io.netty/netty-resolver-dns/4.1.101.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 maven/mavencentral/io.netty/netty-resolver/4.1.100.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 maven/mavencentral/io.netty/netty-resolver/4.1.101.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 -maven/mavencentral/io.netty/netty-resolver/4.1.107.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 +maven/mavencentral/io.netty/netty-resolver/4.1.108.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 maven/mavencentral/io.netty/netty-resolver/4.1.86.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 maven/mavencentral/io.netty/netty-tcnative-boringssl-static/2.0.56.Final, Apache-2.0 OR LicenseRef-Public-Domain OR BSD-2-Clause OR MIT, approved, CQ15280 maven/mavencentral/io.netty/netty-tcnative-boringssl-static/2.0.62.Final, Apache-2.0 OR LicenseRef-Public-Domain OR BSD-2-Clause OR MIT, approved, CQ15280 @@ -192,16 +189,16 @@ maven/mavencentral/io.netty/netty-tcnative-classes/2.0.56.Final, Apache-2.0, app maven/mavencentral/io.netty/netty-tcnative-classes/2.0.62.Final, Apache-2.0, approved, clearlydefined maven/mavencentral/io.netty/netty-transport-classes-epoll/4.1.100.Final, Apache-2.0, approved, #6366 maven/mavencentral/io.netty/netty-transport-classes-epoll/4.1.101.Final, Apache-2.0, approved, #6366 -maven/mavencentral/io.netty/netty-transport-classes-epoll/4.1.107.Final, Apache-2.0, approved, #6366 +maven/mavencentral/io.netty/netty-transport-classes-epoll/4.1.108.Final, Apache-2.0, approved, #6366 maven/mavencentral/io.netty/netty-transport-classes-kqueue/4.1.101.Final, Apache-2.0, approved, #4107 maven/mavencentral/io.netty/netty-transport-native-epoll/4.1.101.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 maven/mavencentral/io.netty/netty-transport-native-kqueue/4.1.101.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 maven/mavencentral/io.netty/netty-transport-native-unix-common/4.1.101.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 -maven/mavencentral/io.netty/netty-transport-native-unix-common/4.1.107.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 +maven/mavencentral/io.netty/netty-transport-native-unix-common/4.1.108.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 maven/mavencentral/io.netty/netty-transport-native-unix-common/4.1.86.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 maven/mavencentral/io.netty/netty-transport/4.1.100.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 maven/mavencentral/io.netty/netty-transport/4.1.101.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 -maven/mavencentral/io.netty/netty-transport/4.1.107.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 +maven/mavencentral/io.netty/netty-transport/4.1.108.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 maven/mavencentral/io.netty/netty-transport/4.1.86.Final, Apache-2.0 AND BSD-3-Clause AND MIT, approved, CQ20926 maven/mavencentral/io.opentelemetry.instrumentation/opentelemetry-instrumentation-annotations/1.32.0, Apache-2.0, approved, #11684 maven/mavencentral/io.opentelemetry/opentelemetry-api/1.32.0, Apache-2.0, approved, #11682 @@ -561,10 +558,10 @@ maven/mavencentral/org.javassist/javassist/3.29.2-GA, Apache-2.0 AND LGPL-2.1-or maven/mavencentral/org.jetbrains.kotlin/kotlin-stdlib-common/1.9.10, Apache-2.0, approved, #14186 maven/mavencentral/org.jetbrains.kotlin/kotlin-stdlib-jdk7/1.8.0, Apache-2.0, approved, #8807 maven/mavencentral/org.jetbrains.kotlin/kotlin-stdlib-jdk7/1.8.21, Apache-2.0, approved, #8807 -maven/mavencentral/org.jetbrains.kotlin/kotlin-stdlib-jdk7/1.9.10, None, restricted, #14193 +maven/mavencentral/org.jetbrains.kotlin/kotlin-stdlib-jdk7/1.9.10, Apache-2.0, approved, #14193 maven/mavencentral/org.jetbrains.kotlin/kotlin-stdlib-jdk8/1.8.0, Apache-2.0, approved, #8919 maven/mavencentral/org.jetbrains.kotlin/kotlin-stdlib-jdk8/1.8.21, Apache-2.0, approved, #8919 -maven/mavencentral/org.jetbrains.kotlin/kotlin-stdlib-jdk8/1.9.10, None, restricted, #14191 +maven/mavencentral/org.jetbrains.kotlin/kotlin-stdlib-jdk8/1.9.10, Apache-2.0, approved, #14191 maven/mavencentral/org.jetbrains.kotlin/kotlin-stdlib/1.8.21, Apache-2.0, approved, #8865 maven/mavencentral/org.jetbrains.kotlin/kotlin-stdlib/1.9.10, Apache-2.0, approved, #11827 maven/mavencentral/org.jetbrains.kotlin/kotlin-stdlib/1.9.21, Apache-2.0, approved, #11827 @@ -631,58 +628,58 @@ maven/mavencentral/org.yaml/snakeyaml/1.33, Apache-2.0, approved, clearlydefined maven/mavencentral/org.yaml/snakeyaml/2.0, Apache-2.0 AND (Apache-2.0 OR BSD-3-Clause OR EPL-1.0 OR GPL-2.0-or-later OR LGPL-2.1-or-later), approved, #7275 maven/mavencentral/org.yaml/snakeyaml/2.2, Apache-2.0 AND (Apache-2.0 OR BSD-3-Clause OR EPL-1.0 OR GPL-2.0-or-later OR LGPL-2.1-or-later), approved, #10232 maven/mavencentral/software.amazon.awssdk/annotations/2.24.10, Apache-2.0, approved, #13251 -maven/mavencentral/software.amazon.awssdk/annotations/2.25.16, Apache-2.0, approved, #13691 +maven/mavencentral/software.amazon.awssdk/annotations/2.25.21, Apache-2.0, approved, #13691 maven/mavencentral/software.amazon.awssdk/apache-client/2.24.10, Apache-2.0, approved, #13257 -maven/mavencentral/software.amazon.awssdk/apache-client/2.25.16, Apache-2.0, approved, #13687 +maven/mavencentral/software.amazon.awssdk/apache-client/2.25.21, Apache-2.0, approved, #13687 maven/mavencentral/software.amazon.awssdk/arns/2.24.10, Apache-2.0, approved, #13243 -maven/mavencentral/software.amazon.awssdk/arns/2.25.16, Apache-2.0, approved, #13695 +maven/mavencentral/software.amazon.awssdk/arns/2.25.21, Apache-2.0, approved, #13695 maven/mavencentral/software.amazon.awssdk/auth/2.24.10, Apache-2.0, approved, #13256 -maven/mavencentral/software.amazon.awssdk/auth/2.25.16, Apache-2.0, approved, #13692 +maven/mavencentral/software.amazon.awssdk/auth/2.25.21, Apache-2.0, approved, #13692 maven/mavencentral/software.amazon.awssdk/aws-core/2.24.10, Apache-2.0, approved, #13240 -maven/mavencentral/software.amazon.awssdk/aws-core/2.25.16, Apache-2.0, approved, #13702 +maven/mavencentral/software.amazon.awssdk/aws-core/2.25.21, Apache-2.0, approved, #13702 maven/mavencentral/software.amazon.awssdk/aws-query-protocol/2.24.10, Apache-2.0, approved, #13262 -maven/mavencentral/software.amazon.awssdk/aws-query-protocol/2.25.16, Apache-2.0, approved, #13701 +maven/mavencentral/software.amazon.awssdk/aws-query-protocol/2.25.21, Apache-2.0, approved, #13701 maven/mavencentral/software.amazon.awssdk/aws-xml-protocol/2.24.10, Apache-2.0, approved, #13247 -maven/mavencentral/software.amazon.awssdk/aws-xml-protocol/2.25.16, Apache-2.0, approved, #13684 +maven/mavencentral/software.amazon.awssdk/aws-xml-protocol/2.25.21, Apache-2.0, approved, #13684 maven/mavencentral/software.amazon.awssdk/checksums-spi/2.24.10, Apache-2.0, approved, #13245 -maven/mavencentral/software.amazon.awssdk/checksums-spi/2.25.16, Apache-2.0, approved, #13686 +maven/mavencentral/software.amazon.awssdk/checksums-spi/2.25.21, Apache-2.0, approved, #13686 maven/mavencentral/software.amazon.awssdk/checksums/2.24.10, Apache-2.0, approved, #13242 -maven/mavencentral/software.amazon.awssdk/checksums/2.25.16, Apache-2.0, approved, #13677 +maven/mavencentral/software.amazon.awssdk/checksums/2.25.21, Apache-2.0, approved, #13677 maven/mavencentral/software.amazon.awssdk/crt-core/2.24.10, Apache-2.0, approved, #13252 -maven/mavencentral/software.amazon.awssdk/crt-core/2.25.16, Apache-2.0, approved, #13705 +maven/mavencentral/software.amazon.awssdk/crt-core/2.25.21, Apache-2.0, approved, #13705 maven/mavencentral/software.amazon.awssdk/endpoints-spi/2.24.10, Apache-2.0, approved, #13246 -maven/mavencentral/software.amazon.awssdk/endpoints-spi/2.25.16, Apache-2.0, approved, #13681 +maven/mavencentral/software.amazon.awssdk/endpoints-spi/2.25.21, Apache-2.0, approved, #13681 maven/mavencentral/software.amazon.awssdk/http-auth-aws/2.24.10, Apache-2.0, approved, #13253 -maven/mavencentral/software.amazon.awssdk/http-auth-aws/2.25.16, Apache-2.0, approved, #13696 +maven/mavencentral/software.amazon.awssdk/http-auth-aws/2.25.21, Apache-2.0, approved, #13696 maven/mavencentral/software.amazon.awssdk/http-auth-spi/2.24.10, Apache-2.0, approved, #13264 -maven/mavencentral/software.amazon.awssdk/http-auth-spi/2.25.16, Apache-2.0, approved, #13704 +maven/mavencentral/software.amazon.awssdk/http-auth-spi/2.25.21, Apache-2.0, approved, #13704 maven/mavencentral/software.amazon.awssdk/http-auth/2.24.10, Apache-2.0, approved, #13248 -maven/mavencentral/software.amazon.awssdk/http-auth/2.25.16, Apache-2.0, approved, #13682 +maven/mavencentral/software.amazon.awssdk/http-auth/2.25.21, Apache-2.0, approved, #13682 maven/mavencentral/software.amazon.awssdk/http-client-spi/2.24.10, Apache-2.0, approved, #13259 -maven/mavencentral/software.amazon.awssdk/http-client-spi/2.25.16, Apache-2.0, approved, #13706 +maven/mavencentral/software.amazon.awssdk/http-client-spi/2.25.21, Apache-2.0, approved, #13706 maven/mavencentral/software.amazon.awssdk/iam/2.24.10, Apache-2.0, approved, #13444 maven/mavencentral/software.amazon.awssdk/identity-spi/2.24.10, Apache-2.0, approved, #13244 -maven/mavencentral/software.amazon.awssdk/identity-spi/2.25.16, Apache-2.0, approved, #13685 +maven/mavencentral/software.amazon.awssdk/identity-spi/2.25.21, Apache-2.0, approved, #13685 maven/mavencentral/software.amazon.awssdk/json-utils/2.24.10, Apache-2.0, approved, #13261 -maven/mavencentral/software.amazon.awssdk/json-utils/2.25.16, Apache-2.0, approved, #13698 +maven/mavencentral/software.amazon.awssdk/json-utils/2.25.21, Apache-2.0, approved, #13698 maven/mavencentral/software.amazon.awssdk/metrics-spi/2.24.10, Apache-2.0, approved, #13239 -maven/mavencentral/software.amazon.awssdk/metrics-spi/2.25.16, Apache-2.0, approved, #13680 +maven/mavencentral/software.amazon.awssdk/metrics-spi/2.25.21, Apache-2.0, approved, #13680 maven/mavencentral/software.amazon.awssdk/netty-nio-client/2.24.10, Apache-2.0, approved, #13260 -maven/mavencentral/software.amazon.awssdk/netty-nio-client/2.25.16, Apache-2.0, approved, #13693 +maven/mavencentral/software.amazon.awssdk/netty-nio-client/2.25.21, Apache-2.0, approved, #13693 maven/mavencentral/software.amazon.awssdk/profiles/2.24.10, Apache-2.0, approved, #13258 -maven/mavencentral/software.amazon.awssdk/profiles/2.25.16, Apache-2.0, approved, #13697 +maven/mavencentral/software.amazon.awssdk/profiles/2.25.21, Apache-2.0, approved, #13697 maven/mavencentral/software.amazon.awssdk/protocol-core/2.24.10, Apache-2.0, approved, #13241 -maven/mavencentral/software.amazon.awssdk/protocol-core/2.25.16, Apache-2.0, approved, #13679 +maven/mavencentral/software.amazon.awssdk/protocol-core/2.25.21, Apache-2.0, approved, #13679 maven/mavencentral/software.amazon.awssdk/regions/2.24.10, Apache-2.0, approved, #13255 -maven/mavencentral/software.amazon.awssdk/regions/2.25.16, Apache-2.0, approved, #13694 -maven/mavencentral/software.amazon.awssdk/s3-transfer-manager/2.25.16, Apache-2.0, approved, #13699 +maven/mavencentral/software.amazon.awssdk/regions/2.25.21, Apache-2.0, approved, #13694 +maven/mavencentral/software.amazon.awssdk/s3-transfer-manager/2.25.21, Apache-2.0, approved, #13699 maven/mavencentral/software.amazon.awssdk/s3/2.24.10, Apache-2.0, approved, #13254 -maven/mavencentral/software.amazon.awssdk/s3/2.25.16, Apache-2.0, approved, #13688 +maven/mavencentral/software.amazon.awssdk/s3/2.25.21, Apache-2.0, approved, #13688 maven/mavencentral/software.amazon.awssdk/sdk-core/2.24.10, Apache-2.0, approved, #13265 -maven/mavencentral/software.amazon.awssdk/sdk-core/2.25.16, Apache-2.0, approved, #13700 +maven/mavencentral/software.amazon.awssdk/sdk-core/2.25.21, Apache-2.0, approved, #13700 maven/mavencentral/software.amazon.awssdk/sts/2.24.10, Apache-2.0, approved, #13442 maven/mavencentral/software.amazon.awssdk/third-party-jackson-core/2.24.10, Apache-2.0, approved, #13249 -maven/mavencentral/software.amazon.awssdk/third-party-jackson-core/2.25.16, Apache-2.0, approved, #13703 +maven/mavencentral/software.amazon.awssdk/third-party-jackson-core/2.25.21, Apache-2.0, approved, #13703 maven/mavencentral/software.amazon.awssdk/utils/2.24.10, Apache-2.0, approved, #13250 -maven/mavencentral/software.amazon.awssdk/utils/2.25.16, Apache-2.0, approved, #13689 +maven/mavencentral/software.amazon.awssdk/utils/2.25.21, Apache-2.0, approved, #13689 maven/mavencentral/software.amazon.eventstream/eventstream/1.0.1, Apache-2.0, approved, clearlydefined diff --git a/charts/tractusx-connector-azure-vault/Chart.yaml b/charts/tractusx-connector-azure-vault/Chart.yaml index 74b7e2e7a..1a3d03ca6 100644 --- a/charts/tractusx-connector-azure-vault/Chart.yaml +++ b/charts/tractusx-connector-azure-vault/Chart.yaml @@ -54,6 +54,6 @@ dependencies: # PostgreSQL - name: postgresql alias: postgresql - version: 12.11.2 + version: "15.2.1" repository: https://charts.bitnami.com/bitnami condition: install.postgresql diff --git a/charts/tractusx-connector-azure-vault/README.md b/charts/tractusx-connector-azure-vault/README.md index e056ee64f..6720cd354 100644 --- a/charts/tractusx-connector-azure-vault/README.md +++ b/charts/tractusx-connector-azure-vault/README.md @@ -61,24 +61,24 @@ helm install my-release tractusx-edc/tractusx-connector-azure-vault --version 0. | Repository | Name | Version | |------------|------|---------| -| https://charts.bitnami.com/bitnami | postgresql(postgresql) | 12.11.2 | +| https://charts.bitnami.com/bitnami | postgresql(postgresql) | 15.2.1 | ## Values | Key | Type | Default | Description | |-----|------|---------|-------------| -| backendService.httpProxyTokenReceiverUrl | string | `"https://example.com"` | Specifies a backend service which will receive the EDR | | controlplane.affinity | object | `{}` | | | controlplane.autoscaling.enabled | bool | `false` | Enables [horizontal pod autoscaling](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/) | | controlplane.autoscaling.maxReplicas | int | `100` | Maximum replicas if resource consumption exceeds resource threshholds | | controlplane.autoscaling.minReplicas | int | `1` | Minimal replicas if resource consumption falls below resource threshholds | | controlplane.autoscaling.targetCPUUtilizationPercentage | int | `80` | targetAverageUtilization of cpu provided to a pod | | controlplane.autoscaling.targetMemoryUtilizationPercentage | int | `80` | targetAverageUtilization of memory provided to a pod | +| controlplane.bdrs.cache_validity_seconds | int | `600` | | +| controlplane.bdrs.server.url | string | `nil` | | | controlplane.businessPartnerValidation.log.agreementValidation | bool | `true` | | | controlplane.debug.enabled | bool | `false` | | | controlplane.debug.port | int | `1044` | | | controlplane.debug.suspendOnStart | bool | `false` | | -| controlplane.edr.transferProxyTokenValidity | string | `"2592000"` | | | controlplane.endpoints | object | `{"control":{"path":"/control","port":8083},"default":{"path":"/api","port":8080},"management":{"authKey":"password","path":"/management","port":8081},"metrics":{"path":"/metrics","port":9090},"protocol":{"path":"/api/v1/dsp","port":8084}}` | endpoints of the control plane | | controlplane.endpoints.control | object | `{"path":"/control","port":8083}` | control api, used for internal control calls. can be added to the internal ingress, but should probably not | | controlplane.endpoints.control.path | string | `"/control"` | path for incoming api calls | @@ -243,14 +243,29 @@ helm install my-release tractusx-edc/tractusx-connector-azure-vault --version 0. | dataplane.securityContext.runAsUser | int | `10001` | The container's process will run with the specified uid | | dataplane.service.port | int | `80` | | | dataplane.service.type | string | `"ClusterIP"` | [Service type](https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services-service-types) to expose the running application on a set of Pods as a network service. | +| dataplane.token.refresh.expiry_seconds | int | `300` | | +| dataplane.token.refresh.expiry_tolerance_seconds | int | `10` | | +| dataplane.token.refresh.refresh_endpoint | string | `nil` | | +| dataplane.token.signer.privatekey_alias | string | `nil` | | +| dataplane.token.verifier.publickey_alias | string | `nil` | | | dataplane.tolerations | list | `[]` | | | dataplane.url.public | string | `""` | Explicitly declared url for reaching the public api (e.g. if ingresses not used) | | dataplane.volumeMounts | string | `nil` | declare where to mount [volumes](https://kubernetes.io/docs/concepts/storage/volumes/) into the container | | dataplane.volumes | string | `nil` | [volume](https://kubernetes.io/docs/concepts/storage/volumes/) directories | | fullnameOverride | string | `""` | | +| iatp.id | string | `"did:web:changeme"` | | +| iatp.sts.dim.url | string | `nil` | | +| iatp.sts.oauth.client.id | string | `nil` | | +| iatp.sts.oauth.client.secret_alias | string | `nil` | | +| iatp.sts.oauth.token_url | string | `nil` | | | imagePullSecrets | list | `[]` | Existing image pull secret to use to [obtain the container image from private registries](https://kubernetes.io/docs/concepts/containers/images/#using-a-private-registry) | | install.postgresql | bool | `true` | | | nameOverride | string | `""` | | +| networkPolicy.controlplane | object | `{"from":[{"namespaceSelector":{}}]}` | Configuration of the controlplane component | +| networkPolicy.controlplane.from | list | `[{"namespaceSelector":{}}]` | Specify from rule network policy for cp (defaults to all namespaces) | +| networkPolicy.dataplane | object | `{"from":[{"namespaceSelector":{}}]}` | Configuration of the dataplane component | +| networkPolicy.dataplane.from | list | `[{"namespaceSelector":{}}]` | Specify from rule network policy for dp (defaults to all namespaces) | +| networkPolicy.enabled | bool | `false` | If `true` network policy will be created to restrict access to control- and dataplane | | participant.id | string | `"BPNLCHANGEME"` | BPN Number | | postgresql.auth.database | string | `"edc"` | | | postgresql.auth.password | string | `"password"` | | diff --git a/charts/tractusx-connector-azure-vault/templates/deployment-controlplane.yaml b/charts/tractusx-connector-azure-vault/templates/deployment-controlplane.yaml index f5e187f1c..98cf57bf6 100644 --- a/charts/tractusx-connector-azure-vault/templates/deployment-controlplane.yaml +++ b/charts/tractusx-connector-azure-vault/templates/deployment-controlplane.yaml @@ -146,6 +146,8 @@ spec: ######################## - name: EDC_PARTICIPANT_ID value: {{ .Values.participant.id | required ".Values.participant.id is required" | quote }} + - name: "EDC_IAM_ISSUER_ID" + value: {{ .Values.iatp.id | required ".Values.iatp.id is required" | quote}} ####### # API # @@ -236,16 +238,6 @@ spec: - name: "EDC_DATASOURCE_TRANSFERPROCESS_URL" value: {{ tpl .Values.postgresql.jdbcUrl . | quote }} - # see extension https://github.com/eclipse-tractusx/tractusx-edc/tree/main/edc-extensions/edr-cache-sql - - name: "EDC_DATASOURCE_EDR_NAME" - value: "edr" - - name: "EDC_DATASOURCE_EDR_USER" - value: {{ .Values.postgresql.auth.username | required ".Values.postgresql.auth.username is required" | quote }} - - name: "EDC_DATASOURCE_EDR_PASSWORD" - value: {{ .Values.postgresql.auth.password | required ".Values.postgresql.auth.password is required" | quote }} - - name: "EDC_DATASOURCE_EDR_URL" - value: {{ tpl .Values.postgresql.jdbcUrl . | quote }} - # see extension https://github.com/eclipse-edc/Connector/tree/main/extensions/policy-monitor/store/sql/policy-monitor-store-sql - name: "EDC_DATASOURCE_POLICY-MONITOR_NAME" value: "policy-monitor" @@ -266,6 +258,32 @@ spec: - name: "EDC_DATASOURCE_BPN_URL" value: {{ tpl .Values.postgresql.jdbcUrl . | quote }} + + ############################# + ## IATP / STS / DIM CONFIG ## + ############################# + - name: "EDC_IAM_STS_OAUTH_TOKEN_URL" + value: {{ .Values.iatp.sts.oauth.token_url | required ".Values.iatp.oauth.token_url is required" | quote}} + - name: "EDC_IAM_STS_OAUTH_CLIENT_ID" + value: {{ .Values.iatp.sts.oauth.client.id | required ".Values.iatp.sts.oauth.client.id is required" | quote}} + - name: "EDC_IAM_STS_OAUTH_CLIENT_SECRET_ALIAS" + value: {{ .Values.iatp.sts.oauth.client.secret_alias | required ".Values.iatp.sts.oauth.client.secret_alias is required" | quote}} + - name: "EDC_IAM_STS_DIM_URL" + value: {{ .Values.iatp.sts.dim.url | required ".Values.iatp.sts.dim.url is required" | quote}} + + ################# + ## BDRS CLIENT ## + ################# + + {{- if .Values.controlplane.bdrs.server.url }} + - name: "TX_IAM_IATP_BDRS_SERVER_URL" + value: {{ .Values.controlplane.bdrs.server.url | required ".Values.controlplane.bdrs.server.url is required" | quote }} + {{- end }} + {{- if .Values.controlplane.bdrs.cache_validity_seconds }} + - name: "TX_IAM_IATP_BDRS_CACHE_VALIDITY" + value: {{ .Values.controlplane.bdrs.cache_validity_seconds | quote}} + {{- end}} + ################ ## DATA PLANE ## ################ @@ -281,53 +299,31 @@ spec: value: |- {{ printf "{ \"publicApiUrl\": \"%s\" }" (include "txdc.dataplane.url.public" . ) }} - # see extension https://github.com/eclipse-edc/Connector/tree/main/extensions/control-plane/data-plane-transfer - - name: "EDC_TRANSFER_PROXY_ENDPOINT" - value: {{ include "txdc.dataplane.url.public" . }} - {{- if .Values.vault.secretNames.transferProxyTokenSignerPrivateKey }} - - name: "EDC_TRANSFER_PROXY_TOKEN_SIGNER_PRIVATEKEY_ALIAS" - value: {{ .Values.vault.secretNames.transferProxyTokenSignerPrivateKey | quote }} - {{- end }} - {{- if .Values.vault.secretNames.transferProxyTokenSignerPublicKey }} - - name: "EDC_TRANSFER_PROXY_TOKEN_VERIFIER_PUBLICKEY_ALIAS" - value: {{ .Values.vault.secretNames.transferProxyTokenSignerPublicKey | quote }} - {{- end }} - - name: "EDC_TRANSFER_PROXY_TOKEN_VALIDITY_SECONDS" - value: {{ .Values.controlplane.edr.transferProxyTokenValidity | required ".Values.controlplane.edr.transferProxyTokenValidity is required" | quote }} - # see extension https://github.com/eclipse-edc/Connector/tree/main/extensions/control-plane/transfer/transfer-pull-http-dynamic-receiver - - name: "EDC_RECEIVER_HTTP_DYNAMIC_ENDPOINT" - value: {{ .Values.backendService.httpProxyTokenReceiverUrl | required ".Values.backendService.httpProxyTokenReceiverUrl is required" | quote }} ########### ## VAULT ## ########### - - name: "EDC_VAULT_CLIENTID" + - name: "AZURE_CLIENT_ID" value: {{ .Values.vault.azure.client | required ".Values.vault.azure.client is required" | quote }} - - name: "EDC_VAULT_TENANTID" + - name: "AZURE_TENANT_ID" value: {{ .Values.vault.azure.tenant | required ".Values.vault.azure.tenant is required" | quote }} - name: "EDC_VAULT_NAME" value: {{ .Values.vault.azure.name | required ".Values.vault.azure.name is required" | quote }} # only set the env var if config value not null {{- if .Values.vault.azure.secret }} - - name: "EDC_VAULT_CLIENTSECRET" + - name: "AZURE_CLIENT_SECRET" value: {{ .Values.vault.azure.secret | quote }} {{- end }} # only set the env var if config value not null {{- if .Values.vault.azure.certificate }} - - name: "EDC_VAULT_CERTIFICATE" + - name: "AZURE_CLIENT_CERTIFICATE_PATH" value: {{ .Values.vault.azure.certificate | quote }} {{- end }} - ########################### - ## AAS WRAPPER EXTENSION ## - ########################### - - name: "EDC_CP_ADAPTER_CACHE_CATALOG_EXPIRE_AFTER" - value: "0" - - name: "EDC_CP_ADAPTER_REUSE_CONTRACT_AGREEMENT" - value: "0" + ########################### ## BUSINESS PARTNER NUMBER VALIDATION EXTENSION ## diff --git a/charts/tractusx-connector-azure-vault/templates/deployment-dataplane.yaml b/charts/tractusx-connector-azure-vault/templates/deployment-dataplane.yaml index 48085d744..58984c928 100644 --- a/charts/tractusx-connector-azure-vault/templates/deployment-dataplane.yaml +++ b/charts/tractusx-connector-azure-vault/templates/deployment-dataplane.yaml @@ -1,24 +1,24 @@ ################################################################################# -# Copyright (c) 2023 ZF Friedrichshafen AG -# Copyright (c) 2023 Mercedes-Benz Tech Innovation GmbH -# Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) -# Copyright (c) 2021,2023 Contributors to the Eclipse Foundation -# -# See the NOTICE file(s) distributed with this work for additional -# information regarding copyright ownership. -# -# This program and the accompanying materials are made available under the -# terms of the Apache License, Version 2.0 which is available at -# https://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. -# -# SPDX-License-Identifier: Apache-2.0 -################################################################################# + # Copyright (c) 2023 ZF Friedrichshafen AG + # Copyright (c) 2023 Mercedes-Benz Tech Innovation GmbH + # Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + # Copyright (c) 2021,2023 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License, Version 2.0 which is available at + # https://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. + # + # SPDX-License-Identifier: Apache-2.0 + ################################################################################# --- @@ -145,6 +145,8 @@ spec: ######################## - name: EDC_PARTICIPANT_ID value: {{ .Values.participant.id | required ".Values.participant.id is required" | quote }} + - name: "EDC_IAM_ISSUER_ID" + value: {{ .Values.iatp.id | required ".Values.iatp.id is required" | quote}} ####### # API # @@ -182,41 +184,72 @@ spec: value: {{ .Values.dataplane.aws.accessKeyId | quote }} {{- end }} - ############### - ## EDR CACHE ## - ############### - - # see extension https://github.com/eclipse-tractusx/tractusx-edc/tree/main/edc-extensions/edr-cache-sql - - name: "EDC_DATASOURCE_EDR_NAME" - value: "edr" - - name: "EDC_DATASOURCE_EDR_USER" - value: {{ .Values.postgresql.auth.username | required ".Values.postgresql.auth.username is required" | quote }} - - name: "EDC_DATASOURCE_EDR_PASSWORD" - value: {{ .Values.postgresql.auth.password | required ".Values.postgresql.auth.password is required" | quote }} - - name: "EDC_DATASOURCE_EDR_URL" - value: {{ .Values.postgresql.jdbcUrl | required ".Values.postgresql.jdbcUrl is required" | quote }} - ########### ## VAULT ## ########### - - name: "EDC_VAULT_CLIENTID" + - name: "AZURE_CLIENT_ID" value: {{ .Values.vault.azure.client | quote }} - - name: "EDC_VAULT_TENANTID" + - name: "AZURE_TENANT_ID" value: {{ .Values.vault.azure.tenant | quote }} - name: "EDC_VAULT_NAME" value: {{ .Values.vault.azure.name | quote }} # only set the env var if config value not null {{- if .Values.vault.azure.secret }} - - name: "EDC_VAULT_CLIENTSECRET" + - name: "AZURE_CLIENT_SECRET" value: {{ .Values.vault.azure.secret | quote }} {{- end }} # only set the env var if config value not null {{- if .Values.vault.azure.certificate }} - - name: "EDC_VAULT_CERTIFICATE" + - name: "AZURE_CLIENT_CERTIFICATE_PATH" value: {{ .Values.vault.azure.certificate | quote }} {{- end }} + ############################# + ## IATP / STS / DIM CONFIG ## + ############################# + - name: "EDC_IAM_STS_OAUTH_TOKEN_URL" + value: {{ .Values.iatp.sts.oauth.token_url | required ".Values.iatp.oauth.token_url is required" | quote}} + - name: "EDC_IAM_STS_OAUTH_CLIENT_ID" + value: {{ .Values.iatp.sts.oauth.client.id | required ".Values.iatp.sts.oauth.client.id is required" | quote}} + - name: "EDC_IAM_STS_OAUTH_CLIENT_SECRET_ALIAS" + value: {{ .Values.iatp.sts.oauth.client.secret_alias | required ".Values.iatp.sts.oauth.client.secret_alias is required" | quote}} + - name: "EDC_IAM_STS_DIM_URL" + value: {{ .Values.iatp.sts.dim.url | required ".Values.iatp.sts.dim.url is required" | quote}} + + + ######################### + ## DATA PLANE PUBLIC API + ######################## + - name: "EDC_DATAPLANE_API_PUBLIC_BASEURL" + value: {{ include "txdc.dataplane.url.public" . }} + + + ################## + ## TOKEN REFRESH + ################## + {{- if .Values.dataplane.token.refresh.expiry_seconds }} + - name: "EDC_DATAPLANE_TOKEN_EXPIRY" + value: {{ .Values.dataplane.token.refresh.expiry_seconds | quote}} + {{- end}} + + {{- if .Values.dataplane.token.refresh.expiry_tolerance_seconds }} + - name: "EDC_DATAPLANE_TOKEN_EXPIRY_TOLERANCE" + value: {{ .Values.dataplane.token.refresh.expiry_tolerance_seconds | quote }} + {{- end}} + + {{- if .Values.dataplane.token.refresh.refresh_endpoint }} + - name: "EDC_DATAPLANE_TOKEN_REFRESH_ENDPOINT" + value: {{ .Values.dataplane.token.refresh.refresh_endpoint }} + {{- end}} + + - name: "EDC_TRANSFER_PROXY_TOKEN_SIGNER_PRIVATEKEY_ALIAS" + value: {{ .Values.dataplane.token.signer.privatekey_alias | required ".Values.dataplane.token.signer.privatekey_alias is required" | quote}} + + - name: "EDC_TRANSFER_PROXY_TOKEN_VERIFIER_PUBLICKEY_ALIAS" + value: {{ .Values.dataplane.token.verifier.publickey_alias | required ".Values.dataplane.token.verifier.publickey_alias" | quote }} + + ###################################### ## Additional environment variables ## ###################################### diff --git a/charts/tractusx-connector-azure-vault/values.yaml b/charts/tractusx-connector-azure-vault/values.yaml index 157fcb2b8..e0bbc34c9 100644 --- a/charts/tractusx-connector-azure-vault/values.yaml +++ b/charts/tractusx-connector-azure-vault/values.yaml @@ -40,6 +40,20 @@ participant: # -- BPN Number id: "BPNLCHANGEME" + +iatp: + # Decentralized IDentifier + id: "did:web:changeme" + sts: + dim: + url: + oauth: + token_url: + client: + id: + secret_alias: + + controlplane: image: # -- Which derivate of the control plane to use. when left empty the deployment will select the correct image automatically @@ -117,8 +131,13 @@ controlplane: businessPartnerValidation: log: agreementValidation: true - edr: - transferProxyTokenValidity: "2592000" + + bdrs: + # time that a cached BPN/DID resolution map is valid in seconds, default is 10 min + cache_validity_seconds: 600 + server: + # URL of the BPN/DID Resolution Service - required: + url: service: # -- [Service type](https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services-service-types) to expose the running application on a set of Pods as a network service. @@ -344,6 +363,20 @@ dataplane: metrics: port: 9090 path: /metrics + + token: + refresh: + expiry_seconds: 300 + expiry_tolerance_seconds: 10 + # optional URL that can be provided where clients go to refresh tokens. + refresh_endpoint: + signer: + # alias under which the private key is stored in the vault (JWK or PEM format) + privatekey_alias: + verifier: + # alias under which the public key is stored in the vault, that belongs to the private key ("privatekey_alias", JWK or PEM format) + publickey_alias: + aws: endpointOverride: "" accessKeyId: "" @@ -505,9 +538,20 @@ vault: transferProxyTokenSignerPublicKey: transferProxyTokenEncryptionAesKey: transfer-proxy-token-encryption-aes-key -backendService: - # -- Specifies a backend service which will receive the EDR - httpProxyTokenReceiverUrl: "https://example.com" +networkPolicy: + # -- If `true` network policy will be created to restrict access to control- and dataplane + enabled: false + # -- Configuration of the controlplane component + controlplane: + # -- Specify from rule network policy for cp (defaults to all namespaces) + from: + - namespaceSelector: {} + # -- Configuration of the dataplane component + dataplane: + # -- Specify from rule network policy for dp (defaults to all namespaces) + from: + - namespaceSelector: {} + serviceAccount: # Specifies whether a service account should be created create: true @@ -518,6 +562,7 @@ serviceAccount: name: "" # -- Existing image pull secret bound to the service account to use to [obtain the container image from private registries](https://kubernetes.io/docs/concepts/containers/images/#using-a-private-registry) imagePullSecrets: [] + # -- Configurations for Helm tests tests: # -- Configure the hook-delete-policy for Helm tests diff --git a/charts/tractusx-connector-memory/README.md b/charts/tractusx-connector-memory/README.md index 5fa0c2d74..76a3c8126 100644 --- a/charts/tractusx-connector-memory/README.md +++ b/charts/tractusx-connector-memory/README.md @@ -56,6 +56,11 @@ helm install my-release tractusx-edc/tractusx-connector-memory --version 0.6.0 \ | customCaCerts | object | `{}` | Add custom ca certificates to the truststore | | customLabels | object | `{}` | To add some custom labels | | fullnameOverride | string | `""` | | +| iatp.id | string | `"did:web:changeme"` | | +| iatp.sts.dim.url | string | `nil` | | +| iatp.sts.oauth.client.id | string | `nil` | | +| iatp.sts.oauth.client.secret_alias | string | `nil` | | +| iatp.sts.oauth.token_url | string | `nil` | | | imagePullSecrets | list | `[]` | Existing image pull secret to use to [obtain the container image from private registries](https://kubernetes.io/docs/concepts/containers/images/#using-a-private-registry) | | nameOverride | string | `""` | | | participant.id | string | `"BPNLCHANGEME"` | BPN Number | @@ -65,11 +70,12 @@ helm install my-release tractusx-edc/tractusx-connector-memory --version 0.6.0 \ | runtime.autoscaling.minReplicas | int | `1` | Minimal replicas if resource consumption falls below resource threshholds | | runtime.autoscaling.targetCPUUtilizationPercentage | int | `80` | targetAverageUtilization of cpu provided to a pod | | runtime.autoscaling.targetMemoryUtilizationPercentage | int | `80` | targetAverageUtilization of memory provided to a pod | +| runtime.bdrs.cache_validity_seconds | int | `600` | | +| runtime.bdrs.server.url | string | `nil` | | | runtime.businessPartnerValidation.log.agreementValidation | bool | `true` | | | runtime.debug.enabled | bool | `false` | | | runtime.debug.port | int | `1044` | | | runtime.debug.suspendOnStart | bool | `false` | | -| runtime.edr.transferProxyTokenValidity | string | `"2592000"` | | | runtime.endpoints | object | `{"control":{"path":"/control","port":8083},"default":{"path":"/api","port":8080},"management":{"authKey":"password","path":"/management","port":8081},"protocol":{"path":"/api/v1/dsp","port":8084},"proxy":{"path":"/proxy","port":8186},"public":{"path":"/api/public","port":8086}}` | endpoints of the control plane | | runtime.endpoints.control | object | `{"path":"/control","port":8083}` | control api, used for internal control calls. can be added to the internal ingress, but should probably not | | runtime.endpoints.control.path | string | `"/control"` | path for incoming api calls | @@ -147,6 +153,11 @@ helm install my-release tractusx-edc/tractusx-connector-memory --version 0.6.0 \ | runtime.securityContext.runAsUser | int | `10001` | The container's process will run with the specified uid | | runtime.service.annotations | object | `{}` | | | runtime.service.type | string | `"ClusterIP"` | [Service type](https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services-service-types) to expose the running application on a set of Pods as a network service. | +| runtime.token.refresh.expiry_seconds | int | `300` | | +| runtime.token.refresh.expiry_tolerance_seconds | int | `10` | | +| runtime.token.refresh.refresh_endpoint | string | `nil` | | +| runtime.token.signer.privatekey_alias | string | `nil` | | +| runtime.token.verifier.publickey_alias | string | `nil` | | | runtime.tolerations | list | `[]` | | | runtime.url.protocol | string | `""` | Explicitly declared url for reaching the dsp api (e.g. if ingresses not used) | | runtime.url.public | string | `""` | | diff --git a/charts/tractusx-connector-memory/templates/deployment-runtime.yaml b/charts/tractusx-connector-memory/templates/deployment-runtime.yaml index a9453bcec..a5d4c0e3f 100644 --- a/charts/tractusx-connector-memory/templates/deployment-runtime.yaml +++ b/charts/tractusx-connector-memory/templates/deployment-runtime.yaml @@ -146,6 +146,8 @@ spec: ######################## - name: EDC_PARTICIPANT_ID value: {{ .Values.participant.id | required ".Values.participant.id is required" | quote }} + - name: "EDC_IAM_ISSUER_ID" + value: {{ .Values.iatp.id | required ".Values.iatp.id is required" | quote}} ####### # API # @@ -197,6 +199,31 @@ spec: - name: "EDC_OAUTH_ENDPOINT_AUDIENCE" value: {{ printf "%s%s" (include "txdc.runtime.url.protocol" . ) .Values.runtime.endpoints.protocol.path | quote }} + ############################# + ## IATP / STS / DIM CONFIG ## + ############################# + - name: "EDC_IAM_STS_OAUTH_TOKEN_URL" + value: {{ .Values.iatp.sts.oauth.token_url | required ".Values.iatp.oauth.token_url is required" | quote}} + - name: "EDC_IAM_STS_OAUTH_CLIENT_ID" + value: {{ .Values.iatp.sts.oauth.client.id | required ".Values.iatp.sts.oauth.client.id is required" | quote}} + - name: "EDC_IAM_STS_OAUTH_CLIENT_SECRET_ALIAS" + value: {{ .Values.iatp.sts.oauth.client.secret_alias | required ".Values.iatp.sts.oauth.client.secret_alias is required" | quote}} + - name: "EDC_IAM_STS_DIM_URL" + value: {{ .Values.iatp.sts.dim.url | required ".Values.iatp.sts.dim.url is required" | quote}} + + ################# + ## BDRS CLIENT ## + ################# + + {{- if .Values.runtime.bdrs.server.url }} + - name: "TX_IAM_IATP_BDRS_SERVER_URL" + value: {{ .Values.runtime.bdrs.server.url | required ".Values.runtime.bdrs.server.url is required" | quote }} + {{- end }} + {{- if .Values.runtime.bdrs.cache_validity_seconds }} + - name: "TX_IAM_IATP_BDRS_CACHE_VALIDITY" + value: {{ .Values.runtime.bdrs.cache_validity_seconds | quote}} + {{- end}} + ################ ## DATA PLANE ## ################ @@ -212,23 +239,35 @@ spec: value: |- {{ printf "{ \"publicApiUrl\": \"%s\" }" (include "txdc.dataplane.url.public" . ) }} - # see extension https://github.com/eclipse-edc/Connector/tree/main/extensions/control-plane/data-plane-transfer - - name: "EDC_TRANSFER_PROXY_ENDPOINT" + + - name: "EDC_DATAPLANE_API_PUBLIC_BASEURL" value: {{ include "txdc.dataplane.url.public" . }} - {{- if .Values.vault.secretNames.transferProxyTokenSignerPrivateKey }} + + + ################## + ## TOKEN REFRESH + ################## + {{- if .Values.runtime.token.refresh.expiry_seconds }} + - name: "EDC_DATAPLANE_TOKEN_EXPIRY" + value: {{ .Values.runtime.token.refresh.expiry_seconds | quote}} + {{- end}} + + {{- if .Values.runtime.token.refresh.expiry_tolerance_seconds }} + - name: "EDC_DATAPLANE_TOKEN_EXPIRY_TOLERANCE" + value: {{ .Values.runtime.token.refresh.expiry_tolerance_seconds | quote }} + {{- end}} + + {{- if .Values.runtime.token.refresh.refresh_endpoint }} + - name: "EDC_DATAPLANE_TOKEN_REFRESH_ENDPOINT" + value: {{ .Values.runtime.token.refresh.refresh_endpoint }} + {{- end}} + - name: "EDC_TRANSFER_PROXY_TOKEN_SIGNER_PRIVATEKEY_ALIAS" - value: {{ .Values.vault.secretNames.transferProxyTokenSignerPrivateKey | quote }} - {{- end }} - {{- if .Values.vault.secretNames.transferProxyTokenSignerPublicKey }} + value: {{ .Values.runtime.token.signer.privatekey_alias | required ".Values.runtime.token.signer.privatekey_alias is required" | quote}} + - name: "EDC_TRANSFER_PROXY_TOKEN_VERIFIER_PUBLICKEY_ALIAS" - value: {{ .Values.vault.secretNames.transferProxyTokenSignerPublicKey | quote }} - {{- end }} - - name: "EDC_TRANSFER_PROXY_TOKEN_VALIDITY_SECONDS" - value: {{ .Values.runtime.edr.transferProxyTokenValidity | required ".Values.runtime.edr.transferProxyTokenValidity is required" | quote }} + value: {{ .Values.runtime.token.verifier.publickey_alias | required ".Values.runtime.token.verifier.publickey_alias" | quote }} - # see extension https://github.com/eclipse-edc/Connector/tree/main/extensions/control-plane/http-receiver - - name: "EDC_RECEIVER_HTTP_ENDPOINT" - value: {{ .Values.backendService.httpProxyTokenReceiverUrl | required ".Values.backendService.httpProxyTokenReceiverUrl is required" | quote }} ########### ## VAULT ## diff --git a/charts/tractusx-connector-memory/values.yaml b/charts/tractusx-connector-memory/values.yaml index 886610abb..3289edfcf 100644 --- a/charts/tractusx-connector-memory/values.yaml +++ b/charts/tractusx-connector-memory/values.yaml @@ -34,6 +34,18 @@ participant: # -- BPN Number id: "BPNLCHANGEME" +iatp: + # Decentralized IDentifier + id: "did:web:changeme" + sts: + dim: + url: + oauth: + token_url: + client: + id: + secret_alias: + # -- Add custom ca certificates to the truststore customCaCerts: {} @@ -109,11 +121,29 @@ runtime: proxy: port: 8186 path: /proxy + businessPartnerValidation: log: agreementValidation: true - edr: - transferProxyTokenValidity: "2592000" + token: + refresh: + expiry_seconds: 300 + expiry_tolerance_seconds: 10 + # optional URL that can be provided where clients go to refresh tokens. + refresh_endpoint: + signer: + # alias under which the private key is stored in the vault (JWK or PEM format) + privatekey_alias: + verifier: + # alias under which the public key is stored in the vault, that belongs to the private key ("privatekey_alias", JWK or PEM format) + publickey_alias: + + bdrs: + # time that a cached BPN/DID resolution map is valid in seconds, default is 10 min + cache_validity_seconds: 600 + server: + # URL of the BPN/DID Resolution Service - required: + url: service: # -- [Service type](https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services-service-types) to expose the running application on a set of Pods as a network service. diff --git a/charts/tractusx-connector/Chart.yaml b/charts/tractusx-connector/Chart.yaml index cce1ff152..b01a54b2e 100644 --- a/charts/tractusx-connector/Chart.yaml +++ b/charts/tractusx-connector/Chart.yaml @@ -54,12 +54,12 @@ dependencies: # HashiCorp Vault - name: vault alias: vault - version: 0.20.0 + version: "0.27.0" repository: https://helm.releases.hashicorp.com condition: install.vault # PostgreSQL - name: postgresql alias: postgresql - version: 12.11.2 + version: "15.2.1" repository: https://charts.bitnami.com/bitnami condition: install.postgresql diff --git a/charts/tractusx-connector/README.md b/charts/tractusx-connector/README.md index 922e1b816..a6db95db8 100644 --- a/charts/tractusx-connector/README.md +++ b/charts/tractusx-connector/README.md @@ -54,25 +54,25 @@ helm install my-release tractusx-edc/tractusx-connector --version 0.6.0 \ | Repository | Name | Version | |------------|------|---------| -| https://charts.bitnami.com/bitnami | postgresql(postgresql) | 12.11.2 | -| https://helm.releases.hashicorp.com | vault(vault) | 0.20.0 | +| https://charts.bitnami.com/bitnami | postgresql(postgresql) | 15.2.1 | +| https://helm.releases.hashicorp.com | vault(vault) | 0.27.0 | ## Values | Key | Type | Default | Description | |-----|------|---------|-------------| -| backendService.httpProxyTokenReceiverUrl | string | `"https://example.com"` | Specifies a backend service which will receive the EDR | | controlplane.affinity | object | `{}` | | | controlplane.autoscaling.enabled | bool | `false` | Enables [horizontal pod autoscaling](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/) | | controlplane.autoscaling.maxReplicas | int | `100` | Maximum replicas if resource consumption exceeds resource threshholds | | controlplane.autoscaling.minReplicas | int | `1` | Minimal replicas if resource consumption falls below resource threshholds | | controlplane.autoscaling.targetCPUUtilizationPercentage | int | `80` | targetAverageUtilization of cpu provided to a pod | | controlplane.autoscaling.targetMemoryUtilizationPercentage | int | `80` | targetAverageUtilization of memory provided to a pod | +| controlplane.bdrs.cache_validity_seconds | int | `600` | | +| controlplane.bdrs.server.url | string | `nil` | | | controlplane.businessPartnerValidation.log.agreementValidation | bool | `true` | | | controlplane.debug.enabled | bool | `false` | | | controlplane.debug.port | int | `1044` | | | controlplane.debug.suspendOnStart | bool | `false` | | -| controlplane.edr.transferProxyTokenValidity | string | `"2592000"` | | | controlplane.endpoints | object | `{"control":{"path":"/control","port":8083},"default":{"path":"/api","port":8080},"management":{"authKey":"password","path":"/management","port":8081},"metrics":{"path":"/metrics","port":9090},"protocol":{"path":"/api/v1/dsp","port":8084}}` | endpoints of the control plane | | controlplane.endpoints.control | object | `{"path":"/control","port":8083}` | control api, used for internal control calls. can be added to the internal ingress, but should probably not | | controlplane.endpoints.control.path | string | `"/control"` | path for incoming api calls | @@ -154,11 +154,6 @@ helm install my-release tractusx-edc/tractusx-connector --version 0.6.0 \ | controlplane.securityContext.runAsUser | int | `10001` | The container's process will run with the specified uid | | controlplane.service.annotations | object | `{}` | | | controlplane.service.type | string | `"ClusterIP"` | [Service type](https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services-service-types) to expose the running application on a set of Pods as a network service. | -| controlplane.ssi.miw.authorityId | string | `""` | The BPN of the issuer authority | -| controlplane.ssi.miw.url | string | `""` | MIW URL | -| controlplane.ssi.oauth.client.id | string | `""` | The client ID for KeyCloak | -| controlplane.ssi.oauth.client.secretAlias | string | `"client-secret"` | The alias under which the client secret is stored in the vault. | -| controlplane.ssi.oauth.tokenurl | string | `""` | The URL (of KeyCloak), where access tokens can be obtained | | controlplane.tolerations | list | `[]` | | | controlplane.url.protocol | string | `""` | Explicitly declared url for reaching the dsp api (e.g. if ingresses not used) | | controlplane.volumeMounts | string | `nil` | declare where to mount [volumes](https://kubernetes.io/docs/concepts/storage/volumes/) into the container | @@ -242,11 +237,21 @@ helm install my-release tractusx-edc/tractusx-connector --version 0.6.0 \ | dataplane.securityContext.runAsUser | int | `10001` | The container's process will run with the specified uid | | dataplane.service.port | int | `80` | | | dataplane.service.type | string | `"ClusterIP"` | [Service type](https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services-service-types) to expose the running application on a set of Pods as a network service. | +| dataplane.token.refresh.expiry_seconds | int | `300` | | +| dataplane.token.refresh.expiry_tolerance_seconds | int | `10` | | +| dataplane.token.refresh.refresh_endpoint | string | `nil` | | +| dataplane.token.signer.privatekey_alias | string | `nil` | | +| dataplane.token.verifier.publickey_alias | string | `nil` | | | dataplane.tolerations | list | `[]` | | | dataplane.url.public | string | `""` | Explicitly declared url for reaching the public api (e.g. if ingresses not used) | | dataplane.volumeMounts | string | `nil` | declare where to mount [volumes](https://kubernetes.io/docs/concepts/storage/volumes/) into the container | | dataplane.volumes | string | `nil` | [volume](https://kubernetes.io/docs/concepts/storage/volumes/) directories | | fullnameOverride | string | `""` | | +| iatp.id | string | `"did:web:changeme"` | | +| iatp.sts.dim.url | string | `nil` | | +| iatp.sts.oauth.client.id | string | `nil` | | +| iatp.sts.oauth.client.secret_alias | string | `nil` | | +| iatp.sts.oauth.token_url | string | `nil` | | | imagePullSecrets | list | `[]` | Existing image pull secret to use to [obtain the container image from private registries](https://kubernetes.io/docs/concepts/containers/images/#using-a-private-registry) | | install.postgresql | bool | `true` | | | install.vault | bool | `true` | | diff --git a/charts/tractusx-connector/templates/deployment-controlplane.yaml b/charts/tractusx-connector/templates/deployment-controlplane.yaml index 06c482763..4f3196d22 100644 --- a/charts/tractusx-connector/templates/deployment-controlplane.yaml +++ b/charts/tractusx-connector/templates/deployment-controlplane.yaml @@ -146,6 +146,8 @@ spec: ######################## - name: EDC_PARTICIPANT_ID value: {{ .Values.participant.id | required ".Values.participant.id is required" | quote }} + - name: "EDC_IAM_ISSUER_ID" + value: {{ .Values.iatp.id | required ".Values.iatp.id is required" | quote}} ####### # API # @@ -236,16 +238,6 @@ spec: - name: "EDC_DATASOURCE_TRANSFERPROCESS_URL" value: {{ tpl .Values.postgresql.jdbcUrl . | quote }} - # see extension https://github.com/eclipse-tractusx/tractusx-edc/tree/main/edc-extensions/edr-cache-sql - - name: "EDC_DATASOURCE_EDR_NAME" - value: "edr" - - name: "EDC_DATASOURCE_EDR_USER" - value: {{ .Values.postgresql.auth.username | required ".Values.postgresql.auth.username is required" | quote }} - - name: "EDC_DATASOURCE_EDR_PASSWORD" - value: {{ .Values.postgresql.auth.password | required ".Values.postgresql.auth.password is required" | quote }} - - name: "EDC_DATASOURCE_EDR_URL" - value: {{ tpl .Values.postgresql.jdbcUrl . | quote }} - # see extension https://github.com/eclipse-edc/Connector/tree/main/extensions/policy-monitor/store/sql/policy-monitor-store-sql - name: "EDC_DATASOURCE_POLICY-MONITOR_NAME" value: "policy-monitor" @@ -266,6 +258,32 @@ spec: - name: "EDC_DATASOURCE_BPN_URL" value: {{ tpl .Values.postgresql.jdbcUrl . | quote }} + + ############################# + ## IATP / STS / DIM CONFIG ## + ############################# + - name: "EDC_IAM_STS_OAUTH_TOKEN_URL" + value: {{ .Values.iatp.sts.oauth.token_url | required ".Values.iatp.oauth.token_url is required" | quote}} + - name: "EDC_IAM_STS_OAUTH_CLIENT_ID" + value: {{ .Values.iatp.sts.oauth.client.id | required ".Values.iatp.sts.oauth.client.id is required" | quote}} + - name: "EDC_IAM_STS_OAUTH_CLIENT_SECRET_ALIAS" + value: {{ .Values.iatp.sts.oauth.client.secret_alias | required ".Values.iatp.sts.oauth.client.secret_alias is required" | quote}} + - name: "EDC_IAM_STS_DIM_URL" + value: {{ .Values.iatp.sts.dim.url | required ".Values.iatp.sts.dim.url is required" | quote}} + + ################# + ## BDRS CLIENT ## + ################# + + {{- if .Values.controlplane.bdrs.server.url }} + - name: "TX_IAM_IATP_BDRS_SERVER_URL" + value: {{ .Values.controlplane.bdrs.server.url | required ".Values.controlplane.bdrs.server.url is required" | quote }} + {{- end }} + {{- if .Values.controlplane.bdrs.cache_validity_seconds }} + - name: "TX_IAM_IATP_BDRS_CACHE_VALIDITY" + value: {{ .Values.controlplane.bdrs.cache_validity_seconds | quote}} + {{- end}} + ################ ## DATA PLANE ## ################ @@ -281,24 +299,8 @@ spec: value: |- {{ printf "{ \"publicApiUrl\": \"%s\" }" (include "txdc.dataplane.url.public" . ) }} - # see extension https://github.com/eclipse-edc/Connector/tree/main/extensions/control-plane/data-plane-transfer - - name: "EDC_TRANSFER_PROXY_ENDPOINT" - value: {{ include "txdc.dataplane.url.public" . }} - {{- if .Values.vault.secretNames.transferProxyTokenSignerPrivateKey }} - - name: "EDC_TRANSFER_PROXY_TOKEN_SIGNER_PRIVATEKEY_ALIAS" - value: {{ .Values.vault.secretNames.transferProxyTokenSignerPrivateKey | quote }} - {{- end }} - {{- if .Values.vault.secretNames.transferProxyTokenSignerPublicKey }} - - name: "EDC_TRANSFER_PROXY_TOKEN_VERIFIER_PUBLICKEY_ALIAS" - value: {{ .Values.vault.secretNames.transferProxyTokenSignerPublicKey | quote }} - {{- end }} - - name: "EDC_TRANSFER_PROXY_TOKEN_VALIDITY_SECONDS" - value: {{ .Values.controlplane.edr.transferProxyTokenValidity | required ".Values.controlplane.edr.transferProxyTokenValidity is required" | quote }} - # see extension https://github.com/eclipse-edc/Connector/tree/main/extensions/control-plane/transfer/transfer-pull-http-dynamic-receiver - - name: "EDC_RECEIVER_HTTP_DYNAMIC_ENDPOINT" - value: {{ .Values.backendService.httpProxyTokenReceiverUrl | required ".Values.backendService.httpProxyTokenReceiverUrl is required" | quote }} ########### ## VAULT ## diff --git a/charts/tractusx-connector/templates/deployment-dataplane.yaml b/charts/tractusx-connector/templates/deployment-dataplane.yaml index 8a43fc37b..c02094659 100644 --- a/charts/tractusx-connector/templates/deployment-dataplane.yaml +++ b/charts/tractusx-connector/templates/deployment-dataplane.yaml @@ -1,24 +1,24 @@ ################################################################################# -# Copyright (c) 2023 ZF Friedrichshafen AG -# Copyright (c) 2023 Mercedes-Benz Tech Innovation GmbH -# Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) -# Copyright (c) 2021,2023 Contributors to the Eclipse Foundation -# -# See the NOTICE file(s) distributed with this work for additional -# information regarding copyright ownership. -# -# This program and the accompanying materials are made available under the -# terms of the Apache License, Version 2.0 which is available at -# https://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. -# -# SPDX-License-Identifier: Apache-2.0 -################################################################################# + # Copyright (c) 2023 ZF Friedrichshafen AG + # Copyright (c) 2023 Mercedes-Benz Tech Innovation GmbH + # Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + # Copyright (c) 2021,2023 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License, Version 2.0 which is available at + # https://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. + # + # SPDX-License-Identifier: Apache-2.0 + ################################################################################# --- @@ -145,6 +145,8 @@ spec: ######################## - name: EDC_PARTICIPANT_ID value: {{ .Values.participant.id | required ".Values.participant.id is required" | quote }} + - name: "EDC_IAM_ISSUER_ID" + value: {{ .Values.iatp.id | required ".Values.iatp.id is required" | quote}} ####### # API # @@ -182,20 +184,6 @@ spec: value: {{ .Values.dataplane.aws.accessKeyId | quote }} {{- end }} - ############### - ## EDR CACHE ## - ############### - - # see extension https://github.com/eclipse-tractusx/tractusx-edc/tree/main/edc-extensions/edr-cache-sql - - name: "EDC_DATASOURCE_EDR_NAME" - value: "edr" - - name: "EDC_DATASOURCE_EDR_USER" - value: {{ .Values.postgresql.auth.username | required ".Values.postgresql.auth.username is required" | quote }} - - name: "EDC_DATASOURCE_EDR_PASSWORD" - value: {{ .Values.postgresql.auth.password | required ".Values.postgresql.auth.password is required" | quote }} - - name: "EDC_DATASOURCE_EDR_URL" - value: {{ tpl .Values.postgresql.jdbcUrl . | quote }} - ########### ## VAULT ## ########### @@ -216,6 +204,50 @@ spec: - name: "EDC_VAULT_HASHICORP_API_HEALTH_CHECK_PATH" value: {{ .Values.vault.hashicorp.paths.health | quote }} + ############################# + ## IATP / STS / DIM CONFIG ## + ############################# + - name: "EDC_IAM_STS_OAUTH_TOKEN_URL" + value: {{ .Values.iatp.sts.oauth.token_url | required ".Values.iatp.oauth.token_url is required" | quote}} + - name: "EDC_IAM_STS_OAUTH_CLIENT_ID" + value: {{ .Values.iatp.sts.oauth.client.id | required ".Values.iatp.sts.oauth.client.id is required" | quote}} + - name: "EDC_IAM_STS_OAUTH_CLIENT_SECRET_ALIAS" + value: {{ .Values.iatp.sts.oauth.client.secret_alias | required ".Values.iatp.sts.oauth.client.secret_alias is required" | quote}} + - name: "EDC_IAM_STS_DIM_URL" + value: {{ .Values.iatp.sts.dim.url | required ".Values.iatp.sts.dim.url is required" | quote}} + + + ######################### + ## DATA PLANE PUBLIC API + ######################## + - name: "EDC_DATAPLANE_API_PUBLIC_BASEURL" + value: {{ include "txdc.dataplane.url.public" . }} + + + ################## + ## TOKEN REFRESH + ################## + {{- if .Values.dataplane.token.refresh.expiry_seconds }} + - name: "EDC_DATAPLANE_TOKEN_EXPIRY" + value: {{ .Values.dataplane.token.refresh.expiry_seconds | quote}} + {{- end}} + + {{- if .Values.dataplane.token.refresh.expiry_tolerance_seconds }} + - name: "EDC_DATAPLANE_TOKEN_EXPIRY_TOLERANCE" + value: {{ .Values.dataplane.token.refresh.expiry_tolerance_seconds | quote }} + {{- end}} + + {{- if .Values.dataplane.token.refresh.refresh_endpoint }} + - name: "EDC_DATAPLANE_TOKEN_REFRESH_ENDPOINT" + value: {{ .Values.dataplane.token.refresh.refresh_endpoint }} + {{- end}} + + - name: "EDC_TRANSFER_PROXY_TOKEN_SIGNER_PRIVATEKEY_ALIAS" + value: {{ .Values.dataplane.token.signer.privatekey_alias | required ".Values.dataplane.token.signer.privatekey_alias is required" | quote}} + + - name: "EDC_TRANSFER_PROXY_TOKEN_VERIFIER_PUBLICKEY_ALIAS" + value: {{ .Values.dataplane.token.verifier.publickey_alias | required ".Values.dataplane.token.verifier.publickey_alias" | quote }} + ###################################### ## Additional environment variables ## ###################################### diff --git a/charts/tractusx-connector/values.yaml b/charts/tractusx-connector/values.yaml index 0de6875f6..70e046c0b 100644 --- a/charts/tractusx-connector/values.yaml +++ b/charts/tractusx-connector/values.yaml @@ -40,6 +40,20 @@ participant: # -- BPN Number id: "BPNLCHANGEME" + +iatp: + # Decentralized IDentifier + id: "did:web:changeme" + sts: + dim: + url: + oauth: + token_url: + client: + id: + secret_alias: + + controlplane: image: # -- Which derivate of the control plane to use. when left empty the deployment will select the correct image automatically @@ -117,23 +131,13 @@ controlplane: businessPartnerValidation: log: agreementValidation: true - edr: - transferProxyTokenValidity: "2592000" - # SSI configuration - ssi: - miw: - # -- MIW URL - url: "" - # -- The BPN of the issuer authority - authorityId: "" - oauth: - # -- The URL (of KeyCloak), where access tokens can be obtained - tokenurl: "" - client: - # -- The client ID for KeyCloak - id: "" - # -- The alias under which the client secret is stored in the vault. - secretAlias: "client-secret" + + bdrs: + # time that a cached BPN/DID resolution map is valid in seconds, default is 10 min + cache_validity_seconds: 600 + server: + # URL of the BPN/DID Resolution Service - required: + url: service: # -- [Service type](https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services-service-types) to expose the running application on a set of Pods as a network service. @@ -357,6 +361,20 @@ dataplane: metrics: port: 9090 path: /metrics + + token: + refresh: + expiry_seconds: 300 + expiry_tolerance_seconds: 10 + # optional URL that can be provided where clients go to refresh tokens. + refresh_endpoint: + signer: + # alias under which the private key is stored in the vault (JWK or PEM format) + privatekey_alias: + verifier: + # alias under which the public key is stored in the vault, that belongs to the private key ("privatekey_alias", JWK or PEM format) + publickey_alias: + aws: endpointOverride: "" accessKeyId: "" @@ -525,9 +543,6 @@ vault: transferProxyTokenSignerPrivateKey: transferProxyTokenSignerPublicKey: transferProxyTokenEncryptionAesKey: transfer-proxy-token-encryption-aes-key -backendService: - # -- Specifies a backend service which will receive the EDR - httpProxyTokenReceiverUrl: "https://example.com" networkPolicy: # -- If `true` network policy will be created to restrict access to control- and dataplane diff --git a/core/json-ld-core/src/main/resources/document/dspace.jsonld b/core/json-ld-core/src/main/resources/document/dspace.jsonld new file mode 100644 index 000000000..f475b2350 --- /dev/null +++ b/core/json-ld-core/src/main/resources/document/dspace.jsonld @@ -0,0 +1,62 @@ +{ + "@context": { + "odrl": "http://www.w3.org/ns/odrl/2/", + "xsd": "http://www.w3.org/2001/XMLSchema#", + "cred": "https://www.w3.org/2018/credentials#", + "sec": "https://w3id.org/security#", + "foaf": "http://xmlns.com/foaf/0.1/", + "cc": "http://creativecommons.org/ns#", + "dct": "http://purl.org/dc/terms/", + "dcat": "http://www.w3.org/ns/dcat#", + "dspace": "https://w3id.org/dspace/2024/1/", + + "dct:title": { "@language": "en" }, + "dct:creator": { "@type": "@id" }, + "dct:description": { "@container": "@set" }, + "dct:issued": { "@type": "xsd:dateTime" }, + "dct:modified": { "@type": "xsd:dateTime" }, + + "dcat:byteSize": { "@type": "xsd:decimal" }, + "dcat:distribution": { "@container": "@set" }, + "dcat:theme": { "@type": "@id" }, + "dcat:conformsTo": { "@type": "@id" }, + "dcat:dataset": { "@container": "@set" }, + "dcat:endpointURL": { "@type": "xsd:anyURI" }, + "dcat:endpointDescription": { "@type": "xsd:anyURI" }, + "dcat:keyword": { "@container": "@set" }, + "dcat:servesDataset": {"@container": "@set" }, + "dcat:service": { "@container": "@set" }, + "dcat:accessService": { "@container": "@set" }, + + "dspace:agreementId": { "@type": "@id" }, + "dspace:dataset": { "@type": "@id" }, + "dspace:transportType": { "@type": "@id" }, + "dspace:state": { "@type": "@id" }, + "dspace:providerId": { "@type": "@id" }, + "dspace:consumerId": { "@type": "@id" }, + "dspace:participantId": { "@type": "@id" }, + "dspace:reason": { "@container": "@set" }, + "dspace:catalog": { "@container": "@set" }, + "dspace:filter": { "@container": "@set" }, + "dspace:timestamp": { "@type": "xsd:dateTime" }, + "dspace:callbackAddress": { "@type": "xsd:anyURI" }, + "dspace:endpointProperties": { "@container": "@set" }, + + "foaf:homepage": { "@type": "xsd:anyURI" }, + + "odrl:hasPolicy": { "@container": "@set" }, + "odrl:permission": { "@container": "@set" }, + "odrl:prohibition": { "@container": "@set" }, + "odrl:obligation": { "@container": "@set" }, + "odrl:duty": { "@container": "@set" }, + "odrl:constraint": { "@container": "@set" }, + "odrl:action": { "@type": "@id" }, + "odrl:target": { "@type": "@id" }, + "odrl:leftOperand": { "@type": "@id" }, + "odrl:operator": { "@type": "@id" }, + "odrl:rightOperandReference": { "@type": "@id" }, + "odrl:profile": { "@container": "@set" } + "odrl:assigner": { "@type": "@id" }, + "odrl:assignee": { "@type": "@id" } + } +} diff --git a/edc-extensions/iatp/tx-iatp-sts-dim/src/test/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/DimSecureServiceExtensionTest.java b/edc-extensions/iatp/tx-iatp-sts-dim/src/test/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/DimSecureServiceExtensionTest.java index b8d99569b..f4c5a9b62 100644 --- a/edc-extensions/iatp/tx-iatp-sts-dim/src/test/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/DimSecureServiceExtensionTest.java +++ b/edc-extensions/iatp/tx-iatp-sts-dim/src/test/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/DimSecureServiceExtensionTest.java @@ -20,15 +20,17 @@ package org.eclipse.tractusx.edc.iam.iatp.sts.dim; import org.eclipse.edc.junit.extensions.DependencyInjectionExtension; +import org.eclipse.edc.spi.monitor.Monitor; import org.eclipse.edc.spi.system.ServiceExtensionContext; import org.eclipse.edc.spi.system.configuration.Config; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatNoException; import static org.eclipse.tractusx.edc.iam.iatp.sts.dim.DimSecureTokenServiceExtension.DIM_URL; +import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @ExtendWith(DependencyInjectionExtension.class) @@ -44,7 +46,11 @@ void initialize(ServiceExtensionContext context, DimSecureTokenServiceExtension @Test void initialize_shouldNotThrow_whenUrlIsMissing(ServiceExtensionContext context, DimSecureTokenServiceExtension extension) { - assertThatNoException().isThrownBy(() -> extension.secureTokenService(context)); + var monitor = context.getMonitor(); + var prefixeMonitor = mock(Monitor.class); + when(monitor.withPrefix(anyString())).thenReturn(prefixeMonitor); + extension.secureTokenService(context); + verify(prefixeMonitor).severe("Mandatory config value missing: 'edc.iam.sts.dim.url'. This runtime will not be fully operational! Starting with v0.7.x this will be a runtime error."); } } diff --git a/edc-tests/deployment/src/main/resources/helm/tractusx-connector-azure-vault-test.yaml b/edc-tests/deployment/src/main/resources/helm/tractusx-connector-azure-vault-test.yaml index 98ac76659..0b9e0e5e6 100644 --- a/edc-tests/deployment/src/main/resources/helm/tractusx-connector-azure-vault-test.yaml +++ b/edc-tests/deployment/src/main/resources/helm/tractusx-connector-azure-vault-test.yaml @@ -25,6 +25,17 @@ fullnameOverride: tx-prod ################################ participant: id: "test-participant" +iatp: + # Decentralized IDentifier + id: "did:web:changeme" + sts: + dim: + url: "https://somewhere.dim.org" + oauth: + token_url: "https://changeme.org" + client: + id: "test-client-id" + secret_alias: "test-alias" controlplane: service: type: NodePort @@ -35,13 +46,12 @@ controlplane: pullPolicy: Never tag: "latest" repository: "edc-controlplane-postgresql-azure-vault" - ssi: - miw: - url: "http://localhost:8080" - authorityId: "authorityId" securityContext: # avoids some errors in the log: cannot write temp files of large multipart requests when R/O readOnlyRootFilesystem: false + bdrs: + server: + url: "https://bdrs.test.org" dataplane: endpoints: proxy: @@ -57,6 +67,11 @@ dataplane: endpointOverride: http://minio:9000 secretAccessKey: qwerty123 accessKeyId: qwerty123 + token: + signer: + privatekey_alias: "key-1" + verifier: + publickey_alias: "key-1" postgresql: jdbcUrl: jdbc:postgresql://{{ .Release.Name }}-postgresql:5432/edc auth: diff --git a/edc-tests/deployment/src/main/resources/helm/tractusx-connector-memory-test.yaml b/edc-tests/deployment/src/main/resources/helm/tractusx-connector-memory-test.yaml index 354c667ae..9032eab3a 100644 --- a/edc-tests/deployment/src/main/resources/helm/tractusx-connector-memory-test.yaml +++ b/edc-tests/deployment/src/main/resources/helm/tractusx-connector-memory-test.yaml @@ -23,16 +23,23 @@ fullnameOverride: tx-inmem participant: id: "test-participant" +iatp: + # Decentralized IDentifier + id: "did:web:changeme" + sts: + dim: + url: "https://somewhere.dim.org" + oauth: + token_url: "https://changeme.org" + client: + id: "test-client-id" + secret_alias: "test-alias" runtime: service: type: NodePort endpoints: management: authKey: password - ssi: - miw: - url: "http://localhost:8080" - authorityId: "authorityId" image: pullPolicy: Never tag: "latest" @@ -40,11 +47,16 @@ runtime: securityContext: # avoids some errors in the log: cannot write temp files of large multipart requests when R/O readOnlyRootFilesystem: false + bdrs: + server: + url: "https://bdrs.test.org" + token: + signer: + privatekey_alias: "key-1" + verifier: + publickey_alias: "key-1" vault: secretNames: - transferProxyTokenEncryptionAesKey: aes-keys - # this must be set through CLI args: --set vault.secrets=$YOUR_VAULT_SECRETS where YOUR_VAULT_SECRETS should - # be a string in the format "key1:secret1;key2:secret2;..." secrets: backendService: httpProxyTokenReceiverUrl: "http://backend:8080" diff --git a/edc-tests/deployment/src/main/resources/helm/tractusx-connector-test.yaml b/edc-tests/deployment/src/main/resources/helm/tractusx-connector-test.yaml index 20ec65cbc..dc6c63bf8 100644 --- a/edc-tests/deployment/src/main/resources/helm/tractusx-connector-test.yaml +++ b/edc-tests/deployment/src/main/resources/helm/tractusx-connector-test.yaml @@ -24,7 +24,27 @@ fullnameOverride: tx-prod ################################ participant: id: "test-participant" +iatp: + # Decentralized IDentifier + id: "did:web:changeme" + sts: + dim: + url: "https://somewhere.dim.org" + oauth: + token_url: "https://changeme.org" + client: + id: "test-client-id" + secret_alias: "test-alias" controlplane: + # the ssi object is still needed for the upgradeability test + # todo: remove this after 0.7.0 is released + ssi: + miw: + url: "http://localhost:8080" + authorityId: "authorityId" + oauth: + client: + secretAlias: "client-secret" service: type: NodePort endpoints: @@ -37,13 +57,9 @@ controlplane: securityContext: # avoids some errors in the log: cannot write temp files of large multipart requests when R/O readOnlyRootFilesystem: false - ssi: - miw: - url: "http://localhost:8080" - authorityId: "authorityId" - oauth: - client: - secretAlias: "client-secret" + bdrs: + server: + url: "https://bdrs.test.org" dataplane: endpoints: proxy: @@ -59,6 +75,11 @@ dataplane: endpointOverride: http://minio:9000 secretAccessKey: qwerty123 accessKeyId: qwerty123 + token: + signer: + privatekey_alias: "key-1" + verifier: + publickey_alias: "key-1" postgresql: jdbcUrl: jdbc:postgresql://{{ .Release.Name }}-postgresql:5432/edc auth: @@ -73,6 +94,21 @@ vault: # this must be set through CLI args: --set vault.secrets=$YOUR_VAULT_SECRETS where YOUR_VAULT_SECRETS should # be a string in the format "key1:secret1;key2:secret2;..." secrets: + + # the post-start object is still needed for the upgradeability test + # todo: remove this after 0.7.0 is released + server: + postStart: + - sh + - -c + - |- + { + sleep 5 + + /bin/vault kv put secret/client-secret content=kEmH7QRPWhKfy8f+x0pFMw== + + /bin/vault kv put secret/aes-keys content=YWVzX2VuY2tleV90ZXN0Cg== + } backendService: httpProxyTokenReceiverUrl: "http://backend:8080" tests: diff --git a/edc-tests/deployment/src/main/resources/prepare-test.sh b/edc-tests/deployment/src/main/resources/prepare-test.sh deleted file mode 100755 index ba3848a6b..000000000 --- a/edc-tests/deployment/src/main/resources/prepare-test.sh +++ /dev/null @@ -1,37 +0,0 @@ -#!/bin/bash - -# -# Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) -# -# This program and the accompanying materials are made available under the -# terms of the Apache License, Version 2.0 which is available at -# https://www.apache.org/licenses/LICENSE-2.0 -# -# SPDX-License-Identifier: Apache-2.0 -# -# Contributors: -# Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - initial API and implementation -# -# - -set -euo pipefail - -if [ "$#" -lt 1 ]; then - echo "usage prepare-test.sh PATH_TO_YAML" - echo "" - echo "Please provide the path to the YAML file, which contains the config for the test infrastructure! In most cases - this will be edc-tests/deployment/src/main/resources/helm/test-infrastructure/values.yaml" - exit 42 -fi - -VALUES_FILE=$1 - -CLIENT_SECRET=$(openssl rand -base64 16) -AES_KEY=$(echo aes_enckey_test | base64) -echo "$AES_KEY" > aes.key -echo "$CLIENT_SECRET" > client.secret - -# add a "postStart" command to the vault config, that creates a oauth client secret and an aes-keys secret -yq -i ".vault.server.postStart |= [\"sh\",\"-c\",\"{\nsleep 5\n -/bin/vault kv put secret/client-secret content=$CLIENT_SECRET\n -/bin/vault kv put secret/aes-keys content=$AES_KEY\n}\"]" "$VALUES_FILE" \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 207cad9f6..de13fa183 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -10,7 +10,6 @@ aws = "2.25.21" azure-identity = "1.11.4" bouncyCastle-jdk18on = "1.77" flyway = "10.10.0" -iron-vc = "0.14.0" jackson = "2.17.0" jakarta-json = "2.0.1" jupiter = "5.10.2" @@ -187,7 +186,6 @@ edc-edr-store-receiver = { module = "org.eclipse.edc:edr-store-receiver", versio apache-sshd-core = { module = "org.apache.sshd:sshd-core", version.ref = "apache-sshd" } apache-sshd-sftp = { module = "org.apache.sshd:sshd-sftp", version.ref = "apache-sshd" } -apicatalog-iron-vc = { module = "com.apicatalog:iron-verifiable-credentials", version.ref = "iron-vc" } assertj = { module = "org.assertj:assertj-core", version.ref = "assertj" } awaitility = { module = "org.awaitility:awaitility", version.ref = "awaitility" } aws-s3 = { module = "software.amazon.awssdk:s3", version.ref = "aws" } diff --git a/samples/multi-tenancy/src/main/java/org/eclipse/tractusx/edc/samples/multitenancy/MultiTenantRuntime.java b/samples/multi-tenancy/src/main/java/org/eclipse/tractusx/edc/samples/multitenancy/MultiTenantRuntime.java index d7ac26513..b4c8c0025 100644 --- a/samples/multi-tenancy/src/main/java/org/eclipse/tractusx/edc/samples/multitenancy/MultiTenantRuntime.java +++ b/samples/multi-tenancy/src/main/java/org/eclipse/tractusx/edc/samples/multitenancy/MultiTenantRuntime.java @@ -47,7 +47,8 @@ public static void main(String[] args) { runtime.boot(); } - protected void boot() { + @Override + public void boot() { loadTenantsConfig().getConfig("edc.tenants").partition().forEach(this::bootTenant); } From e877eec3f8095b6f764b6a2bc41dfad30d3c6f9f Mon Sep 17 00:00:00 2001 From: Enrico Risa Date: Tue, 2 Apr 2024 19:51:32 +0200 Subject: [PATCH 092/100] feat: extract scopes only on relevant messages (#1184) * feat: extract scopes only on relevant messages --- edc-extensions/iatp/tx-iatp/build.gradle.kts | 3 + .../iam/iatp/IatpScopeExtractorExtension.java | 6 +- .../iatp/scope/CredentialScopeExtractor.java | 37 ++++- .../scope/CredentialScopeExtractorTest.java | 67 ++++++++- .../tractusx/edc/helpers/DimHelper.java | 3 +- .../edc/lifecycle/DimParticipant.java | 9 ++ .../catalog/DimCatalogIntegrationTest.java | 50 +++++- .../DimHttpPullTransferIntegrationTest.java | 53 ++++++- .../transfer/HttpConsumerPullBaseTest.java | 2 +- .../AbstractIatpConsumerPullTest.java | 142 +++++++++++++++++- .../build.gradle.kts | 1 + 11 files changed, 354 insertions(+), 19 deletions(-) diff --git a/edc-extensions/iatp/tx-iatp/build.gradle.kts b/edc-extensions/iatp/tx-iatp/build.gradle.kts index c4c359f34..ebeda88ae 100644 --- a/edc-extensions/iatp/tx-iatp/build.gradle.kts +++ b/edc-extensions/iatp/tx-iatp/build.gradle.kts @@ -26,6 +26,9 @@ dependencies { implementation(libs.edc.spi.core) implementation(libs.edc.spi.policyengine) implementation(libs.edc.spi.identitytrust) + implementation(libs.edc.spi.contract) + implementation(libs.edc.spi.transfer) + implementation(libs.edc.spi.catalog) implementation(project(":spi:core-spi")) implementation(project(":core:core-utils")) diff --git a/edc-extensions/iatp/tx-iatp/src/main/java/org/eclipse/tractusx/edc/iam/iatp/IatpScopeExtractorExtension.java b/edc-extensions/iatp/tx-iatp/src/main/java/org/eclipse/tractusx/edc/iam/iatp/IatpScopeExtractorExtension.java index 2cd451e1a..8804950e1 100644 --- a/edc-extensions/iatp/tx-iatp/src/main/java/org/eclipse/tractusx/edc/iam/iatp/IatpScopeExtractorExtension.java +++ b/edc-extensions/iatp/tx-iatp/src/main/java/org/eclipse/tractusx/edc/iam/iatp/IatpScopeExtractorExtension.java @@ -22,6 +22,7 @@ import org.eclipse.edc.identitytrust.scope.ScopeExtractorRegistry; import org.eclipse.edc.runtime.metamodel.annotation.Extension; import org.eclipse.edc.runtime.metamodel.annotation.Inject; +import org.eclipse.edc.spi.monitor.Monitor; import org.eclipse.edc.spi.system.ServiceExtension; import org.eclipse.edc.spi.system.ServiceExtensionContext; import org.eclipse.tractusx.edc.iam.iatp.scope.CredentialScopeExtractor; @@ -36,6 +37,9 @@ public class IatpScopeExtractorExtension implements ServiceExtension { @Inject private ScopeExtractorRegistry scopeExtractorRegistry; + @Inject + private Monitor monitor; + @Override public String name() { return NAME; @@ -43,6 +47,6 @@ public String name() { @Override public void initialize(ServiceExtensionContext context) { - scopeExtractorRegistry.registerScopeExtractor(new CredentialScopeExtractor()); + scopeExtractorRegistry.registerScopeExtractor(new CredentialScopeExtractor(monitor)); } } diff --git a/edc-extensions/iatp/tx-iatp/src/main/java/org/eclipse/tractusx/edc/iam/iatp/scope/CredentialScopeExtractor.java b/edc-extensions/iatp/tx-iatp/src/main/java/org/eclipse/tractusx/edc/iam/iatp/scope/CredentialScopeExtractor.java index 48654a1e6..e7391699a 100644 --- a/edc-extensions/iatp/tx-iatp/src/main/java/org/eclipse/tractusx/edc/iam/iatp/scope/CredentialScopeExtractor.java +++ b/edc-extensions/iatp/tx-iatp/src/main/java/org/eclipse/tractusx/edc/iam/iatp/scope/CredentialScopeExtractor.java @@ -19,10 +19,17 @@ package org.eclipse.tractusx.edc.iam.iatp.scope; +import org.eclipse.edc.connector.controlplane.catalog.spi.CatalogRequestMessage; +import org.eclipse.edc.connector.controlplane.contract.spi.types.negotiation.ContractRequestMessage; +import org.eclipse.edc.connector.controlplane.transfer.spi.types.protocol.TransferRequestMessage; import org.eclipse.edc.identitytrust.scope.ScopeExtractor; import org.eclipse.edc.policy.engine.spi.PolicyContext; import org.eclipse.edc.policy.model.Operator; +import org.eclipse.edc.spi.iam.RequestContext; +import org.eclipse.edc.spi.monitor.Monitor; +import org.eclipse.edc.spi.types.domain.message.RemoteMessage; +import java.util.Optional; import java.util.Set; import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.CX_POLICY_NS; @@ -39,21 +46,41 @@ public class CredentialScopeExtractor implements ScopeExtractor { public static final String SCOPE_FORMAT = "%s:%s:read"; public static final String CREDENTIAL_FORMAT = "%sCredential"; - public CredentialScopeExtractor() { + private static final Set> SUPPORTED_MESSAGES = Set.of(CatalogRequestMessage.class, ContractRequestMessage.class, TransferRequestMessage.class); + + private final Monitor monitor; + + public CredentialScopeExtractor(Monitor monitor) { + this.monitor = monitor; } @Override public Set extractScopes(Object leftValue, Operator operator, Object rightValue, PolicyContext context) { Set scopes = Set.of(); - if (leftValue instanceof String leftOperand && leftOperand.startsWith(CX_POLICY_NS)) { - leftOperand = leftOperand.replace(CX_POLICY_NS, ""); - var credentialType = extractCredentialType(leftOperand, rightValue); - scopes = Set.of(SCOPE_FORMAT.formatted(CREDENTIAL_TYPE_NAMESPACE, CREDENTIAL_FORMAT.formatted(capitalize(credentialType)))); + var requestContext = context.getContextData(RequestContext.class); + + if (requestContext != null) { + if (leftValue instanceof String leftOperand && leftOperand.startsWith(CX_POLICY_NS) && isMessageSupported(requestContext)) { + leftOperand = leftOperand.replace(CX_POLICY_NS, ""); + var credentialType = extractCredentialType(leftOperand, rightValue); + scopes = Set.of(SCOPE_FORMAT.formatted(CREDENTIAL_TYPE_NAMESPACE, CREDENTIAL_FORMAT.formatted(capitalize(credentialType)))); + + } + + } else { + monitor.warning("RequestContext not found in the PolicyContext: scope cannot be extracted from the policy. Defaulting to empty scopes"); } return scopes; } + private boolean isMessageSupported(RequestContext ctx) { + return Optional.ofNullable(ctx.getMessage()) + .map(RemoteMessage::getClass) + .map(SUPPORTED_MESSAGES::contains) + .orElse(false); + } + /** * Possible values for credential: *
      diff --git a/edc-extensions/iatp/tx-iatp/src/test/java/org/eclipse/tractusx/edc/iam/iatp/scope/CredentialScopeExtractorTest.java b/edc-extensions/iatp/tx-iatp/src/test/java/org/eclipse/tractusx/edc/iam/iatp/scope/CredentialScopeExtractorTest.java index 3130668fc..a89878479 100644 --- a/edc-extensions/iatp/tx-iatp/src/test/java/org/eclipse/tractusx/edc/iam/iatp/scope/CredentialScopeExtractorTest.java +++ b/edc-extensions/iatp/tx-iatp/src/test/java/org/eclipse/tractusx/edc/iam/iatp/scope/CredentialScopeExtractorTest.java @@ -19,33 +19,69 @@ package org.eclipse.tractusx.edc.iam.iatp.scope; +import org.eclipse.edc.connector.controlplane.catalog.spi.CatalogRequestMessage; +import org.eclipse.edc.connector.controlplane.contract.spi.types.agreement.ContractAgreementMessage; +import org.eclipse.edc.connector.controlplane.contract.spi.types.negotiation.ContractNegotiationTerminationMessage; +import org.eclipse.edc.connector.controlplane.contract.spi.types.negotiation.ContractRequestMessage; +import org.eclipse.edc.connector.controlplane.contract.spi.types.offer.ContractOffer; +import org.eclipse.edc.connector.controlplane.transfer.spi.types.protocol.TransferRequestMessage; +import org.eclipse.edc.connector.controlplane.transfer.spi.types.protocol.TransferTerminationMessage; import org.eclipse.edc.policy.engine.spi.PolicyContextImpl; +import org.eclipse.edc.policy.model.Policy; +import org.eclipse.edc.spi.iam.RequestContext; import org.eclipse.edc.spi.iam.TokenParameters; +import org.eclipse.edc.spi.monitor.Monitor; +import org.eclipse.edc.spi.types.domain.message.RemoteMessage; import org.eclipse.tractusx.edc.edr.spi.CoreConstants; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtensionContext; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.ArgumentsProvider; +import org.junit.jupiter.params.provider.ArgumentsSource; + +import java.util.stream.Stream; import static org.assertj.core.api.Assertions.assertThat; import static org.eclipse.tractusx.edc.iam.iatp.TxIatpConstants.CREDENTIAL_TYPE_NAMESPACE; import static org.eclipse.tractusx.edc.iam.iatp.scope.CredentialScopeExtractor.FRAMEWORK_CREDENTIAL_PREFIX; +import static org.mockito.Mockito.mock; public class CredentialScopeExtractorTest { + private final Monitor monitor = mock(); private CredentialScopeExtractor extractor; @BeforeEach void setup() { - extractor = new CredentialScopeExtractor(); + extractor = new CredentialScopeExtractor(monitor); } - @Test - void verify_extractScopes() { + @DisplayName("Scope extractor with supported messages") + @ParameterizedTest(name = "{1}") + @ArgumentsSource(SupportedMessages.class) + void verify_extractScopes(RemoteMessage message) { var builder = TokenParameters.Builder.newInstance(); - var ctx = PolicyContextImpl.Builder.newInstance().additional(TokenParameters.Builder.class, builder).build(); + var requestContext = RequestContext.Builder.newInstance().message(message).direction(RequestContext.Direction.Egress).build(); + var ctx = PolicyContextImpl.Builder.newInstance().additional(TokenParameters.Builder.class, builder).additional(RequestContext.class, requestContext).build(); var scopes = extractor.extractScopes(CoreConstants.CX_POLICY_NS + FRAMEWORK_CREDENTIAL_PREFIX + ".pfc", null, null, ctx); assertThat(scopes).contains(CREDENTIAL_TYPE_NAMESPACE + ":PfcCredential:read"); } + + @DisplayName("Scope extractor with not supported messages") + @ParameterizedTest(name = "{1}") + @ArgumentsSource(NotSupportedMessages.class) + void verify_extractScopes_isEmpty_whenNotSupportedMessages(RemoteMessage message) { + var builder = TokenParameters.Builder.newInstance(); + var requestContext = RequestContext.Builder.newInstance().message(message).direction(RequestContext.Direction.Egress).build(); + var ctx = PolicyContextImpl.Builder.newInstance().additional(TokenParameters.Builder.class, builder).additional(RequestContext.class, requestContext).build(); + var scopes = extractor.extractScopes(CoreConstants.CX_POLICY_NS + FRAMEWORK_CREDENTIAL_PREFIX + ".pfc", null, null, ctx); + assertThat(scopes).isEmpty(); + } + @Test void verify_extractScope_Empty() { var builder = TokenParameters.Builder.newInstance(); @@ -53,4 +89,27 @@ void verify_extractScope_Empty() { var scopes = extractor.extractScopes("wrong", null, null, ctx); assertThat(scopes).isEmpty(); } + + private static class SupportedMessages implements ArgumentsProvider { + @Override + public Stream provideArguments(ExtensionContext extensionContext) { + var offer = ContractOffer.Builder.newInstance().id("id").assetId("assetId").policy(Policy.Builder.newInstance().build()).build(); + return Stream.of( + Arguments.of(CatalogRequestMessage.Builder.newInstance().build()), + Arguments.of(ContractRequestMessage.Builder.newInstance().contractOffer(offer).callbackAddress("cb").build()), + Arguments.of(TransferRequestMessage.Builder.newInstance().callbackAddress("cb").build()) + ); + } + } + + private static class NotSupportedMessages implements ArgumentsProvider { + @Override + public Stream provideArguments(ExtensionContext extensionContext) { + return Stream.of( + Arguments.of(ContractNegotiationTerminationMessage.Builder.newInstance().build()), + Arguments.of(ContractAgreementMessage.Builder.newInstance().counterPartyAddress("cb").contractAgreement(mock()).build()), + Arguments.of(TransferTerminationMessage.Builder.newInstance().counterPartyAddress("pd").build()) + ); + } + } } diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/helpers/DimHelper.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/helpers/DimHelper.java index dce4bf013..08c0d1210 100644 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/helpers/DimHelper.java +++ b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/helpers/DimHelper.java @@ -35,7 +35,7 @@ public interface DimHelper { * @param name The participant name * @return The composed {@link DimParticipant} */ - static DimParticipant configureParticipant(String name) { + static DimParticipant configureParticipant(String name, String bdrsUrl) { var bpn = getEnv(format("DIM_%s_BPN", name)); var dimUrl = getEnv(format("DIM_%s_DIM_URL", name)); var stsUrl = getEnv(format("DIM_%s_STS_URL", name)); @@ -51,6 +51,7 @@ static DimParticipant configureParticipant(String name) { .dimUri(URI.create(dimUrl)) .trustedIssuer(trustedIssuer) .did(did) + .bdrsUri(URI.create(bdrsUrl)) .build(); } diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/DimParticipant.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/DimParticipant.java index 348398439..e521753a6 100644 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/DimParticipant.java +++ b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/lifecycle/DimParticipant.java @@ -33,10 +33,13 @@ public class DimParticipant extends TractusxIatpParticipantBase { protected URI dimUri; + protected URI bdrsUri; + @Override public Map iatpConfiguration(TractusxIatpParticipantBase... others) { var config = new HashMap<>(super.iatpConfiguration(others)); config.put("edc.iam.sts.dim.url", dimUri.toString()); + config.put("tx.iam.iatp.bdrs.server.url", bdrsUri.toString()); config.put("edc.transfer.proxy.token.verifier.publickey.alias", getKeyId()); return config; } @@ -56,10 +59,16 @@ public Builder dimUri(URI dimUri) { return self(); } + public Builder bdrsUri(URI bdrsUri) { + participant.bdrsUri = bdrsUri; + return self(); + } + @Override public DimParticipant build() { super.build(); Objects.requireNonNull(participant.dimUri, "DIM URI should not be null"); + Objects.requireNonNull(participant.bdrsUri, "BDRS URI should not be null"); return participant; } } diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/catalog/DimCatalogIntegrationTest.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/catalog/DimCatalogIntegrationTest.java index 8ccd84d1f..02e776aa3 100644 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/catalog/DimCatalogIntegrationTest.java +++ b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/catalog/DimCatalogIntegrationTest.java @@ -19,18 +19,27 @@ package org.eclipse.tractusx.edc.tests.catalog; +import com.fasterxml.jackson.databind.ObjectMapper; import org.eclipse.tractusx.edc.lifecycle.DimParticipant; import org.eclipse.tractusx.edc.lifecycle.ParticipantRuntime; import org.eclipse.tractusx.edc.tag.DimIntegrationTest; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; +import org.mockserver.integration.ClientAndServer; +import org.mockserver.model.HttpResponse; +import java.io.ByteArrayOutputStream; +import java.io.IOException; import java.util.Map; +import java.util.zip.GZIPOutputStream; import static org.assertj.core.api.Assertions.assertThat; import static org.eclipse.edc.connector.controlplane.test.system.utils.PolicyFixtures.noConstraintPolicy; +import static org.eclipse.edc.util.io.Ports.getFreePort; import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.CX_POLICY_NS; import static org.eclipse.tractusx.edc.helpers.DimHelper.configureParticipant; import static org.eclipse.tractusx.edc.lifecycle.Runtimes.dimRuntime; @@ -38,19 +47,56 @@ import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.SOKRATES_NAME; import static org.eclipse.tractusx.edc.tests.helpers.CatalogHelperFunctions.getDatasetAssetId; import static org.eclipse.tractusx.edc.tests.helpers.PolicyHelperFunctions.frameworkPolicy; +import static org.mockserver.model.HttpRequest.request; @DimIntegrationTest @Disabled public class DimCatalogIntegrationTest { - protected static final DimParticipant SOKRATES = configureParticipant(SOKRATES_NAME); - protected static final DimParticipant PLATO = configureParticipant(PLATO_NAME); + private static final ObjectMapper MAPPER = new ObjectMapper(); + private static final Integer BDRS_PORT = getFreePort(); + private static final String BDRS_URL = "http://localhost:%s/api".formatted(BDRS_PORT); + + protected static final DimParticipant SOKRATES = configureParticipant(SOKRATES_NAME, BDRS_URL); + protected static final DimParticipant PLATO = configureParticipant(PLATO_NAME, BDRS_URL); @RegisterExtension protected static final ParticipantRuntime PLATO_RUNTIME = dimRuntime(PLATO.getName(), PLATO.iatpConfiguration(SOKRATES)); @RegisterExtension protected static final ParticipantRuntime SOKRATES_RUNTIME = dimRuntime(SOKRATES.getName(), SOKRATES.iatpConfiguration(PLATO)); + private static ClientAndServer bdrsServer; + + @BeforeAll + static void beforeAll() { + bdrsServer = ClientAndServer.startClientAndServer(BDRS_PORT); + bdrsServer.when(request() + .withMethod("GET") + .withPath("/api/bpn-directory")) + .respond(HttpResponse.response() + .withHeader("Content-Encoding", "gzip") + .withBody(createGzipStream()) + .withStatusCode(200)); + + } + + private static byte[] createGzipStream() { + var data = Map.of(SOKRATES.getBpn(), SOKRATES.getDid(), + PLATO.getBpn(), PLATO.getDid()); + + var bas = new ByteArrayOutputStream(); + try (var gzip = new GZIPOutputStream(bas)) { + gzip.write(MAPPER.writeValueAsBytes(data)); + } catch (IOException e) { + throw new RuntimeException(e); + } + return bas.toByteArray(); + } + + @AfterAll + static void afterAll() { + bdrsServer.stop(); + } @Test @DisplayName("Verify that Sokrates receives only the offers he is permitted to") diff --git a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/DimHttpPullTransferIntegrationTest.java b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/DimHttpPullTransferIntegrationTest.java index 2c9c80ef8..1b8d48be9 100644 --- a/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/DimHttpPullTransferIntegrationTest.java +++ b/edc-tests/e2e-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/DimHttpPullTransferIntegrationTest.java @@ -19,30 +19,75 @@ package org.eclipse.tractusx.edc.tests.transfer; +import com.fasterxml.jackson.databind.ObjectMapper; import org.eclipse.tractusx.edc.lifecycle.DimParticipant; import org.eclipse.tractusx.edc.lifecycle.ParticipantRuntime; import org.eclipse.tractusx.edc.tag.DimIntegrationTest; import org.eclipse.tractusx.edc.tests.participant.TractusxParticipantBase; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.extension.RegisterExtension; +import org.mockserver.integration.ClientAndServer; +import org.mockserver.model.HttpResponse; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.Map; +import java.util.zip.GZIPOutputStream; + +import static org.eclipse.edc.util.io.Ports.getFreePort; import static org.eclipse.tractusx.edc.helpers.DimHelper.configureParticipant; import static org.eclipse.tractusx.edc.lifecycle.Runtimes.dimRuntime; import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.PLATO_NAME; import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.SOKRATES_NAME; +import static org.mockserver.model.HttpRequest.request; @DimIntegrationTest @Disabled public class DimHttpPullTransferIntegrationTest extends HttpConsumerPullBaseTest { - protected static final DimParticipant SOKRATES = configureParticipant(SOKRATES_NAME); - protected static final DimParticipant PLATO = configureParticipant(PLATO_NAME); - + private static final ObjectMapper MAPPER = new ObjectMapper(); + private static final Integer BDRS_PORT = getFreePort(); + private static final String BDRS_URL = "http://localhost:%s/api".formatted(BDRS_PORT); + protected static final DimParticipant SOKRATES = configureParticipant(SOKRATES_NAME, BDRS_URL); + protected static final DimParticipant PLATO = configureParticipant(PLATO_NAME, BDRS_URL); @RegisterExtension protected static final ParticipantRuntime PLATO_RUNTIME = dimRuntime(PLATO.getName(), PLATO.iatpConfiguration(SOKRATES)); - @RegisterExtension protected static final ParticipantRuntime SOKRATES_RUNTIME = dimRuntime(SOKRATES.getName(), SOKRATES.iatpConfiguration(PLATO)); + private static ClientAndServer bdrsServer; + + @BeforeAll + static void beforeAll() { + bdrsServer = ClientAndServer.startClientAndServer(BDRS_PORT); + bdrsServer.when(request() + .withMethod("GET") + .withPath("/api/bpn-directory")) + .respond(HttpResponse.response() + .withHeader("Content-Encoding", "gzip") + .withBody(createGzipStream()) + .withStatusCode(200)); + + } + + private static byte[] createGzipStream() { + var data = Map.of(SOKRATES.getBpn(), SOKRATES.getDid(), + PLATO.getBpn(), PLATO.getDid()); + + var bas = new ByteArrayOutputStream(); + try (var gzip = new GZIPOutputStream(bas)) { + gzip.write(MAPPER.writeValueAsBytes(data)); + } catch (IOException e) { + throw new RuntimeException(e); + } + return bas.toByteArray(); + } + + @AfterAll + static void afterAll() { + bdrsServer.stop(); + } @Override public TractusxParticipantBase plato() { diff --git a/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/transfer/HttpConsumerPullBaseTest.java b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/transfer/HttpConsumerPullBaseTest.java index 697615d93..9a35f7f2e 100644 --- a/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/transfer/HttpConsumerPullBaseTest.java +++ b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/transfer/HttpConsumerPullBaseTest.java @@ -51,7 +51,7 @@ public abstract class HttpConsumerPullBaseTest implements ParticipantAwareTest { public static final String MOCK_BACKEND_PATH = "/mock/api"; protected ClientAndServer server; - private String privateBackendUrl; + protected String privateBackendUrl; @BeforeEach diff --git a/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/AbstractIatpConsumerPullTest.java b/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/AbstractIatpConsumerPullTest.java index df4b53d5a..ef0446bd1 100644 --- a/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/AbstractIatpConsumerPullTest.java +++ b/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/AbstractIatpConsumerPullTest.java @@ -19,22 +19,44 @@ package org.eclipse.tractusx.edc.tests.transfer; +import jakarta.json.Json; import jakarta.json.JsonObject; +import org.eclipse.edc.connector.controlplane.transfer.spi.types.TransferProcessStates; +import org.eclipse.edc.policy.model.Operator; import org.eclipse.tractusx.edc.tests.participant.TractusxParticipantBase; import org.eclipse.tractusx.edc.tests.transfer.iatp.harness.DataspaceIssuer; import org.eclipse.tractusx.edc.tests.transfer.iatp.harness.IatpParticipant; import org.eclipse.tractusx.edc.tests.transfer.iatp.harness.StsParticipant; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.extension.ExtensionContext; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.ArgumentsProvider; +import org.junit.jupiter.params.provider.ArgumentsSource; +import org.mockserver.verify.VerificationTimes; +import java.io.IOException; import java.net.URI; +import java.util.List; import java.util.Map; +import java.util.concurrent.atomic.AtomicReference; +import java.util.stream.Stream; +import static org.assertj.core.api.Assertions.assertThat; +import static org.awaitility.Awaitility.await; +import static org.awaitility.pollinterval.FibonacciPollInterval.fibonacci; import static org.eclipse.edc.util.io.Ports.getFreePort; +import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.CX_CREDENTIAL_NS; import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.CX_POLICY_NS; import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.PLATO_BPN; import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.PLATO_NAME; import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.SOKRATES_BPN; import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.SOKRATES_NAME; import static org.eclipse.tractusx.edc.tests.helpers.PolicyHelperFunctions.frameworkPolicy; +import static org.eclipse.tractusx.edc.tests.helpers.TransferProcessHelperFunctions.createProxyRequest; +import static org.eclipse.tractusx.edc.tests.participant.TractusxParticipantBase.ASYNC_TIMEOUT; +import static org.mockserver.model.HttpRequest.request; +import static org.mockserver.model.HttpResponse.response; public abstract class AbstractIatpConsumerPullTest extends HttpConsumerPullBaseTest { @@ -80,9 +102,127 @@ public TractusxParticipantBase sokrates() { return SOKRATES; } + + @DisplayName("Contract policy is fulfilled") + @ParameterizedTest(name = "{1}") + @ArgumentsSource(ValidContractPolicyProvider.class) + void transferData_whenContractPolicyFulfilled(JsonObject contractPolicy, String description) { + var assetId = "api-asset-1"; + + var authCodeHeaderName = "test-authkey"; + var authCode = "test-authcode"; + + Map dataAddress = Map.of( + "baseUrl", privateBackendUrl, + "type", "HttpData", + "contentType", "application/json", + "authKey", authCodeHeaderName, + "authCode", authCode + ); + + PLATO.createAsset(assetId, Map.of(), dataAddress); + + var accessPolicyId = PLATO.createPolicyDefinition(createAccessPolicy(SOKRATES.getBpn())); + var contractPolicyId = PLATO.createPolicyDefinition(contractPolicy); + PLATO.createContractDefinition(assetId, "def-1", accessPolicyId, contractPolicyId); + var transferProcessId = SOKRATES.requestAsset(PLATO, assetId, Json.createObjectBuilder().build(), createProxyRequest(), "HttpData-PULL"); + + var edr = new AtomicReference(); + + // wait until transfer process completes + await().pollInterval(fibonacci()) + .atMost(ASYNC_TIMEOUT) + .untilAsserted(() -> { + var tpState = SOKRATES.getTransferProcessState(transferProcessId); + assertThat(tpState).isNotNull().isEqualTo(TransferProcessStates.STARTED.toString()); + }); + + // wait until EDC is available on the consumer side + server.when(request().withMethod("GET").withPath(MOCK_BACKEND_PATH)).respond(response().withStatusCode(200).withBody("test response")); + await().pollInterval(fibonacci()) + .atMost(ASYNC_TIMEOUT) + .untilAsserted(() -> { + edr.set(SOKRATES.edrs().getEdr(transferProcessId)); + assertThat(edr).isNotNull(); + }); + + // pull data out of provider's backend service: + // Prov-DP -> Prov-backend + assertThat(sokrates().data().pullData(edr.get(), Map.of())).isEqualTo("test response"); + + server.verify(request() + .withPath(MOCK_BACKEND_PATH) + .withHeader("Edc-Contract-Agreement-Id") + .withHeader("Edc-Bpn", sokrates().getBpn()) + .withMethod("GET"), VerificationTimes.exactly(1)); + } + + @DisplayName("Contract policy is NOT fulfilled") + @ParameterizedTest(name = "{1}") + @ArgumentsSource(InvalidContractPolicyProvider.class) + void transferData_whenContractPolicyNotFulfilled(JsonObject contractPolicy, String description) throws IOException { + var assetId = "api-asset-1"; + + var authCodeHeaderName = "test-authkey"; + var authCode = "test-authcode"; + + Map dataAddress = Map.of( + "baseUrl", privateBackendUrl, + "type", "HttpData", + "contentType", "application/json", + "authKey", authCodeHeaderName, + "authCode", authCode + ); + + PLATO.createAsset(assetId, Map.of(), dataAddress); + + var accessPolicyId = PLATO.createPolicyDefinition(createAccessPolicy(SOKRATES.getBpn())); + var contractPolicyId = PLATO.createPolicyDefinition(contractPolicy); + PLATO.createContractDefinition(assetId, "def-1", accessPolicyId, contractPolicyId); + var negotiationId = SOKRATES.initContractNegotiation(PLATO, assetId); + + await().pollInterval(fibonacci()) + .atMost(ASYNC_TIMEOUT) + .untilAsserted(() -> { + var contractNegotiationState = SOKRATES.getContractNegotiationState(negotiationId); + assertThat(contractNegotiationState).isEqualTo("TERMINATED"); + }); + } + @Override protected JsonObject createContractPolicy(String bpn) { - return frameworkPolicy(Map.of(CX_POLICY_NS + "Membership", "active")); + return frameworkPolicy(Map.of(CX_CREDENTIAL_NS + "Membership", "active")); + } + + private static class ValidContractPolicyProvider implements ArgumentsProvider { + @Override + public Stream provideArguments(ExtensionContext extensionContext) { + return Stream.of( + Arguments.of(frameworkPolicy(Map.of(CX_POLICY_NS + "Membership", "active")), "MembershipCredential"), + Arguments.of(frameworkPolicy(Map.of(CX_POLICY_NS + "FrameworkAgreement.pcf", "active")), "PCF Use Case (legacy notation)"), + Arguments.of(frameworkPolicy(Map.of(CX_POLICY_NS + "FrameworkAgreement", "pcf")), "PCF Use Case (new notation)"), + Arguments.of(frameworkPolicy(Map.of(CX_POLICY_NS + "Dismantler", "active")), "Dismantler Credential"), + Arguments.of(frameworkPolicy(Map.of(CX_POLICY_NS + "Dismantler.activityType", "vehicleDismantle")), "Dismantler Cred (activity type)"), + Arguments.of(frameworkPolicy(CX_POLICY_NS + "Dismantler.allowedBrands", Operator.IS_ANY_OF, List.of("Moskvich", "Tatra")), "Dismantler allowedBrands (IS_ANY_OF, one intersects)"), + Arguments.of(frameworkPolicy(CX_POLICY_NS + "Dismantler.allowedBrands", Operator.EQ, List.of("Moskvich", "Lada")), "Dismantler allowedBrands (EQ, exact match)"), + Arguments.of(frameworkPolicy(CX_POLICY_NS + "Dismantler.allowedBrands", Operator.IS_NONE_OF, List.of("Yugo", "Tatra")), "Dismantler allowedBrands (IS_NONE_OF, no intersect)"), + Arguments.of(frameworkPolicy(CX_POLICY_NS + "Dismantler.allowedBrands", Operator.IN, List.of("Moskvich", "Tatra", "Yugo", "Lada")), "Dismantler allowedBrands (IN, fully contained)") + ); + } + } + + private static class InvalidContractPolicyProvider implements ArgumentsProvider { + @Override + public Stream provideArguments(ExtensionContext extensionContext) { + return Stream.of( + Arguments.of(frameworkPolicy(Map.of(CX_POLICY_NS + "FrameworkAgreement.sustainability", "active")), "Sustainability Use Case (legacy notation)"), + Arguments.of(frameworkPolicy(Map.of(CX_POLICY_NS + "FrameworkAgreement", "traceability")), "Traceability Use Case (new notation)"), + Arguments.of(frameworkPolicy(Map.of(CX_POLICY_NS + "Dismantler.activityType", "vehicleScrap")), "Dismantler activityType does not match"), + Arguments.of(frameworkPolicy(CX_POLICY_NS + "Dismantler.allowedBrands", Operator.NEQ, List.of("Moskvich", "Lada")), "Dismantler allowedBrands (NEQ, but is equal)"), + Arguments.of(frameworkPolicy(CX_POLICY_NS + "Dismantler.allowedBrands", Operator.IS_NONE_OF, List.of("Yugo", "Lada")), "Dismantler allowedBrands (IS_NONE_OF, but is one contains)"), + Arguments.of(frameworkPolicy(CX_POLICY_NS + "Dismantler.allowedBrands", Operator.IN, List.of("Moskvich", "Tatra", "Yugo")), "Dismantler allowedBrands (IN, but not subset)") + ); + } } } diff --git a/edc-tests/runtime/iatp/runtime-memory-iatp-dim-ih/build.gradle.kts b/edc-tests/runtime/iatp/runtime-memory-iatp-dim-ih/build.gradle.kts index 78de2f073..8393f81f3 100644 --- a/edc-tests/runtime/iatp/runtime-memory-iatp-dim-ih/build.gradle.kts +++ b/edc-tests/runtime/iatp/runtime-memory-iatp-dim-ih/build.gradle.kts @@ -29,6 +29,7 @@ dependencies { exclude(module = "bdrs-client") } implementation(project(":core:json-ld-core")) + implementation(project(":edc-extensions:cx-policy")) implementation(project(":edc-extensions:iatp:tx-iatp")) implementation(project(":edc-extensions:iatp:tx-iatp-sts-dim")) From 4972a3e4ea61f7ba6d14d9688b2be5b383cc78ad Mon Sep 17 00:00:00 2001 From: Enrico Risa Date: Wed, 3 Apr 2024 13:20:41 +0200 Subject: [PATCH 093/100] chore: updates with the latest EDC refactor (#1189) * chore: updates with the latest EDC refactor * chore: dependencies file --- DEPENDENCIES | 29 ++++++++++--------- .../credentials/CredentialTypePredicate.java | 2 +- ...ctDynamicCredentialConstraintFunction.java | 2 +- ...ismantlerCredentialConstraintFunction.java | 2 +- ...AgreementCredentialConstraintFunction.java | 2 +- .../edc/policy/cx/CredentialFunctions.java | 7 +++-- ...meworkAgreementConstraintFunctionTest.java | 2 +- .../iatp/sts/dim/DimSecureTokenService.java | 4 +-- .../dim/DimSecureTokenServiceExtension.java | 2 +- .../sts/dim/DimSecureTokenServiceTest.java | 2 +- .../iam/iatp/IatpScopeExtractorExtension.java | 2 +- .../iatp/identity/IatpIdentityExtractor.java | 2 +- .../iatp/scope/CredentialScopeExtractor.java | 2 +- .../iatp/IatpScopeExtractorExtensionTest.java | 2 +- .../identity/IatpIdentityExtractorTest.java | 6 ++-- .../TokenRefreshHandlerExtension.java | 2 +- .../tokenrefresh/TokenRefreshHandlerImpl.java | 2 +- .../TokenRefreshHandlerImplTest.java | 2 +- .../tests/runtimes/ParticipantRuntime.java | 2 +- .../iatp/dispatchers/DimDispatcher.java | 2 +- .../iatp/harness/DataspaceIssuer.java | 10 +++---- .../runtime-memory-iatp-ih/build.gradle.kts | 2 +- .../SecureTokenServiceExtension.java | 2 +- gradle/libs.versions.toml | 2 +- 24 files changed, 48 insertions(+), 46 deletions(-) diff --git a/DEPENDENCIES b/DEPENDENCIES index 7b011161f..6adb1ad26 100644 --- a/DEPENDENCIES +++ b/DEPENDENCIES @@ -24,8 +24,8 @@ maven/mavencentral/com.fasterxml.jackson.core/jackson-annotations/2.13.5, Apache maven/mavencentral/com.fasterxml.jackson.core/jackson-annotations/2.14.0, Apache-2.0, approved, #5303 maven/mavencentral/com.fasterxml.jackson.core/jackson-annotations/2.14.1, Apache-2.0, approved, #5303 maven/mavencentral/com.fasterxml.jackson.core/jackson-annotations/2.15.1, Apache-2.0, approved, #7947 -maven/mavencentral/com.fasterxml.jackson.core/jackson-annotations/2.15.2, Apache-2.0, approved, #7947 maven/mavencentral/com.fasterxml.jackson.core/jackson-annotations/2.15.3, Apache-2.0, approved, #7947 +maven/mavencentral/com.fasterxml.jackson.core/jackson-annotations/2.16.2, Apache-2.0, approved, #11606 maven/mavencentral/com.fasterxml.jackson.core/jackson-annotations/2.17.0, Apache-2.0, approved, #13672 maven/mavencentral/com.fasterxml.jackson.core/jackson-core/2.13.5, Apache-2.0, approved, #2133 maven/mavencentral/com.fasterxml.jackson.core/jackson-core/2.14.1, Apache-2.0 AND MIT, approved, #4303 @@ -38,8 +38,8 @@ maven/mavencentral/com.fasterxml.jackson.core/jackson-databind/2.14.0, Apache-2. maven/mavencentral/com.fasterxml.jackson.core/jackson-databind/2.14.1, Apache-2.0, approved, #4105 maven/mavencentral/com.fasterxml.jackson.core/jackson-databind/2.14.2, Apache-2.0, approved, #4105 maven/mavencentral/com.fasterxml.jackson.core/jackson-databind/2.15.1, Apache-2.0, approved, #7934 -maven/mavencentral/com.fasterxml.jackson.core/jackson-databind/2.15.2, Apache-2.0, approved, #7934 maven/mavencentral/com.fasterxml.jackson.core/jackson-databind/2.15.3, Apache-2.0, approved, #7934 +maven/mavencentral/com.fasterxml.jackson.core/jackson-databind/2.16.2, Apache-2.0, approved, #11605 maven/mavencentral/com.fasterxml.jackson.core/jackson-databind/2.17.0, Apache-2.0, approved, #13671 maven/mavencentral/com.fasterxml.jackson.dataformat/jackson-dataformat-toml/2.15.2, Apache-2.0, approved, #9160 maven/mavencentral/com.fasterxml.jackson.dataformat/jackson-dataformat-toml/2.17.0, Apache-2.0, approved, #14192 @@ -47,17 +47,17 @@ maven/mavencentral/com.fasterxml.jackson.dataformat/jackson-dataformat-xml/2.13. maven/mavencentral/com.fasterxml.jackson.dataformat/jackson-dataformat-xml/2.17.0, Apache-2.0, approved, #13666 maven/mavencentral/com.fasterxml.jackson.dataformat/jackson-dataformat-yaml/2.14.0, Apache-2.0, approved, #5933 maven/mavencentral/com.fasterxml.jackson.dataformat/jackson-dataformat-yaml/2.15.1, Apache-2.0, approved, #8802 -maven/mavencentral/com.fasterxml.jackson.dataformat/jackson-dataformat-yaml/2.15.2, Apache-2.0, approved, #8802 +maven/mavencentral/com.fasterxml.jackson.dataformat/jackson-dataformat-yaml/2.16.2, Apache-2.0, approved, #11855 maven/mavencentral/com.fasterxml.jackson.dataformat/jackson-dataformat-yaml/2.17.0, Apache-2.0, approved, #13669 maven/mavencentral/com.fasterxml.jackson.datatype/jackson-datatype-jakarta-jsonp/2.17.0, Apache-2.0, approved, #14161 maven/mavencentral/com.fasterxml.jackson.datatype/jackson-datatype-jsr310/2.13.5, Apache-2.0, approved, clearlydefined maven/mavencentral/com.fasterxml.jackson.datatype/jackson-datatype-jsr310/2.14.0, Apache-2.0, approved, #4699 maven/mavencentral/com.fasterxml.jackson.datatype/jackson-datatype-jsr310/2.15.1, Apache-2.0, approved, #7930 -maven/mavencentral/com.fasterxml.jackson.datatype/jackson-datatype-jsr310/2.15.2, Apache-2.0, approved, #7930 +maven/mavencentral/com.fasterxml.jackson.datatype/jackson-datatype-jsr310/2.16.2, Apache-2.0, approved, #11853 maven/mavencentral/com.fasterxml.jackson.datatype/jackson-datatype-jsr310/2.17.0, Apache-2.0, approved, #14160 maven/mavencentral/com.fasterxml.jackson.jakarta.rs/jackson-jakarta-rs-base/2.17.0, Apache-2.0, approved, #14194 maven/mavencentral/com.fasterxml.jackson.jakarta.rs/jackson-jakarta-rs-json-provider/2.15.1, Apache-2.0, approved, #9236 -maven/mavencentral/com.fasterxml.jackson.jakarta.rs/jackson-jakarta-rs-json-provider/2.15.2, Apache-2.0, approved, #9236 +maven/mavencentral/com.fasterxml.jackson.jakarta.rs/jackson-jakarta-rs-json-provider/2.16.2, Apache-2.0, approved, #11858 maven/mavencentral/com.fasterxml.jackson.jakarta.rs/jackson-jakarta-rs-json-provider/2.17.0, Apache-2.0, approved, #14195 maven/mavencentral/com.fasterxml.jackson.module/jackson-module-jakarta-xmlbind-annotations/2.15.3, Apache-2.0, approved, #9241 maven/mavencentral/com.fasterxml.jackson.module/jackson-module-jakarta-xmlbind-annotations/2.17.0, Apache-2.0, approved, #13668 @@ -143,7 +143,7 @@ maven/mavencentral/dev.failsafe/failsafe/3.3.1, Apache-2.0, approved, #9268 maven/mavencentral/dev.failsafe/failsafe/3.3.2, Apache-2.0, approved, #9268 maven/mavencentral/info.picocli/picocli/4.7.5, Apache-2.0, approved, #4365 maven/mavencentral/io.github.classgraph/classgraph/4.8.154, MIT, approved, CQ22530 -maven/mavencentral/io.github.classgraph/classgraph/4.8.162, MIT, approved, CQ22530 +maven/mavencentral/io.github.classgraph/classgraph/4.8.165, MIT, approved, CQ22530 maven/mavencentral/io.micrometer/micrometer-commons/1.12.4, Apache-2.0 AND (Apache-2.0 AND MIT), approved, #11679 maven/mavencentral/io.micrometer/micrometer-core/1.12.4, Apache-2.0 AND (Apache-2.0 AND MIT), approved, #11678 maven/mavencentral/io.micrometer/micrometer-observation/1.12.4, Apache-2.0, approved, #11680 @@ -218,22 +218,21 @@ maven/mavencentral/io.rest-assured/rest-assured/5.4.0, Apache-2.0, approved, #12 maven/mavencentral/io.rest-assured/xml-path/5.4.0, Apache-2.0, approved, #12038 maven/mavencentral/io.setl/rdf-urdna/1.1, Apache-2.0, approved, clearlydefined maven/mavencentral/io.swagger.core.v3/swagger-annotations-jakarta/2.2.15, Apache-2.0, approved, #5947 -maven/mavencentral/io.swagger.core.v3/swagger-annotations-jakarta/2.2.18, Apache-2.0, approved, #5947 maven/mavencentral/io.swagger.core.v3/swagger-annotations-jakarta/2.2.21, Apache-2.0, approved, #5947 maven/mavencentral/io.swagger.core.v3/swagger-annotations/2.2.15, Apache-2.0, approved, #11362 maven/mavencentral/io.swagger.core.v3/swagger-annotations/2.2.8, Apache-2.0, approved, #11362 maven/mavencentral/io.swagger.core.v3/swagger-core-jakarta/2.2.15, Apache-2.0, approved, #5929 -maven/mavencentral/io.swagger.core.v3/swagger-core-jakarta/2.2.18, Apache-2.0, approved, #5929 +maven/mavencentral/io.swagger.core.v3/swagger-core-jakarta/2.2.21, Apache-2.0, approved, #5929 maven/mavencentral/io.swagger.core.v3/swagger-core/2.2.15, Apache-2.0, approved, #9265 maven/mavencentral/io.swagger.core.v3/swagger-core/2.2.8, Apache-2.0, approved, #9265 maven/mavencentral/io.swagger.core.v3/swagger-integration-jakarta/2.2.15, Apache-2.0, approved, #11475 -maven/mavencentral/io.swagger.core.v3/swagger-integration-jakarta/2.2.18, Apache-2.0, approved, #11475 +maven/mavencentral/io.swagger.core.v3/swagger-integration-jakarta/2.2.21, Apache-2.0, approved, #11475 maven/mavencentral/io.swagger.core.v3/swagger-integration/2.2.15, Apache-2.0, approved, #10352 maven/mavencentral/io.swagger.core.v3/swagger-jaxrs2-jakarta/2.2.15, Apache-2.0, approved, #11477 -maven/mavencentral/io.swagger.core.v3/swagger-jaxrs2-jakarta/2.2.18, Apache-2.0, approved, #11477 +maven/mavencentral/io.swagger.core.v3/swagger-jaxrs2-jakarta/2.2.21, Apache-2.0, approved, #11477 maven/mavencentral/io.swagger.core.v3/swagger-jaxrs2/2.2.15, Apache-2.0, approved, #9814 maven/mavencentral/io.swagger.core.v3/swagger-models-jakarta/2.2.15, Apache-2.0, approved, #5919 -maven/mavencentral/io.swagger.core.v3/swagger-models-jakarta/2.2.18, Apache-2.0, approved, #5919 +maven/mavencentral/io.swagger.core.v3/swagger-models-jakarta/2.2.21, Apache-2.0, approved, #5919 maven/mavencentral/io.swagger.core.v3/swagger-models/2.2.15, Apache-2.0, approved, #10353 maven/mavencentral/io.swagger.core.v3/swagger-models/2.2.8, Apache-2.0, approved, #10353 maven/mavencentral/io.swagger.parser.v3/swagger-parser-core/2.1.10, Apache-2.0, approved, #11478 @@ -286,7 +285,7 @@ maven/mavencentral/org.apache.commons/commons-digester3/3.2, Apache-2.0, approve maven/mavencentral/org.apache.commons/commons-lang3/3.10, Apache-2.0, approved, clearlydefined maven/mavencentral/org.apache.commons/commons-lang3/3.11, Apache-2.0, approved, CQ22642 maven/mavencentral/org.apache.commons/commons-lang3/3.12.0, Apache-2.0, approved, clearlydefined -maven/mavencentral/org.apache.commons/commons-lang3/3.13.0, Apache-2.0, approved, #9820 +maven/mavencentral/org.apache.commons/commons-lang3/3.14.0, Apache-2.0, approved, #11677 maven/mavencentral/org.apache.commons/commons-lang3/3.7, Apache-2.0, approved, clearlydefined maven/mavencentral/org.apache.commons/commons-lang3/3.8.1, Apache-2.0, approved, #815 maven/mavencentral/org.apache.commons/commons-pool2/2.12.0, Apache-2.0 AND LicenseRef-Public-Domain, approved, #10843 @@ -438,8 +437,8 @@ maven/mavencentral/org.eclipse.edc/identity-trust-sts-api/0.6.1-SNAPSHOT, Apache maven/mavencentral/org.eclipse.edc/identity-trust-sts-client-configuration/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/identity-trust-sts-core/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/identity-trust-sts-embedded/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-trust-sts-remote-core/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-trust-sts-remote/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-trust-sts-remote-client/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-trust-sts-remote-lib/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/identity-trust-sts-spi/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/identity-trust-transform/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/jersey-core/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc @@ -452,6 +451,7 @@ maven/mavencentral/org.eclipse.edc/json-ld-spi/0.6.1-SNAPSHOT, Apache-2.0, appro maven/mavencentral/org.eclipse.edc/json-ld/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/junit-base/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/junit/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/jws2020-lib/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/jws2020/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/jwt-spi/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/jwt-verifiable-credentials/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc @@ -555,6 +555,7 @@ maven/mavencentral/org.jacoco/org.jacoco.core/0.8.9, EPL-2.0, approved, CQ23283 maven/mavencentral/org.jacoco/org.jacoco.report/0.8.9, EPL-2.0 AND Apache-2.0, approved, CQ23284 maven/mavencentral/org.javassist/javassist/3.28.0-GA, Apache-2.0 OR LGPL-2.1-or-later OR MPL-1.1, approved, #327 maven/mavencentral/org.javassist/javassist/3.29.2-GA, Apache-2.0 AND LGPL-2.1-or-later AND MPL-1.1, approved, #6023 +maven/mavencentral/org.javassist/javassist/3.30.2-GA, Apache-2.0 AND LGPL-2.1-or-later AND MPL-1.1, approved, #12108 maven/mavencentral/org.jetbrains.kotlin/kotlin-stdlib-common/1.9.10, Apache-2.0, approved, #14186 maven/mavencentral/org.jetbrains.kotlin/kotlin-stdlib-jdk7/1.8.0, Apache-2.0, approved, #8807 maven/mavencentral/org.jetbrains.kotlin/kotlin-stdlib-jdk7/1.8.21, Apache-2.0, approved, #8807 diff --git a/core/core-utils/src/main/java/org/eclipse/tractusx/edc/core/utils/credentials/CredentialTypePredicate.java b/core/core-utils/src/main/java/org/eclipse/tractusx/edc/core/utils/credentials/CredentialTypePredicate.java index 0ab867c26..91ad8a92a 100644 --- a/core/core-utils/src/main/java/org/eclipse/tractusx/edc/core/utils/credentials/CredentialTypePredicate.java +++ b/core/core-utils/src/main/java/org/eclipse/tractusx/edc/core/utils/credentials/CredentialTypePredicate.java @@ -19,7 +19,7 @@ package org.eclipse.tractusx.edc.core.utils.credentials; -import org.eclipse.edc.identitytrust.model.VerifiableCredential; +import org.eclipse.edc.iam.identitytrust.spi.model.VerifiableCredential; import java.util.function.Predicate; diff --git a/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/common/AbstractDynamicCredentialConstraintFunction.java b/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/common/AbstractDynamicCredentialConstraintFunction.java index 164744403..e94ac99fb 100644 --- a/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/common/AbstractDynamicCredentialConstraintFunction.java +++ b/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/common/AbstractDynamicCredentialConstraintFunction.java @@ -19,7 +19,7 @@ package org.eclipse.tractusx.edc.policy.cx.common; -import org.eclipse.edc.identitytrust.model.VerifiableCredential; +import org.eclipse.edc.iam.identitytrust.spi.model.VerifiableCredential; import org.eclipse.edc.policy.engine.spi.DynamicAtomicConstraintFunction; import org.eclipse.edc.policy.engine.spi.PolicyContext; import org.eclipse.edc.policy.model.Operator; diff --git a/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/dismantler/DismantlerCredentialConstraintFunction.java b/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/dismantler/DismantlerCredentialConstraintFunction.java index f9549f2ba..008879b71 100644 --- a/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/dismantler/DismantlerCredentialConstraintFunction.java +++ b/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/dismantler/DismantlerCredentialConstraintFunction.java @@ -20,7 +20,7 @@ package org.eclipse.tractusx.edc.policy.cx.dismantler; import jakarta.json.JsonObject; -import org.eclipse.edc.identitytrust.model.VerifiableCredential; +import org.eclipse.edc.iam.identitytrust.spi.model.VerifiableCredential; import org.eclipse.edc.policy.engine.spi.PolicyContext; import org.eclipse.edc.policy.model.Operator; import org.eclipse.edc.policy.model.Permission; diff --git a/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/framework/FrameworkAgreementCredentialConstraintFunction.java b/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/framework/FrameworkAgreementCredentialConstraintFunction.java index 6aa34648d..2806f26bd 100644 --- a/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/framework/FrameworkAgreementCredentialConstraintFunction.java +++ b/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/framework/FrameworkAgreementCredentialConstraintFunction.java @@ -19,7 +19,7 @@ package org.eclipse.tractusx.edc.policy.cx.framework; -import org.eclipse.edc.identitytrust.model.VerifiableCredential; +import org.eclipse.edc.iam.identitytrust.spi.model.VerifiableCredential; import org.eclipse.edc.policy.engine.spi.PolicyContext; import org.eclipse.edc.policy.model.Operator; import org.eclipse.edc.policy.model.Permission; diff --git a/edc-extensions/cx-policy/src/test/java/org/eclipse/tractusx/edc/policy/cx/CredentialFunctions.java b/edc-extensions/cx-policy/src/test/java/org/eclipse/tractusx/edc/policy/cx/CredentialFunctions.java index d562863d5..d8551dd17 100644 --- a/edc-extensions/cx-policy/src/test/java/org/eclipse/tractusx/edc/policy/cx/CredentialFunctions.java +++ b/edc-extensions/cx-policy/src/test/java/org/eclipse/tractusx/edc/policy/cx/CredentialFunctions.java @@ -19,9 +19,10 @@ package org.eclipse.tractusx.edc.policy.cx; -import org.eclipse.edc.identitytrust.model.CredentialSubject; -import org.eclipse.edc.identitytrust.model.Issuer; -import org.eclipse.edc.identitytrust.model.VerifiableCredential; + +import org.eclipse.edc.iam.identitytrust.spi.model.CredentialSubject; +import org.eclipse.edc.iam.identitytrust.spi.model.Issuer; +import org.eclipse.edc.iam.identitytrust.spi.model.VerifiableCredential; import java.time.Instant; import java.time.temporal.ChronoUnit; diff --git a/edc-extensions/cx-policy/src/test/java/org/eclipse/tractusx/edc/policy/cx/framework/FrameworkAgreementConstraintFunctionTest.java b/edc-extensions/cx-policy/src/test/java/org/eclipse/tractusx/edc/policy/cx/framework/FrameworkAgreementConstraintFunctionTest.java index 03cf56f3a..bcda76c88 100644 --- a/edc-extensions/cx-policy/src/test/java/org/eclipse/tractusx/edc/policy/cx/framework/FrameworkAgreementConstraintFunctionTest.java +++ b/edc-extensions/cx-policy/src/test/java/org/eclipse/tractusx/edc/policy/cx/framework/FrameworkAgreementConstraintFunctionTest.java @@ -19,7 +19,7 @@ package org.eclipse.tractusx.edc.policy.cx.framework; -import org.eclipse.edc.identitytrust.model.VerifiableCredential; +import org.eclipse.edc.iam.identitytrust.spi.model.VerifiableCredential; import org.eclipse.edc.policy.engine.spi.PolicyContext; import org.eclipse.edc.policy.model.Operator; import org.eclipse.edc.policy.model.Permission; diff --git a/edc-extensions/iatp/tx-iatp-sts-dim/src/main/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/DimSecureTokenService.java b/edc-extensions/iatp/tx-iatp-sts-dim/src/main/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/DimSecureTokenService.java index f6b1f9e5f..60c56af78 100644 --- a/edc-extensions/iatp/tx-iatp-sts-dim/src/main/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/DimSecureTokenService.java +++ b/edc-extensions/iatp/tx-iatp-sts-dim/src/main/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/DimSecureTokenService.java @@ -27,7 +27,7 @@ import okhttp3.RequestBody; import okhttp3.Response; import org.eclipse.edc.http.spi.EdcHttpClient; -import org.eclipse.edc.identitytrust.SecureTokenService; +import org.eclipse.edc.iam.identitytrust.spi.SecureTokenService; import org.eclipse.edc.spi.iam.TokenRepresentation; import org.eclipse.edc.spi.monitor.Monitor; import org.eclipse.edc.spi.result.Result; @@ -48,7 +48,7 @@ import static java.lang.String.format; import static org.eclipse.edc.http.spi.FallbackFactories.retryWhenStatusIsNotIn; -import static org.eclipse.edc.identitytrust.SelfIssuedTokenConstants.PRESENTATION_TOKEN_CLAIM; +import static org.eclipse.edc.iam.identitytrust.spi.SelfIssuedTokenConstants.PRESENTATION_TOKEN_CLAIM; import static org.eclipse.edc.jwt.spi.JwtRegisteredClaimNames.AUDIENCE; import static org.eclipse.edc.jwt.spi.JwtRegisteredClaimNames.ISSUER; import static org.eclipse.edc.jwt.spi.JwtRegisteredClaimNames.SUBJECT; diff --git a/edc-extensions/iatp/tx-iatp-sts-dim/src/main/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/DimSecureTokenServiceExtension.java b/edc-extensions/iatp/tx-iatp-sts-dim/src/main/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/DimSecureTokenServiceExtension.java index 165b55db8..5b01ff4e6 100644 --- a/edc-extensions/iatp/tx-iatp-sts-dim/src/main/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/DimSecureTokenServiceExtension.java +++ b/edc-extensions/iatp/tx-iatp-sts-dim/src/main/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/DimSecureTokenServiceExtension.java @@ -20,7 +20,7 @@ package org.eclipse.tractusx.edc.iam.iatp.sts.dim; import org.eclipse.edc.http.spi.EdcHttpClient; -import org.eclipse.edc.identitytrust.SecureTokenService; +import org.eclipse.edc.iam.identitytrust.spi.SecureTokenService; import org.eclipse.edc.runtime.metamodel.annotation.Extension; import org.eclipse.edc.runtime.metamodel.annotation.Inject; import org.eclipse.edc.runtime.metamodel.annotation.Provider; diff --git a/edc-extensions/iatp/tx-iatp-sts-dim/src/test/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/DimSecureTokenServiceTest.java b/edc-extensions/iatp/tx-iatp-sts-dim/src/test/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/DimSecureTokenServiceTest.java index cef39d4f8..5861d00eb 100644 --- a/edc-extensions/iatp/tx-iatp-sts-dim/src/test/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/DimSecureTokenServiceTest.java +++ b/edc-extensions/iatp/tx-iatp-sts-dim/src/test/java/org/eclipse/tractusx/edc/iam/iatp/sts/dim/DimSecureTokenServiceTest.java @@ -46,7 +46,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.eclipse.edc.http.client.testfixtures.HttpTestUtils.testHttpClient; -import static org.eclipse.edc.identitytrust.SelfIssuedTokenConstants.PRESENTATION_TOKEN_CLAIM; +import static org.eclipse.edc.iam.identitytrust.spi.SelfIssuedTokenConstants.PRESENTATION_TOKEN_CLAIM; import static org.eclipse.edc.junit.assertions.AbstractResultAssert.assertThat; import static org.eclipse.edc.jwt.spi.JwtRegisteredClaimNames.AUDIENCE; import static org.eclipse.edc.jwt.spi.JwtRegisteredClaimNames.ISSUER; diff --git a/edc-extensions/iatp/tx-iatp/src/main/java/org/eclipse/tractusx/edc/iam/iatp/IatpScopeExtractorExtension.java b/edc-extensions/iatp/tx-iatp/src/main/java/org/eclipse/tractusx/edc/iam/iatp/IatpScopeExtractorExtension.java index 8804950e1..4963aa4b9 100644 --- a/edc-extensions/iatp/tx-iatp/src/main/java/org/eclipse/tractusx/edc/iam/iatp/IatpScopeExtractorExtension.java +++ b/edc-extensions/iatp/tx-iatp/src/main/java/org/eclipse/tractusx/edc/iam/iatp/IatpScopeExtractorExtension.java @@ -19,7 +19,7 @@ package org.eclipse.tractusx.edc.iam.iatp; -import org.eclipse.edc.identitytrust.scope.ScopeExtractorRegistry; +import org.eclipse.edc.iam.identitytrust.spi.scope.ScopeExtractorRegistry; import org.eclipse.edc.runtime.metamodel.annotation.Extension; import org.eclipse.edc.runtime.metamodel.annotation.Inject; import org.eclipse.edc.spi.monitor.Monitor; diff --git a/edc-extensions/iatp/tx-iatp/src/main/java/org/eclipse/tractusx/edc/iam/iatp/identity/IatpIdentityExtractor.java b/edc-extensions/iatp/tx-iatp/src/main/java/org/eclipse/tractusx/edc/iam/iatp/identity/IatpIdentityExtractor.java index 4899f6af1..ce43b9801 100644 --- a/edc-extensions/iatp/tx-iatp/src/main/java/org/eclipse/tractusx/edc/iam/iatp/identity/IatpIdentityExtractor.java +++ b/edc-extensions/iatp/tx-iatp/src/main/java/org/eclipse/tractusx/edc/iam/iatp/identity/IatpIdentityExtractor.java @@ -19,7 +19,7 @@ package org.eclipse.tractusx.edc.iam.iatp.identity; -import org.eclipse.edc.identitytrust.model.VerifiableCredential; +import org.eclipse.edc.iam.identitytrust.spi.model.VerifiableCredential; import org.eclipse.edc.spi.EdcException; import org.eclipse.edc.spi.agent.ParticipantAgentServiceExtension; import org.eclipse.edc.spi.iam.ClaimToken; diff --git a/edc-extensions/iatp/tx-iatp/src/main/java/org/eclipse/tractusx/edc/iam/iatp/scope/CredentialScopeExtractor.java b/edc-extensions/iatp/tx-iatp/src/main/java/org/eclipse/tractusx/edc/iam/iatp/scope/CredentialScopeExtractor.java index e7391699a..8721e4616 100644 --- a/edc-extensions/iatp/tx-iatp/src/main/java/org/eclipse/tractusx/edc/iam/iatp/scope/CredentialScopeExtractor.java +++ b/edc-extensions/iatp/tx-iatp/src/main/java/org/eclipse/tractusx/edc/iam/iatp/scope/CredentialScopeExtractor.java @@ -22,7 +22,7 @@ import org.eclipse.edc.connector.controlplane.catalog.spi.CatalogRequestMessage; import org.eclipse.edc.connector.controlplane.contract.spi.types.negotiation.ContractRequestMessage; import org.eclipse.edc.connector.controlplane.transfer.spi.types.protocol.TransferRequestMessage; -import org.eclipse.edc.identitytrust.scope.ScopeExtractor; +import org.eclipse.edc.iam.identitytrust.spi.scope.ScopeExtractor; import org.eclipse.edc.policy.engine.spi.PolicyContext; import org.eclipse.edc.policy.model.Operator; import org.eclipse.edc.spi.iam.RequestContext; diff --git a/edc-extensions/iatp/tx-iatp/src/test/java/org/eclipse/tractusx/edc/iam/iatp/IatpScopeExtractorExtensionTest.java b/edc-extensions/iatp/tx-iatp/src/test/java/org/eclipse/tractusx/edc/iam/iatp/IatpScopeExtractorExtensionTest.java index 0cd4b6c7d..d75d366ef 100644 --- a/edc-extensions/iatp/tx-iatp/src/test/java/org/eclipse/tractusx/edc/iam/iatp/IatpScopeExtractorExtensionTest.java +++ b/edc-extensions/iatp/tx-iatp/src/test/java/org/eclipse/tractusx/edc/iam/iatp/IatpScopeExtractorExtensionTest.java @@ -19,7 +19,7 @@ package org.eclipse.tractusx.edc.iam.iatp; -import org.eclipse.edc.identitytrust.scope.ScopeExtractorRegistry; +import org.eclipse.edc.iam.identitytrust.spi.scope.ScopeExtractorRegistry; import org.eclipse.edc.junit.extensions.DependencyInjectionExtension; import org.eclipse.edc.spi.system.ServiceExtensionContext; import org.eclipse.tractusx.edc.iam.iatp.scope.CredentialScopeExtractor; diff --git a/edc-extensions/iatp/tx-iatp/src/test/java/org/eclipse/tractusx/edc/iam/iatp/identity/IatpIdentityExtractorTest.java b/edc-extensions/iatp/tx-iatp/src/test/java/org/eclipse/tractusx/edc/iam/iatp/identity/IatpIdentityExtractorTest.java index 82062d705..8db77d945 100644 --- a/edc-extensions/iatp/tx-iatp/src/test/java/org/eclipse/tractusx/edc/iam/iatp/identity/IatpIdentityExtractorTest.java +++ b/edc-extensions/iatp/tx-iatp/src/test/java/org/eclipse/tractusx/edc/iam/iatp/identity/IatpIdentityExtractorTest.java @@ -19,9 +19,9 @@ package org.eclipse.tractusx.edc.iam.iatp.identity; -import org.eclipse.edc.identitytrust.model.CredentialSubject; -import org.eclipse.edc.identitytrust.model.Issuer; -import org.eclipse.edc.identitytrust.model.VerifiableCredential; +import org.eclipse.edc.iam.identitytrust.spi.model.CredentialSubject; +import org.eclipse.edc.iam.identitytrust.spi.model.Issuer; +import org.eclipse.edc.iam.identitytrust.spi.model.VerifiableCredential; import org.eclipse.edc.spi.EdcException; import org.eclipse.edc.spi.iam.ClaimToken; import org.junit.jupiter.api.Test; diff --git a/edc-extensions/tokenrefresh-handler/src/main/java/org/eclipse/tractusx/edc/common/tokenrefresh/TokenRefreshHandlerExtension.java b/edc-extensions/tokenrefresh-handler/src/main/java/org/eclipse/tractusx/edc/common/tokenrefresh/TokenRefreshHandlerExtension.java index f5a320332..2208cf6b8 100644 --- a/edc-extensions/tokenrefresh-handler/src/main/java/org/eclipse/tractusx/edc/common/tokenrefresh/TokenRefreshHandlerExtension.java +++ b/edc-extensions/tokenrefresh-handler/src/main/java/org/eclipse/tractusx/edc/common/tokenrefresh/TokenRefreshHandlerExtension.java @@ -21,7 +21,7 @@ import org.eclipse.edc.edr.spi.store.EndpointDataReferenceCache; import org.eclipse.edc.http.spi.EdcHttpClient; -import org.eclipse.edc.identitytrust.SecureTokenService; +import org.eclipse.edc.iam.identitytrust.spi.SecureTokenService; import org.eclipse.edc.runtime.metamodel.annotation.Extension; import org.eclipse.edc.runtime.metamodel.annotation.Inject; import org.eclipse.edc.runtime.metamodel.annotation.Provider; diff --git a/edc-extensions/tokenrefresh-handler/src/main/java/org/eclipse/tractusx/edc/common/tokenrefresh/TokenRefreshHandlerImpl.java b/edc-extensions/tokenrefresh-handler/src/main/java/org/eclipse/tractusx/edc/common/tokenrefresh/TokenRefreshHandlerImpl.java index dd59927ad..0d07e8ca4 100644 --- a/edc-extensions/tokenrefresh-handler/src/main/java/org/eclipse/tractusx/edc/common/tokenrefresh/TokenRefreshHandlerImpl.java +++ b/edc-extensions/tokenrefresh-handler/src/main/java/org/eclipse/tractusx/edc/common/tokenrefresh/TokenRefreshHandlerImpl.java @@ -26,7 +26,7 @@ import okhttp3.RequestBody; import org.eclipse.edc.edr.spi.store.EndpointDataReferenceCache; import org.eclipse.edc.http.spi.EdcHttpClient; -import org.eclipse.edc.identitytrust.SecureTokenService; +import org.eclipse.edc.iam.identitytrust.spi.SecureTokenService; import org.eclipse.edc.spi.monitor.Monitor; import org.eclipse.edc.spi.result.Result; import org.eclipse.edc.spi.result.ServiceResult; diff --git a/edc-extensions/tokenrefresh-handler/src/test/java/org/eclipse/tractusx/edc/common/tokenrefresh/TokenRefreshHandlerImplTest.java b/edc-extensions/tokenrefresh-handler/src/test/java/org/eclipse/tractusx/edc/common/tokenrefresh/TokenRefreshHandlerImplTest.java index d77b9b43e..07a51a0be 100644 --- a/edc-extensions/tokenrefresh-handler/src/test/java/org/eclipse/tractusx/edc/common/tokenrefresh/TokenRefreshHandlerImplTest.java +++ b/edc-extensions/tokenrefresh-handler/src/test/java/org/eclipse/tractusx/edc/common/tokenrefresh/TokenRefreshHandlerImplTest.java @@ -37,7 +37,7 @@ import org.assertj.core.api.Assertions; import org.eclipse.edc.edr.spi.store.EndpointDataReferenceCache; import org.eclipse.edc.http.spi.EdcHttpClient; -import org.eclipse.edc.identitytrust.SecureTokenService; +import org.eclipse.edc.iam.identitytrust.spi.SecureTokenService; import org.eclipse.edc.spi.iam.TokenRepresentation; import org.eclipse.edc.spi.result.Result; import org.eclipse.edc.spi.result.StoreResult; diff --git a/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/runtimes/ParticipantRuntime.java b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/runtimes/ParticipantRuntime.java index f13b719db..c41974fd8 100644 --- a/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/runtimes/ParticipantRuntime.java +++ b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/runtimes/ParticipantRuntime.java @@ -25,8 +25,8 @@ import com.nimbusds.jose.jwk.gen.ECKeyGenerator; import org.eclipse.edc.boot.system.injection.InjectionContainer; import org.eclipse.edc.iam.did.spi.resolution.DidPublicKeyResolver; +import org.eclipse.edc.iam.identitytrust.spi.SecureTokenService; import org.eclipse.edc.iam.identitytrust.sts.embedded.EmbeddedSecureTokenService; -import org.eclipse.edc.identitytrust.SecureTokenService; import org.eclipse.edc.junit.extensions.EdcRuntimeExtension; import org.eclipse.edc.spi.iam.AudienceResolver; import org.eclipse.edc.spi.iam.IdentityService; diff --git a/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/iatp/dispatchers/DimDispatcher.java b/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/iatp/dispatchers/DimDispatcher.java index 7193d0793..be30b6022 100644 --- a/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/iatp/dispatchers/DimDispatcher.java +++ b/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/iatp/dispatchers/DimDispatcher.java @@ -32,7 +32,7 @@ import java.util.Optional; import java.util.stream.Collectors; -import static org.eclipse.edc.identitytrust.SelfIssuedTokenConstants.PRESENTATION_TOKEN_CLAIM; +import static org.eclipse.edc.iam.identitytrust.spi.SelfIssuedTokenConstants.PRESENTATION_TOKEN_CLAIM; import static org.eclipse.edc.jwt.spi.JwtRegisteredClaimNames.AUDIENCE; import static org.eclipse.edc.jwt.spi.JwtRegisteredClaimNames.ISSUER; import static org.eclipse.edc.jwt.spi.JwtRegisteredClaimNames.SUBJECT; diff --git a/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/iatp/harness/DataspaceIssuer.java b/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/iatp/harness/DataspaceIssuer.java index 89d61968a..37ce54ec1 100644 --- a/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/iatp/harness/DataspaceIssuer.java +++ b/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/iatp/harness/DataspaceIssuer.java @@ -26,12 +26,12 @@ import jakarta.json.JsonObject; import org.eclipse.edc.iam.did.spi.document.DidDocument; import org.eclipse.edc.iam.did.spi.document.VerificationMethod; +import org.eclipse.edc.iam.identitytrust.spi.model.CredentialFormat; +import org.eclipse.edc.iam.identitytrust.spi.model.CredentialSubject; +import org.eclipse.edc.iam.identitytrust.spi.model.Issuer; +import org.eclipse.edc.iam.identitytrust.spi.model.VerifiableCredential; +import org.eclipse.edc.iam.identitytrust.spi.model.VerifiableCredentialContainer; import org.eclipse.edc.identityhub.spi.model.VerifiableCredentialResource; -import org.eclipse.edc.identitytrust.model.CredentialFormat; -import org.eclipse.edc.identitytrust.model.CredentialSubject; -import org.eclipse.edc.identitytrust.model.Issuer; -import org.eclipse.edc.identitytrust.model.VerifiableCredential; -import org.eclipse.edc.identitytrust.model.VerifiableCredentialContainer; import org.eclipse.edc.jsonld.spi.JsonLd; import org.eclipse.edc.security.signature.jws2020.JwkMethod; import org.eclipse.edc.security.signature.jws2020.JwsSignature2020Suite; diff --git a/edc-tests/runtime/iatp/runtime-memory-iatp-ih/build.gradle.kts b/edc-tests/runtime/iatp/runtime-memory-iatp-ih/build.gradle.kts index 3097edb1e..12b86309c 100644 --- a/edc-tests/runtime/iatp/runtime-memory-iatp-ih/build.gradle.kts +++ b/edc-tests/runtime/iatp/runtime-memory-iatp-ih/build.gradle.kts @@ -45,7 +45,7 @@ dependencies { implementation(libs.edc.core.identitytrust) implementation(libs.edc.core.did) implementation(libs.edc.identity.trust.transform) - implementation(libs.edc.identity.trust.sts.remote) + implementation(libs.edc.identity.trust.sts.remote.client) implementation(libs.edc.identity.trust.issuers.configuration) implementation(libs.edc.auth.oauth2.client) implementation(libs.edc.ih.api) diff --git a/edc-tests/runtime/iatp/runtime-memory-sts/src/main/java/org/eclipse/tractusx/edc/lifecycle/SecureTokenServiceExtension.java b/edc-tests/runtime/iatp/runtime-memory-sts/src/main/java/org/eclipse/tractusx/edc/lifecycle/SecureTokenServiceExtension.java index b76dffaf8..31aa5a597 100644 --- a/edc-tests/runtime/iatp/runtime-memory-sts/src/main/java/org/eclipse/tractusx/edc/lifecycle/SecureTokenServiceExtension.java +++ b/edc-tests/runtime/iatp/runtime-memory-sts/src/main/java/org/eclipse/tractusx/edc/lifecycle/SecureTokenServiceExtension.java @@ -19,8 +19,8 @@ package org.eclipse.tractusx.edc.lifecycle; +import org.eclipse.edc.iam.identitytrust.spi.SecureTokenService; import org.eclipse.edc.iam.identitytrust.sts.embedded.EmbeddedSecureTokenService; -import org.eclipse.edc.identitytrust.SecureTokenService; import org.eclipse.edc.keys.spi.PrivateKeyResolver; import org.eclipse.edc.runtime.metamodel.annotation.Inject; import org.eclipse.edc.runtime.metamodel.annotation.Provider; diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index de13fa183..7ecb3c1cc 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -137,7 +137,7 @@ edc-identity-trust-issuers-configuration = { module = "org.eclipse.edc:identity- # IATP for Testing -edc-identity-trust-sts-remote = { module = "org.eclipse.edc:identity-trust-sts-remote-core", version.ref = "edc" } +edc-identity-trust-sts-remote-client = { module = "org.eclipse.edc:identity-trust-sts-remote-client", version.ref = "edc" } edc-identity-trust-sts-embedded = { module = "org.eclipse.edc:identity-trust-sts-embedded", version.ref = "edc" } edc-identity-trust-sts-core = { module = "org.eclipse.edc:identity-trust-sts-core", version.ref = "edc" } edc-identity-trust-sts-api = { module = "org.eclipse.edc:identity-trust-sts-api", version.ref = "edc" } From 8e1a3202be77d6374731dee5aaf6847feec8963a Mon Sep 17 00:00:00 2001 From: Enrico Risa Date: Wed, 3 Apr 2024 15:09:45 +0200 Subject: [PATCH 094/100] feat: inject the audience(DID) as additional property in the DataFlowStartMessage for later verification in refresh token (#1187) --- .../edc-controlplane-base/build.gradle.kts | 2 +- edc-extensions/bdrs-client/build.gradle.kts | 1 + .../mapper/BdrsClientAudienceMapper.java | 42 +++++++++++ .../identity/mapper/BdrsClientExtension.java | 6 +- .../{BdrsClient.java => BdrsClientImpl.java} | 15 ++-- .../mapper/BdrsClientMapperExtension.java | 47 ++++++++++++ ...rg.eclipse.edc.spi.system.ServiceExtension | 3 +- .../mapper/BdrsClientAudienceMapperTest.java | 74 +++++++++++++++++++ ....java => BdrsClientImplExtensionTest.java} | 4 +- ...lientTest.java => BdrsClientImplTest.java} | 37 +++------- .../mapper/BdrsClientMapperExtensionTest.java | 46 ++++++++++++ .../build.gradle.kts | 30 ++++++++ .../flow/TxDataFlowPropertiesProvider.java | 55 ++++++++++++++ ...TxDataFlowPropertiesProviderExtension.java | 43 +++++++++++ ...rg.eclipse.edc.spi.system.ServiceExtension | 20 +++++ ...taFlowPropertiesProviderExtensionTest.java | 46 ++++++++++++ .../TxDataFlowPropertiesProviderTest.java | 62 ++++++++++++++++ .../DataPlaneTokenRefreshServiceImpl.java | 9 +-- .../fixtures/build.gradle.kts | 1 + .../tests/runtimes/BeforeInitCallback.java | 32 ++++++++ .../tests/runtimes/ParticipantRuntime.java | 16 +++- .../tractusx/edc/tests/runtimes/Runtimes.java | 6 +- .../iatp/runtime/IatpParticipantRuntime.java | 2 + .../transfer-tests/build.gradle.kts | 1 + .../TransferWithTokenRefreshTest.java | 8 +- settings.gradle.kts | 2 + spi/bdrs-client-spi/build.gradle.kts | 27 +++++++ .../edc/spi/identity/mapper/BdrsClient.java | 37 ++++++++++ 28 files changed, 620 insertions(+), 54 deletions(-) create mode 100644 edc-extensions/bdrs-client/src/main/java/org/eclipse/tractusx/edc/identity/mapper/BdrsClientAudienceMapper.java rename edc-extensions/bdrs-client/src/main/java/org/eclipse/tractusx/edc/identity/mapper/{BdrsClient.java => BdrsClientImpl.java} (86%) create mode 100644 edc-extensions/bdrs-client/src/main/java/org/eclipse/tractusx/edc/identity/mapper/BdrsClientMapperExtension.java create mode 100644 edc-extensions/bdrs-client/src/test/java/org/eclipse/tractusx/edc/identity/mapper/BdrsClientAudienceMapperTest.java rename edc-extensions/bdrs-client/src/test/java/org/eclipse/tractusx/edc/identity/mapper/{BdrsClientExtensionTest.java => BdrsClientImplExtensionTest.java} (96%) rename edc-extensions/bdrs-client/src/test/java/org/eclipse/tractusx/edc/identity/mapper/{BdrsClientTest.java => BdrsClientImplTest.java} (80%) create mode 100644 edc-extensions/bdrs-client/src/test/java/org/eclipse/tractusx/edc/identity/mapper/BdrsClientMapperExtensionTest.java create mode 100644 edc-extensions/data-flow-properties-provider/build.gradle.kts create mode 100644 edc-extensions/data-flow-properties-provider/src/main/java/org/eclipse/tractusx/edc/flow/TxDataFlowPropertiesProvider.java create mode 100644 edc-extensions/data-flow-properties-provider/src/main/java/org/eclipse/tractusx/edc/flow/TxDataFlowPropertiesProviderExtension.java create mode 100644 edc-extensions/data-flow-properties-provider/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension create mode 100644 edc-extensions/data-flow-properties-provider/src/test/java/org/eclipse/tractusx/edc/flow/TxDataFlowPropertiesProviderExtensionTest.java create mode 100644 edc-extensions/data-flow-properties-provider/src/test/java/org/eclipse/tractusx/edc/flow/TxDataFlowPropertiesProviderTest.java create mode 100644 edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/runtimes/BeforeInitCallback.java create mode 100644 spi/bdrs-client-spi/build.gradle.kts create mode 100644 spi/bdrs-client-spi/src/main/java/org/eclipse/tractusx/edc/spi/identity/mapper/BdrsClient.java diff --git a/edc-controlplane/edc-controlplane-base/build.gradle.kts b/edc-controlplane/edc-controlplane-base/build.gradle.kts index ad2da35ba..dc79e212a 100644 --- a/edc-controlplane/edc-controlplane-base/build.gradle.kts +++ b/edc-controlplane/edc-controlplane-base/build.gradle.kts @@ -44,7 +44,7 @@ dependencies { runtimeOnly(libs.edc.core.identitytrust) runtimeOnly(project(":edc-extensions:iatp:tx-iatp-sts-dim")) runtimeOnly(project(":edc-extensions:bdrs-client")) - + runtimeOnly(project(":edc-extensions:data-flow-properties-provider")) runtimeOnly(libs.edc.core.connector) runtimeOnly(libs.edc.core.controlplane) diff --git a/edc-extensions/bdrs-client/build.gradle.kts b/edc-extensions/bdrs-client/build.gradle.kts index 11da5875e..30e1401e8 100644 --- a/edc-extensions/bdrs-client/build.gradle.kts +++ b/edc-extensions/bdrs-client/build.gradle.kts @@ -24,6 +24,7 @@ plugins { dependencies { implementation(project(":core:core-utils")) + implementation(project(":spi:bdrs-client-spi")) implementation(libs.edc.spi.core) implementation(libs.edc.spi.http) diff --git a/edc-extensions/bdrs-client/src/main/java/org/eclipse/tractusx/edc/identity/mapper/BdrsClientAudienceMapper.java b/edc-extensions/bdrs-client/src/main/java/org/eclipse/tractusx/edc/identity/mapper/BdrsClientAudienceMapper.java new file mode 100644 index 000000000..fbfa0b434 --- /dev/null +++ b/edc-extensions/bdrs-client/src/main/java/org/eclipse/tractusx/edc/identity/mapper/BdrsClientAudienceMapper.java @@ -0,0 +1,42 @@ +/******************************************************************************** + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +package org.eclipse.tractusx.edc.identity.mapper; + +import org.eclipse.edc.spi.iam.AudienceResolver; +import org.eclipse.edc.spi.types.domain.message.RemoteMessage; +import org.eclipse.tractusx.edc.spi.identity.mapper.BdrsClient; + +/** + * An incoming {@link RemoteMessage} is mapped to a DID by calling {@link BdrsClient#resolve(String)} with the {@link RemoteMessage#getCounterPartyId()} + */ +class BdrsClientAudienceMapper implements AudienceResolver { + + private final BdrsClient client; + + BdrsClientAudienceMapper(BdrsClient client) { + this.client = client; + } + + @Override + public String resolve(RemoteMessage remoteMessage) { + return client.resolve(remoteMessage.getCounterPartyId()); + } + +} diff --git a/edc-extensions/bdrs-client/src/main/java/org/eclipse/tractusx/edc/identity/mapper/BdrsClientExtension.java b/edc-extensions/bdrs-client/src/main/java/org/eclipse/tractusx/edc/identity/mapper/BdrsClientExtension.java index 99d7ffc74..f89cdde5e 100644 --- a/edc-extensions/bdrs-client/src/main/java/org/eclipse/tractusx/edc/identity/mapper/BdrsClientExtension.java +++ b/edc-extensions/bdrs-client/src/main/java/org/eclipse/tractusx/edc/identity/mapper/BdrsClientExtension.java @@ -24,11 +24,11 @@ import org.eclipse.edc.runtime.metamodel.annotation.Inject; import org.eclipse.edc.runtime.metamodel.annotation.Provider; import org.eclipse.edc.runtime.metamodel.annotation.Setting; -import org.eclipse.edc.spi.iam.AudienceResolver; import org.eclipse.edc.spi.system.ServiceExtension; import org.eclipse.edc.spi.system.ServiceExtensionContext; import org.eclipse.edc.spi.types.TypeManager; import org.eclipse.tractusx.edc.core.utils.RequiredConfigWarnings; +import org.eclipse.tractusx.edc.spi.identity.mapper.BdrsClient; import static org.eclipse.tractusx.edc.identity.mapper.BdrsClientExtension.NAME; @@ -54,13 +54,13 @@ public String name() { } @Provider - public AudienceResolver getBdrsAudienceResolver(ServiceExtensionContext context) { + public BdrsClient getBdrsClient(ServiceExtensionContext context) { var baseUrl = context.getConfig().getString(BDRS_SERVER_URL_PROPERTY, null); if (baseUrl == null) { RequiredConfigWarnings.warningNotPresent(context.getMonitor(), BDRS_SERVER_URL_PROPERTY); } var cacheValidity = context.getConfig().getInteger(BDRS_SERVER_CACHE_VALIDITY_PERIOD, DEFAULT_BDRS_CACHE_VALIDITY); - return new BdrsClient(baseUrl, cacheValidity, httpClient, context.getMonitor(), typeManager.getMapper()); + return new BdrsClientImpl(baseUrl, cacheValidity, httpClient, context.getMonitor(), typeManager.getMapper()); } } diff --git a/edc-extensions/bdrs-client/src/main/java/org/eclipse/tractusx/edc/identity/mapper/BdrsClient.java b/edc-extensions/bdrs-client/src/main/java/org/eclipse/tractusx/edc/identity/mapper/BdrsClientImpl.java similarity index 86% rename from edc-extensions/bdrs-client/src/main/java/org/eclipse/tractusx/edc/identity/mapper/BdrsClient.java rename to edc-extensions/bdrs-client/src/main/java/org/eclipse/tractusx/edc/identity/mapper/BdrsClientImpl.java index f84fa141b..e9c5fac5f 100644 --- a/edc-extensions/bdrs-client/src/main/java/org/eclipse/tractusx/edc/identity/mapper/BdrsClient.java +++ b/edc-extensions/bdrs-client/src/main/java/org/eclipse/tractusx/edc/identity/mapper/BdrsClientImpl.java @@ -24,9 +24,8 @@ import okhttp3.Request; import org.eclipse.edc.http.spi.EdcHttpClient; import org.eclipse.edc.spi.EdcException; -import org.eclipse.edc.spi.iam.AudienceResolver; import org.eclipse.edc.spi.monitor.Monitor; -import org.eclipse.edc.spi.types.domain.message.RemoteMessage; +import org.eclipse.tractusx.edc.spi.identity.mapper.BdrsClient; import java.io.IOException; import java.time.Instant; @@ -37,12 +36,11 @@ import java.util.zip.GZIPInputStream; /** - * Holds a local cache of BPN-to-DID mapping entries. An incoming {@link RemoteMessage} is mapped by looking up the {@link RemoteMessage#getCounterPartyId()} - * property in that map. + * Holds a local cache of BPN-to-DID mapping entries. *

      - * The local cache expires after a configurable time, at which point {@link BdrsClient#resolve(RemoteMessage)} requests will hit the server again. + * The local cache expires after a configurable time, at which point {@link BdrsClientImpl#resolve(String)}} requests will hit the server again. */ -class BdrsClient implements AudienceResolver { +class BdrsClientImpl implements BdrsClient { private static final TypeReference> MAP_REF = new TypeReference<>() { }; private final String serverUrl; @@ -54,7 +52,7 @@ class BdrsClient implements AudienceResolver { private Map cache = new HashMap<>(); private Instant lastCacheUpdate; - BdrsClient(String baseUrl, int cacheValidity, EdcHttpClient httpClient, Monitor monitor, ObjectMapper mapper) { + BdrsClientImpl(String baseUrl, int cacheValidity, EdcHttpClient httpClient, Monitor monitor, ObjectMapper mapper) { this.serverUrl = baseUrl; this.cacheValidity = cacheValidity; this.httpClient = httpClient; @@ -63,8 +61,7 @@ class BdrsClient implements AudienceResolver { } @Override - public String resolve(RemoteMessage remoteMessage) { - var bpn = remoteMessage.getCounterPartyId(); + public String resolve(String bpn) { String value; lock.readLock().lock(); try { diff --git a/edc-extensions/bdrs-client/src/main/java/org/eclipse/tractusx/edc/identity/mapper/BdrsClientMapperExtension.java b/edc-extensions/bdrs-client/src/main/java/org/eclipse/tractusx/edc/identity/mapper/BdrsClientMapperExtension.java new file mode 100644 index 000000000..2f5f5a19c --- /dev/null +++ b/edc-extensions/bdrs-client/src/main/java/org/eclipse/tractusx/edc/identity/mapper/BdrsClientMapperExtension.java @@ -0,0 +1,47 @@ +/******************************************************************************** + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +package org.eclipse.tractusx.edc.identity.mapper; + +import org.eclipse.edc.runtime.metamodel.annotation.Extension; +import org.eclipse.edc.runtime.metamodel.annotation.Inject; +import org.eclipse.edc.runtime.metamodel.annotation.Provider; +import org.eclipse.edc.spi.iam.AudienceResolver; +import org.eclipse.edc.spi.system.ServiceExtension; +import org.eclipse.tractusx.edc.spi.identity.mapper.BdrsClient; + +import static org.eclipse.tractusx.edc.identity.mapper.BdrsClientExtension.NAME; + +@Extension(value = NAME) +public class BdrsClientMapperExtension implements ServiceExtension { + + @Inject + private BdrsClient bdrsClient; + + @Override + public String name() { + return NAME; + } + + @Provider + public AudienceResolver getBdrsAudienceResolver() { + return new BdrsClientAudienceMapper(bdrsClient); + } + +} diff --git a/edc-extensions/bdrs-client/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension b/edc-extensions/bdrs-client/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension index 8b85b19b1..656f01271 100644 --- a/edc-extensions/bdrs-client/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension +++ b/edc-extensions/bdrs-client/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension @@ -17,4 +17,5 @@ # SPDX-License-Identifier: Apache-2.0 ################################################################################# -org.eclipse.tractusx.edc.identity.mapper.BdrsClientExtension \ No newline at end of file +org.eclipse.tractusx.edc.identity.mapper.BdrsClientExtension +org.eclipse.tractusx.edc.identity.mapper.BdrsClientMapperExtension \ No newline at end of file diff --git a/edc-extensions/bdrs-client/src/test/java/org/eclipse/tractusx/edc/identity/mapper/BdrsClientAudienceMapperTest.java b/edc-extensions/bdrs-client/src/test/java/org/eclipse/tractusx/edc/identity/mapper/BdrsClientAudienceMapperTest.java new file mode 100644 index 000000000..4f6cc2649 --- /dev/null +++ b/edc-extensions/bdrs-client/src/test/java/org/eclipse/tractusx/edc/identity/mapper/BdrsClientAudienceMapperTest.java @@ -0,0 +1,74 @@ +/******************************************************************************** + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +package org.eclipse.tractusx.edc.identity.mapper; + +import org.eclipse.edc.spi.types.domain.message.RemoteMessage; +import org.eclipse.tractusx.edc.spi.identity.mapper.BdrsClient; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +class BdrsClientAudienceMapperTest { + + private final BdrsClient client = mock(); + + private final BdrsClientAudienceMapper clientAudienceMapper = new BdrsClientAudienceMapper(client); + + @Test + void resolve() { + + when(client.resolve("bpn1")).thenReturn("did:web:did1"); + + var did = clientAudienceMapper.resolve(new TestMessage("bpn1")); + + assertThat(did).isEqualTo("did:web:did1"); + + } + + @Test + void resolve_notFound() { + + when(client.resolve("bpn1")).thenReturn(null); + + var did = clientAudienceMapper.resolve(new TestMessage("bpn1")); + + assertThat(did).isNull(); + + } + + private record TestMessage(String bpn) implements RemoteMessage { + @Override + public String getProtocol() { + return "test-proto"; + } + + @Override + public String getCounterPartyAddress() { + return "http://bpn1"; + } + + @Override + public String getCounterPartyId() { + return bpn; + } + } +} \ No newline at end of file diff --git a/edc-extensions/bdrs-client/src/test/java/org/eclipse/tractusx/edc/identity/mapper/BdrsClientExtensionTest.java b/edc-extensions/bdrs-client/src/test/java/org/eclipse/tractusx/edc/identity/mapper/BdrsClientImplExtensionTest.java similarity index 96% rename from edc-extensions/bdrs-client/src/test/java/org/eclipse/tractusx/edc/identity/mapper/BdrsClientExtensionTest.java rename to edc-extensions/bdrs-client/src/test/java/org/eclipse/tractusx/edc/identity/mapper/BdrsClientImplExtensionTest.java index 6123f1332..8e3b4246a 100644 --- a/edc-extensions/bdrs-client/src/test/java/org/eclipse/tractusx/edc/identity/mapper/BdrsClientExtensionTest.java +++ b/edc-extensions/bdrs-client/src/test/java/org/eclipse/tractusx/edc/identity/mapper/BdrsClientImplExtensionTest.java @@ -35,7 +35,7 @@ import static org.mockito.Mockito.when; @ExtendWith(DependencyInjectionExtension.class) -class BdrsClientExtensionTest { +class BdrsClientImplExtensionTest { private final Monitor monitor = mock(); @@ -50,7 +50,7 @@ void createClient_whenUrlMissing_expectLogError(ServiceExtensionContext context, when(context.getConfig()).thenReturn(cfg); when(cfg.getString(eq(BDRS_SERVER_URL_PROPERTY), isNull())).thenReturn(null); - extension.getBdrsAudienceResolver(context); + extension.getBdrsClient(context); verify(monitor).severe(eq("Mandatory config value missing: 'tx.iam.iatp.bdrs.server.url'. This runtime will not be fully operational! Starting with v0.7.x this will be a runtime error.")); } diff --git a/edc-extensions/bdrs-client/src/test/java/org/eclipse/tractusx/edc/identity/mapper/BdrsClientTest.java b/edc-extensions/bdrs-client/src/test/java/org/eclipse/tractusx/edc/identity/mapper/BdrsClientImplTest.java similarity index 80% rename from edc-extensions/bdrs-client/src/test/java/org/eclipse/tractusx/edc/identity/mapper/BdrsClientTest.java rename to edc-extensions/bdrs-client/src/test/java/org/eclipse/tractusx/edc/identity/mapper/BdrsClientImplTest.java index bb77c54c2..4cb5f3c0d 100644 --- a/edc-extensions/bdrs-client/src/test/java/org/eclipse/tractusx/edc/identity/mapper/BdrsClientTest.java +++ b/edc-extensions/bdrs-client/src/test/java/org/eclipse/tractusx/edc/identity/mapper/BdrsClientImplTest.java @@ -25,7 +25,6 @@ import org.eclipse.edc.http.client.EdcHttpClientImpl; import org.eclipse.edc.spi.EdcException; import org.eclipse.edc.spi.monitor.Monitor; -import org.eclipse.edc.spi.types.domain.message.RemoteMessage; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -48,11 +47,11 @@ import static org.mockserver.model.HttpRequest.request; import static org.mockserver.verify.VerificationTimes.exactly; -class BdrsClientTest { +class BdrsClientImplTest { private final Monitor monitor = mock(); private final ObjectMapper mapper = new ObjectMapper(); - private BdrsClient client; + private BdrsClientImpl client; private ClientAndServer bdrsServer; @BeforeEach @@ -66,7 +65,7 @@ void setup() { .withBody(createGzipStream()) .withStatusCode(200)); - client = new BdrsClient("http://localhost:%d/api".formatted(bdrsServer.getPort()), 1, new EdcHttpClientImpl(new OkHttpClient(), RetryPolicy.ofDefaults(), monitor), monitor, mapper); + client = new BdrsClientImpl("http://localhost:%d/api".formatted(bdrsServer.getPort()), 1, new EdcHttpClientImpl(new OkHttpClient(), RetryPolicy.ofDefaults(), monitor), monitor, mapper); } @AfterEach @@ -76,7 +75,7 @@ void teardown() { @Test void getData_whenCacheCold_shouldHitServer() { - var did = client.resolve(new TestMessage("bpn1")); + var did = client.resolve("bpn1"); assertThat(did).isEqualTo("did:web:did1"); bdrsServer.verify(request() @@ -88,8 +87,8 @@ void getData_whenCacheCold_shouldHitServer() { @Test void getData_whenCacheHot_shouldNotHitServer() { - var did1 = client.resolve(new TestMessage("bpn1")); - var did2 = client.resolve(new TestMessage("bpn2")); + var did1 = client.resolve("bpn1"); + var did2 = client.resolve("bpn2"); assertThat(did1).isEqualTo("did:web:did1"); assertThat(did2).isEqualTo("did:web:did2"); @@ -102,13 +101,13 @@ void getData_whenCacheHot_shouldNotHitServer() { @Test void getData_whenCacheExpired_shouldHitServer() { - var did1 = client.resolve(new TestMessage("bpn1")); // hits server + var did1 = client.resolve("bpn1"); // hits server assertThat(did1).isEqualTo("did:web:did1"); await().pollDelay(ofSeconds(2)) .atMost(ofSeconds(3)) //cache expires .untilAsserted(() -> { - var did2 = client.resolve(new TestMessage("bpn2")); // hits server as well, b/c cache is expired + var did2 = client.resolve("bpn2"); // hits server as well, b/c cache is expired assertThat(did2).isEqualTo("did:web:did2"); bdrsServer.verify(request() @@ -122,7 +121,7 @@ void getData_whenCacheExpired_shouldHitServer() { @Test void getData_whenNotFound() { - var did = client.resolve(new TestMessage("bpn-notexist")); + var did = client.resolve("bpn-notexist"); assertThat(did).isNull(); bdrsServer.verify(request() .withMethod("GET") @@ -137,7 +136,7 @@ void getData_bdrsReturnsError(int code) { bdrsServer.reset(); bdrsServer.when(request().withPath("/api/bpn-directory").withMethod("GET")) .respond(HttpResponse.response().withStatusCode(code)); - assertThatThrownBy(() -> client.resolve(new TestMessage("bpn1"))).isInstanceOf(EdcException.class); + assertThatThrownBy(() -> client.resolve("bpn1")).isInstanceOf(EdcException.class); } private byte[] createGzipStream() { @@ -154,20 +153,4 @@ private byte[] createGzipStream() { return bas.toByteArray(); } - private record TestMessage(String bpn) implements RemoteMessage { - @Override - public String getProtocol() { - return "test-proto"; - } - - @Override - public String getCounterPartyAddress() { - return "http://bpn1"; - } - - @Override - public String getCounterPartyId() { - return bpn; - } - } } \ No newline at end of file diff --git a/edc-extensions/bdrs-client/src/test/java/org/eclipse/tractusx/edc/identity/mapper/BdrsClientMapperExtensionTest.java b/edc-extensions/bdrs-client/src/test/java/org/eclipse/tractusx/edc/identity/mapper/BdrsClientMapperExtensionTest.java new file mode 100644 index 000000000..45b6feb50 --- /dev/null +++ b/edc-extensions/bdrs-client/src/test/java/org/eclipse/tractusx/edc/identity/mapper/BdrsClientMapperExtensionTest.java @@ -0,0 +1,46 @@ +/******************************************************************************** + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +package org.eclipse.tractusx.edc.identity.mapper; + +import org.eclipse.edc.junit.extensions.DependencyInjectionExtension; +import org.eclipse.edc.spi.monitor.Monitor; +import org.eclipse.edc.spi.system.ServiceExtensionContext; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; + +@ExtendWith(DependencyInjectionExtension.class) +class BdrsClientMapperExtensionTest { + + private final Monitor monitor = mock(); + + @BeforeEach + void setup(ServiceExtensionContext context) { + context.registerService(Monitor.class, monitor); + } + + @Test + void createMapper(BdrsClientMapperExtension extension) { + assertThat(extension.getBdrsAudienceResolver()).isInstanceOf(BdrsClientAudienceMapper.class); + } +} \ No newline at end of file diff --git a/edc-extensions/data-flow-properties-provider/build.gradle.kts b/edc-extensions/data-flow-properties-provider/build.gradle.kts new file mode 100644 index 000000000..a1c8e165b --- /dev/null +++ b/edc-extensions/data-flow-properties-provider/build.gradle.kts @@ -0,0 +1,30 @@ +/******************************************************************************** + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +plugins { + `maven-publish` + `java-library` +} + +dependencies { + implementation(libs.edc.spi.transfer) + implementation(project(":spi:bdrs-client-spi")) + + testImplementation(libs.edc.junit) +} diff --git a/edc-extensions/data-flow-properties-provider/src/main/java/org/eclipse/tractusx/edc/flow/TxDataFlowPropertiesProvider.java b/edc-extensions/data-flow-properties-provider/src/main/java/org/eclipse/tractusx/edc/flow/TxDataFlowPropertiesProvider.java new file mode 100644 index 000000000..d1cc7d0b4 --- /dev/null +++ b/edc-extensions/data-flow-properties-provider/src/main/java/org/eclipse/tractusx/edc/flow/TxDataFlowPropertiesProvider.java @@ -0,0 +1,55 @@ +/******************************************************************************** + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +package org.eclipse.tractusx.edc.flow; + +import org.eclipse.edc.connector.controlplane.transfer.spi.flow.DataFlowPropertiesProvider; +import org.eclipse.edc.connector.controlplane.transfer.spi.types.TransferProcess; +import org.eclipse.edc.policy.model.Policy; +import org.eclipse.edc.spi.response.ResponseStatus; +import org.eclipse.edc.spi.response.StatusResult; +import org.eclipse.edc.spi.types.domain.transfer.DataFlowStartMessage; +import org.eclipse.tractusx.edc.spi.identity.mapper.BdrsClient; + +import java.util.Map; + +/** + * Extension of {@link DataFlowPropertiesProvider} which provides additional properties in the {@link DataFlowStartMessage} + * like the DID of the counter-party BPN. The resolution is made with the {@link BdrsClient} + */ +public class TxDataFlowPropertiesProvider implements DataFlowPropertiesProvider { + + private static final String AUDIENCE_PROPERTY = "audience"; + + private final BdrsClient bdrsClient; + + public TxDataFlowPropertiesProvider(BdrsClient bdrsClient) { + this.bdrsClient = bdrsClient; + } + + @Override + public StatusResult> propertiesFor(TransferProcess transferProcess, Policy policy) { + var did = bdrsClient.resolve(policy.getAssignee()); + if (did != null) { + return StatusResult.success(Map.of(AUDIENCE_PROPERTY, did)); + } else { + return StatusResult.failure(ResponseStatus.FATAL_ERROR, "Failed to fetch did for BPN %s".formatted(policy.getAssignee())); + } + } +} diff --git a/edc-extensions/data-flow-properties-provider/src/main/java/org/eclipse/tractusx/edc/flow/TxDataFlowPropertiesProviderExtension.java b/edc-extensions/data-flow-properties-provider/src/main/java/org/eclipse/tractusx/edc/flow/TxDataFlowPropertiesProviderExtension.java new file mode 100644 index 000000000..8493b1a12 --- /dev/null +++ b/edc-extensions/data-flow-properties-provider/src/main/java/org/eclipse/tractusx/edc/flow/TxDataFlowPropertiesProviderExtension.java @@ -0,0 +1,43 @@ +/******************************************************************************** + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +package org.eclipse.tractusx.edc.flow; + +import org.eclipse.edc.connector.controlplane.transfer.spi.flow.DataFlowPropertiesProvider; +import org.eclipse.edc.runtime.metamodel.annotation.Extension; +import org.eclipse.edc.runtime.metamodel.annotation.Inject; +import org.eclipse.edc.runtime.metamodel.annotation.Provider; +import org.eclipse.edc.spi.system.ServiceExtension; +import org.eclipse.tractusx.edc.spi.identity.mapper.BdrsClient; + +import static org.eclipse.tractusx.edc.flow.TxDataFlowPropertiesProviderExtension.NAME; + +@Extension(NAME) +public class TxDataFlowPropertiesProviderExtension implements ServiceExtension { + + protected static final String NAME = "Tractus-X Data flow properties provider extension"; + + @Inject + private BdrsClient bdrsClient; + + @Provider + public DataFlowPropertiesProvider dataFlowPropertiesProvider() { + return new TxDataFlowPropertiesProvider(bdrsClient); + } +} diff --git a/edc-extensions/data-flow-properties-provider/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension b/edc-extensions/data-flow-properties-provider/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension new file mode 100644 index 000000000..3a7b065a9 --- /dev/null +++ b/edc-extensions/data-flow-properties-provider/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension @@ -0,0 +1,20 @@ +################################################################################# +# Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License, Version 2.0 which is available at +# https://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. +# +# SPDX-License-Identifier: Apache-2.0 +################################################################################# + +org.eclipse.tractusx.edc.flow.TxDataFlowPropertiesProviderExtension \ No newline at end of file diff --git a/edc-extensions/data-flow-properties-provider/src/test/java/org/eclipse/tractusx/edc/flow/TxDataFlowPropertiesProviderExtensionTest.java b/edc-extensions/data-flow-properties-provider/src/test/java/org/eclipse/tractusx/edc/flow/TxDataFlowPropertiesProviderExtensionTest.java new file mode 100644 index 000000000..11e095ba6 --- /dev/null +++ b/edc-extensions/data-flow-properties-provider/src/test/java/org/eclipse/tractusx/edc/flow/TxDataFlowPropertiesProviderExtensionTest.java @@ -0,0 +1,46 @@ +/******************************************************************************** + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +package org.eclipse.tractusx.edc.flow; + +import org.eclipse.edc.junit.extensions.DependencyInjectionExtension; +import org.eclipse.edc.spi.monitor.Monitor; +import org.eclipse.edc.spi.system.ServiceExtensionContext; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; + +@ExtendWith(DependencyInjectionExtension.class) +class TxDataFlowPropertiesProviderExtensionTest { + + private final Monitor monitor = mock(); + + @BeforeEach + void setup(ServiceExtensionContext context) { + context.registerService(Monitor.class, monitor); + } + + @Test + void createMapper(TxDataFlowPropertiesProviderExtension extension) { + assertThat(extension.dataFlowPropertiesProvider()).isInstanceOf(TxDataFlowPropertiesProvider.class); + } +} \ No newline at end of file diff --git a/edc-extensions/data-flow-properties-provider/src/test/java/org/eclipse/tractusx/edc/flow/TxDataFlowPropertiesProviderTest.java b/edc-extensions/data-flow-properties-provider/src/test/java/org/eclipse/tractusx/edc/flow/TxDataFlowPropertiesProviderTest.java new file mode 100644 index 000000000..f757d5df9 --- /dev/null +++ b/edc-extensions/data-flow-properties-provider/src/test/java/org/eclipse/tractusx/edc/flow/TxDataFlowPropertiesProviderTest.java @@ -0,0 +1,62 @@ +/******************************************************************************** + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +package org.eclipse.tractusx.edc.flow; + +import org.assertj.core.api.Assertions; +import org.eclipse.edc.connector.controlplane.transfer.spi.types.TransferProcess; +import org.eclipse.edc.policy.model.Policy; +import org.eclipse.tractusx.edc.spi.identity.mapper.BdrsClient; +import org.junit.jupiter.api.Test; + +import static org.eclipse.edc.junit.assertions.AbstractResultAssert.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class TxDataFlowPropertiesProviderTest { + + private final BdrsClient client = mock(); + private final TxDataFlowPropertiesProvider provider = new TxDataFlowPropertiesProvider(client); + + + @Test + void propertiesFor() { + + var bpn = "bpn"; + var did = "did"; + + when(client.resolve(bpn)).thenReturn(did); + var result = provider.propertiesFor(TransferProcess.Builder.newInstance().build(), Policy.Builder.newInstance().assignee(bpn).build()); + + assertThat(result).isSucceeded().satisfies(properties -> { + Assertions.assertThat(properties).containsEntry("audience", did); + }); + } + + @Test + void propertiesFor_fails_whenResolutionIsNull() { + + var bpn = "bpn"; + + when(client.resolve(bpn)).thenReturn(null); + var result = provider.propertiesFor(TransferProcess.Builder.newInstance().build(), Policy.Builder.newInstance().assignee(bpn).build()); + + assertThat(result).isFailed().withFailMessage("Failed to fetch did for BPN %s".formatted(bpn)); + } +} diff --git a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImpl.java b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImpl.java index b52317258..64991f0f2 100644 --- a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImpl.java +++ b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImpl.java @@ -43,6 +43,7 @@ import org.eclipse.edc.token.spi.TokenGenerationService; import org.eclipse.edc.token.spi.TokenValidationRule; import org.eclipse.edc.token.spi.TokenValidationService; +import org.eclipse.tractusx.edc.dataplane.tokenrefresh.core.rules.AuthTokenAudienceRule; import org.eclipse.tractusx.edc.dataplane.tokenrefresh.core.rules.ClaimIsPresentRule; import org.eclipse.tractusx.edc.dataplane.tokenrefresh.core.rules.IssuerEqualsSubjectRule; import org.eclipse.tractusx.edc.dataplane.tokenrefresh.core.rules.RefreshTokenValidationRule; @@ -119,8 +120,8 @@ public DataPlaneTokenRefreshServiceImpl(Clock clock, authenticationTokenValidationRules = List.of(new IssuerEqualsSubjectRule(), new ClaimIsPresentRule(AUDIENCE), // we don't check the contents, only it is present new ClaimIsPresentRule(ACCESS_TOKEN_CLAIM), - new ClaimIsPresentRule(TOKEN_ID_CLAIM) - /*new AuthTokenAudienceRule(accessTokenDataStore)*/); + new ClaimIsPresentRule(TOKEN_ID_CLAIM), + new AuthTokenAudienceRule(accessTokenDataStore)); accessTokenAuthorizationRules = List.of(new IssuerEqualsSubjectRule(), new ClaimIsPresentRule(AUDIENCE), new ClaimIsPresentRule(TOKEN_ID_CLAIM), @@ -147,9 +148,7 @@ public DataPlaneTokenRefreshServiceImpl(Clock clock, public Result refreshToken(String refreshToken, String authenticationToken) { authenticationToken = authenticationToken.replace("Bearer", "").trim(); - - // 1. validate authentication token - monitor.warning(" TOKEN REFRESH :: TEMPORARILY DISABLED RULE AuthTokenAudienceRule UNTIL THE 'audience' PROPERTY IS FORWARDED TO DATAPLANES%n"); + var authTokenRes = tokenValidationService.validate(authenticationToken, publicKeyResolver, authenticationTokenValidationRules); if (authTokenRes.failed()) { return Result.failure("Authentication token validation failed: %s".formatted(authTokenRes.getFailureDetail())); diff --git a/edc-tests/edc-controlplane/fixtures/build.gradle.kts b/edc-tests/edc-controlplane/fixtures/build.gradle.kts index dc93f0e33..2297b33c6 100644 --- a/edc-tests/edc-controlplane/fixtures/build.gradle.kts +++ b/edc-tests/edc-controlplane/fixtures/build.gradle.kts @@ -28,6 +28,7 @@ dependencies { testFixturesApi(project(":edc-extensions:edr:edr-api-v2")) testFixturesApi(project(":spi:core-spi")) testFixturesApi(project(":spi:tokenrefresh-spi")) + testFixturesApi(project(":spi:bdrs-client-spi")) testFixturesApi(libs.edc.spi.core) testFixturesApi(libs.edc.spi.policy) diff --git a/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/runtimes/BeforeInitCallback.java b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/runtimes/BeforeInitCallback.java new file mode 100644 index 000000000..1fe184957 --- /dev/null +++ b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/runtimes/BeforeInitCallback.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.eclipse.tractusx.edc.tests.runtimes; + +import org.eclipse.edc.junit.extensions.EdcExtension; + +/** + * Callback invoked before the runtime boots with extensions of {@link EdcExtension}. This will allow injecting + * custom mock services directly in the tests rather than extending the {@link EdcExtension} with custom mocks + */ +@FunctionalInterface +public interface BeforeInitCallback { + + void beforeInit(EdcExtension runtime); +} diff --git a/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/runtimes/ParticipantRuntime.java b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/runtimes/ParticipantRuntime.java index c41974fd8..9207153fe 100644 --- a/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/runtimes/ParticipantRuntime.java +++ b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/runtimes/ParticipantRuntime.java @@ -36,6 +36,7 @@ import org.eclipse.edc.spi.system.ServiceExtensionContext; import org.eclipse.edc.spi.types.domain.message.RemoteMessage; import org.eclipse.edc.token.JwtGenerationService; +import org.eclipse.tractusx.edc.spi.identity.mapper.BdrsClient; import org.eclipse.tractusx.edc.tests.MockBpnIdentityService; import org.junit.jupiter.api.extension.AfterAllCallback; import org.junit.jupiter.api.extension.BeforeAllCallback; @@ -54,12 +55,15 @@ public class ParticipantRuntime extends EdcRuntimeExtension implements BeforeAll private DataWiper wiper; public ParticipantRuntime(String moduleName, String runtimeName, String bpn, Map properties) { + this(moduleName, runtimeName, bpn, properties, null); + } + + public ParticipantRuntime(String moduleName, String runtimeName, String bpn, Map properties, BeforeInitCallback beforeInitCallback) { super(moduleName, runtimeName, properties); this.properties = properties; - if (!properties.containsKey("tx.ssi.miw.url")) { - this.registerServiceMock(IdentityService.class, new MockBpnIdentityService(bpn)); - this.registerServiceMock(AudienceResolver.class, RemoteMessage::getCounterPartyAddress); - } + this.registerServiceMock(IdentityService.class, new MockBpnIdentityService(bpn)); + this.registerServiceMock(AudienceResolver.class, RemoteMessage::getCounterPartyAddress); + this.registerServiceMock(BdrsClient.class, (s) -> s); var kid = properties.get("edc.iam.issuer.id") + "#key-1"; try { runtimeKeyPair = new ECKeyGenerator(Curve.P_256).keyID(kid).generate(); @@ -71,6 +75,10 @@ public ParticipantRuntime(String moduleName, String runtimeName, String bpn, Map } catch (JOSEException e) { throw new RuntimeException(e); } + + if (beforeInitCallback != null) { + beforeInitCallback.beforeInit(this); + } } @Override diff --git a/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/runtimes/Runtimes.java b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/runtimes/Runtimes.java index 79aaf0057..a033ed718 100644 --- a/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/runtimes/Runtimes.java +++ b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/runtimes/Runtimes.java @@ -24,7 +24,11 @@ public interface Runtimes { static ParticipantRuntime memoryRuntime(String runtimeName, String bpn, Map properties) { - return new ParticipantRuntime(":edc-tests:runtime:runtime-memory", runtimeName, bpn, properties); + return memoryRuntime(runtimeName, bpn, properties, null); + } + + static ParticipantRuntime memoryRuntime(String runtimeName, String bpn, Map properties, BeforeInitCallback callback) { + return new ParticipantRuntime(":edc-tests:runtime:runtime-memory", runtimeName, bpn, properties, callback); } static PgParticipantRuntime pgRuntime(String runtimeName, String bpn, Map properties) { diff --git a/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/iatp/runtime/IatpParticipantRuntime.java b/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/iatp/runtime/IatpParticipantRuntime.java index 6864fdc03..b94368687 100644 --- a/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/iatp/runtime/IatpParticipantRuntime.java +++ b/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/iatp/runtime/IatpParticipantRuntime.java @@ -26,6 +26,7 @@ import org.eclipse.edc.spi.security.Vault; import org.eclipse.edc.spi.system.ServiceExtension; import org.eclipse.edc.spi.system.ServiceExtensionContext; +import org.eclipse.tractusx.edc.spi.identity.mapper.BdrsClient; import org.eclipse.tractusx.edc.tests.runtimes.DataWiper; import org.junit.jupiter.api.extension.AfterAllCallback; import org.junit.jupiter.api.extension.BeforeAllCallback; @@ -46,6 +47,7 @@ public IatpParticipantRuntime(String moduleName, String runtimeName, Map s); } @Override diff --git a/edc-tests/edc-controlplane/transfer-tests/build.gradle.kts b/edc-tests/edc-controlplane/transfer-tests/build.gradle.kts index 42771ae1d..ddb7e022c 100644 --- a/edc-tests/edc-controlplane/transfer-tests/build.gradle.kts +++ b/edc-tests/edc-controlplane/transfer-tests/build.gradle.kts @@ -23,6 +23,7 @@ plugins { } dependencies { + testImplementation(project(":spi:bdrs-client-spi")) testImplementation(testFixtures(project(":edc-tests:edc-controlplane:fixtures"))) testImplementation(libs.netty.mockserver) diff --git a/edc-tests/edc-controlplane/transfer-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/TransferWithTokenRefreshTest.java b/edc-tests/edc-controlplane/transfer-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/TransferWithTokenRefreshTest.java index b213a982f..8867a59e9 100644 --- a/edc-tests/edc-controlplane/transfer-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/TransferWithTokenRefreshTest.java +++ b/edc-tests/edc-controlplane/transfer-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/TransferWithTokenRefreshTest.java @@ -23,6 +23,8 @@ import jakarta.json.JsonObject; import org.eclipse.edc.connector.controlplane.transfer.spi.types.TransferProcessStates; import org.eclipse.edc.junit.annotations.EndToEndTest; +import org.eclipse.edc.junit.extensions.EdcExtension; +import org.eclipse.tractusx.edc.spi.identity.mapper.BdrsClient; import org.eclipse.tractusx.edc.tests.participant.TransferParticipant; import org.eclipse.tractusx.edc.tests.runtimes.ParticipantRuntime; import org.junit.jupiter.api.AfterEach; @@ -77,7 +79,7 @@ public class TransferWithTokenRefreshTest { private static final Long VERY_SHORT_TOKEN_EXPIRY = 3L; @RegisterExtension - protected static final ParticipantRuntime PLATO_RUNTIME = memoryRuntime(PLATO.getName(), PLATO.getBpn(), forConfig(PLATO.getConfiguration())); + protected static final ParticipantRuntime PLATO_RUNTIME = memoryRuntime(PLATO.getName(), PLATO.getBpn(), forConfig(PLATO.getConfiguration()), TransferWithTokenRefreshTest::platoInitiator); protected ClientAndServer server; private String privateBackendUrl; @@ -89,6 +91,10 @@ private static Map forConfig(Map originalConfig) return newConfig; } + private static void platoInitiator(EdcExtension runtime) { + runtime.registerServiceMock(BdrsClient.class, (c) -> SOKRATES.getDid()); + } + @BeforeEach void setup() { server = ClientAndServer.startClientAndServer(MOCK_BACKEND_REMOTE_HOST, getFreePort()); diff --git a/settings.gradle.kts b/settings.gradle.kts index 907830c26..586fba727 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -24,6 +24,7 @@ include(":spi:callback-spi") include(":spi:edr-spi") include(":spi:core-spi") include(":spi:tokenrefresh-spi") +include(":spi:bdrs-client-spi") // core modules @@ -49,6 +50,7 @@ include(":edc-extensions:edr:edr-callback") include(":edc-extensions:cx-policy") include(":edc-extensions:iatp:tx-iatp") include(":edc-extensions:iatp:tx-iatp-sts-dim") +include(":edc-extensions:data-flow-properties-provider") // extensions - data plane include(":edc-extensions:dataplane:dataplane-proxy:edc-dataplane-proxy-consumer-api") diff --git a/spi/bdrs-client-spi/build.gradle.kts b/spi/bdrs-client-spi/build.gradle.kts new file mode 100644 index 000000000..63365c44c --- /dev/null +++ b/spi/bdrs-client-spi/build.gradle.kts @@ -0,0 +1,27 @@ +/******************************************************************************** + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +plugins { + `java-library` + `maven-publish` +} + +dependencies { + implementation(libs.edc.spi.core) +} diff --git a/spi/bdrs-client-spi/src/main/java/org/eclipse/tractusx/edc/spi/identity/mapper/BdrsClient.java b/spi/bdrs-client-spi/src/main/java/org/eclipse/tractusx/edc/spi/identity/mapper/BdrsClient.java new file mode 100644 index 000000000..70be4dfc9 --- /dev/null +++ b/spi/bdrs-client-spi/src/main/java/org/eclipse/tractusx/edc/spi/identity/mapper/BdrsClient.java @@ -0,0 +1,37 @@ +/******************************************************************************** + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +package org.eclipse.tractusx.edc.spi.identity.mapper; + +import org.eclipse.edc.runtime.metamodel.annotation.ExtensionPoint; + +/** + * Interface for resolving BPNs to DIDs + */ +@ExtensionPoint +public interface BdrsClient { + + /** + * Resolve the input BPN to a DID + * + * @param bpn The participantID (BPN) + * @return The resolved DID if found, null otherwise + */ + String resolve(String bpn); +} From fd5e27b41dfae365973e600d198b02bbfdb2fd04 Mon Sep 17 00:00:00 2001 From: Enrico Risa Date: Thu, 4 Apr 2024 10:37:05 +0200 Subject: [PATCH 095/100] feat: includes missing datasources (#1190) * feat: integrates missing datasources * chore: updates charts with datasources config * chore: fix after upstream changes --- DEPENDENCIES | 14 +++-- .../templates/deployment-controlplane.yaml | 9 +++ .../templates/deployment-dataplane.yaml | 33 +++++++++++ .../templates/deployment-controlplane.yaml | 10 ++++ .../templates/deployment-dataplane.yaml | 33 +++++++++++ core/core-utils/build.gradle.kts | 1 + .../credentials/CredentialTypePredicate.java | 3 +- .../build.gradle.kts | 2 +- .../build.gradle.kts | 2 +- .../build.gradle.kts | 4 ++ .../build.gradle.kts | 4 ++ edc-extensions/cx-policy/build.gradle.kts | 1 + ...ctDynamicCredentialConstraintFunction.java | 2 +- ...ismantlerCredentialConstraintFunction.java | 2 +- ...AgreementCredentialConstraintFunction.java | 2 +- .../edc/policy/cx/CredentialFunctions.java | 6 +- ...meworkAgreementConstraintFunctionTest.java | 2 +- .../iatp/identity/IatpIdentityExtractor.java | 2 +- .../identity/IatpIdentityExtractorTest.java | 6 +- .../control-plane-migration}/README.md | 0 .../control-plane-migration/build.gradle.kts | 41 ++++++++++++++ .../AssetPostgresqlMigrationExtension.java | 0 ...sinessGroupPostgresMigrationExtension.java | 0 ...efinitionPostgresqlMigrationExtension.java | 0 ...gotiationPostgresqlMigrationExtension.java | 0 .../EdrIndexPostgresqlMigrationExtension.java | 34 ++++++++++++ ...cyMonitorPostgresqlMigrationExtension.java | 0 .../PolicyPostgresqlMigrationExtension.java | 0 ...erProcessPostgresqlMigrationExtension.java | 0 ...rg.eclipse.edc.spi.system.ServiceExtension | 1 + .../V0_0_1__Init_Asset_Database_Schema.sql | 0 .../asset/V0_0_2__Milestone5_Update.sql | 0 .../V0_0_3__Snapshot_20220815_Update.sql | 0 ...Alter_Asset_Property_add_IsPrivateFlag.sql | 0 ..._5__Alter_Asset_Internalize_Properties.sql | 0 ...0_0_6__Transform_Property_Array_To_Map.sql | 0 .../bpn/V0_0_1__Init_BusinessGroup_Schema.sql | 0 ...nit_ContractDefinition_Database_Schema.sql | 0 ...ition_Access_Contract_Policy_Id_Schema.sql | 0 .../V0_0_3__Snapshot_20220815_Update.sql | 0 .../V0_0_4__Snapshot_20221201_Update.sql | 0 ...ter_ContractDefinition_Remove_validity.sql | 0 ...tDefinition_Rename_selector_expression.sql | 0 ...tractDefinition_Add_Private_Properties.sql | 0 ...Definition_Switch_Assets_Selector_Json.sql | 0 ...it_ContractNegotiation_Database_Schema.sql | 0 ...egotation_Contract_Agreement_Id_Schema.sql | 0 .../V0_0_3__Milestone5_Update.sql | 0 .../V0_0_4__Snapshot_20220815_Update.sql | 0 ...lter_ContractNegotiation_Add_Callbacks.sql | 0 ..._Alter_ContractNegotiation_Change_Type.sql | 0 ...er_ContractNegotiation_AddPendingField.sql | 0 ...ctNegotiation_AddProtocolMessagesField.sql | 0 .../V0_0_1__Init_EdrIndex_Database_Schema.sql | 31 +++++++++++ ..._1__Init_PolicyMonitor_Database_Schema.sql | 0 .../V0_0_1__Init_Policy_Database_Schema.sql | 0 .../policy/V0_0_2__Milestone5_Update.sql | 0 .../V0_0_3__Snapshot_20220815_Update.sql | 0 .../policy/V0_0_4__Add_Private_Properties.sql | 0 ...Process_Rename_transfer_process_column.sql | 0 ..._Alter_TransferProcess_AddPendingField.sql | 0 ..._Alter_TransferProcess_AddTransferType.sql | 0 ...er_TransferProcess_AddProtocolMessages.sql | 0 ...__Alter_TransferProcess_AddDataPlaneId.sql | 0 ...lter_TransferProcess_InlineDataAddress.sql | 0 ...__Init_TransferProcess_Database_Schema.sql | 0 ..._Alter_TransferProcess_Add_DataAddress.sql | 0 .../V0_0_3__Alter_Rename_Id.sql | 0 .../V0_0_4__Milestone5_Update.sql | 0 .../V0_0_5__Snapshot_20220815_Update.sql | 0 .../V0_0_6__Snapshot_20230109_Update.sql | 0 .../V0_0_7__Default_Value_For_Properties.sql | 0 ...8__Alter_TransferProcess_Add_Callbacks.sql | 0 ...er_TransferProcess_Remove_Transfertype.sql | 0 ...AssetPostgresqlMigrationExtensionTest.java | 0 .../migrations/data-plane-migration/README.md | 14 +++++ .../data-plane-migration/build.gradle.kts | 41 ++++++++++++++ ...TokenDataPostgresqlMigrationExtension.java | 29 ++++++++++ ...DataPlanePostgresqlMigrationExtension.java | 30 ++++++++++ ...rg.eclipse.edc.spi.system.ServiceExtension | 21 +++++++ ...__Init_AccessTokenData_Database_Schema.sql | 28 ++++++++++ ...V0_0_1__Init_Dataplane_Database_Schema.sql | 55 +++++++++++++++++++ .../build.gradle.kts | 0 .../AbstractPostgresqlMigrationExtension.java | 6 +- .../postgresql/migration/FlywayManager.java | 0 .../tests/runtimes/PgParticipantRuntime.java | 33 +++++------ .../iatp/harness/DataspaceIssuer.java | 10 ++-- .../runtime-postgresql/build.gradle.kts | 3 +- gradle/libs.versions.toml | 6 +- settings.gradle.kts | 4 +- 90 files changed, 481 insertions(+), 44 deletions(-) rename edc-extensions/{postgresql-migration => migrations/control-plane-migration}/README.md (100%) create mode 100644 edc-extensions/migrations/control-plane-migration/build.gradle.kts rename edc-extensions/{postgresql-migration => migrations/control-plane-migration}/src/main/java/org/eclipse/tractusx/edc/postgresql/migration/AssetPostgresqlMigrationExtension.java (100%) rename edc-extensions/{postgresql-migration => migrations/control-plane-migration}/src/main/java/org/eclipse/tractusx/edc/postgresql/migration/BusinessGroupPostgresMigrationExtension.java (100%) rename edc-extensions/{postgresql-migration => migrations/control-plane-migration}/src/main/java/org/eclipse/tractusx/edc/postgresql/migration/ContractDefinitionPostgresqlMigrationExtension.java (100%) rename edc-extensions/{postgresql-migration => migrations/control-plane-migration}/src/main/java/org/eclipse/tractusx/edc/postgresql/migration/ContractNegotiationPostgresqlMigrationExtension.java (100%) create mode 100644 edc-extensions/migrations/control-plane-migration/src/main/java/org/eclipse/tractusx/edc/postgresql/migration/EdrIndexPostgresqlMigrationExtension.java rename edc-extensions/{postgresql-migration => migrations/control-plane-migration}/src/main/java/org/eclipse/tractusx/edc/postgresql/migration/PolicyMonitorPostgresqlMigrationExtension.java (100%) rename edc-extensions/{postgresql-migration => migrations/control-plane-migration}/src/main/java/org/eclipse/tractusx/edc/postgresql/migration/PolicyPostgresqlMigrationExtension.java (100%) rename edc-extensions/{postgresql-migration => migrations/control-plane-migration}/src/main/java/org/eclipse/tractusx/edc/postgresql/migration/TransferProcessPostgresqlMigrationExtension.java (100%) rename edc-extensions/{postgresql-migration => migrations/control-plane-migration}/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension (95%) rename edc-extensions/{postgresql-migration => migrations/control-plane-migration}/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/asset/V0_0_1__Init_Asset_Database_Schema.sql (100%) rename edc-extensions/{postgresql-migration => migrations/control-plane-migration}/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/asset/V0_0_2__Milestone5_Update.sql (100%) rename edc-extensions/{postgresql-migration => migrations/control-plane-migration}/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/asset/V0_0_3__Snapshot_20220815_Update.sql (100%) rename edc-extensions/{postgresql-migration => migrations/control-plane-migration}/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/asset/V0_0_4__Alter_Asset_Property_add_IsPrivateFlag.sql (100%) rename edc-extensions/{postgresql-migration => migrations/control-plane-migration}/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/asset/V0_0_5__Alter_Asset_Internalize_Properties.sql (100%) rename edc-extensions/{postgresql-migration => migrations/control-plane-migration}/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/asset/V0_0_6__Transform_Property_Array_To_Map.sql (100%) rename edc-extensions/{postgresql-migration => migrations/control-plane-migration}/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/bpn/V0_0_1__Init_BusinessGroup_Schema.sql (100%) rename edc-extensions/{postgresql-migration => migrations/control-plane-migration}/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/contractdefinition/V0_0_1__Init_ContractDefinition_Database_Schema.sql (100%) rename edc-extensions/{postgresql-migration => migrations/control-plane-migration}/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/contractdefinition/V0_0_2__Alter_ContractDefinition_Access_Contract_Policy_Id_Schema.sql (100%) rename edc-extensions/{postgresql-migration => migrations/control-plane-migration}/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/contractdefinition/V0_0_3__Snapshot_20220815_Update.sql (100%) rename edc-extensions/{postgresql-migration => migrations/control-plane-migration}/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/contractdefinition/V0_0_4__Snapshot_20221201_Update.sql (100%) rename edc-extensions/{postgresql-migration => migrations/control-plane-migration}/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/contractdefinition/V0_0_5__Alter_ContractDefinition_Remove_validity.sql (100%) rename edc-extensions/{postgresql-migration => migrations/control-plane-migration}/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/contractdefinition/V0_0_6__Alter_ContractDefinition_Rename_selector_expression.sql (100%) rename edc-extensions/{postgresql-migration => migrations/control-plane-migration}/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/contractdefinition/V0_0_7__Alter_ContractDefinition_Add_Private_Properties.sql (100%) rename edc-extensions/{postgresql-migration => migrations/control-plane-migration}/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/contractdefinition/V0_0_8__Alter_ContractDefinition_Switch_Assets_Selector_Json.sql (100%) rename edc-extensions/{postgresql-migration => migrations/control-plane-migration}/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/contractnegotiation/V0_0_1__Init_ContractNegotiation_Database_Schema.sql (100%) rename edc-extensions/{postgresql-migration => migrations/control-plane-migration}/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/contractnegotiation/V0_0_2__Alter_ContractNegotation_Contract_Agreement_Id_Schema.sql (100%) rename edc-extensions/{postgresql-migration => migrations/control-plane-migration}/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/contractnegotiation/V0_0_3__Milestone5_Update.sql (100%) rename edc-extensions/{postgresql-migration => migrations/control-plane-migration}/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/contractnegotiation/V0_0_4__Snapshot_20220815_Update.sql (100%) rename edc-extensions/{postgresql-migration => migrations/control-plane-migration}/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/contractnegotiation/V0_0_5__Alter_ContractNegotiation_Add_Callbacks.sql (100%) rename edc-extensions/{postgresql-migration => migrations/control-plane-migration}/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/contractnegotiation/V0_0_6__Alter_ContractNegotiation_Change_Type.sql (100%) rename edc-extensions/{postgresql-migration => migrations/control-plane-migration}/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/contractnegotiation/V0_0_7__Alter_ContractNegotiation_AddPendingField.sql (100%) rename edc-extensions/{postgresql-migration => migrations/control-plane-migration}/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/contractnegotiation/V0_0_8__Alter_ContractNegotiation_AddProtocolMessagesField.sql (100%) create mode 100644 edc-extensions/migrations/control-plane-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/edr-index/V0_0_1__Init_EdrIndex_Database_Schema.sql rename edc-extensions/{postgresql-migration => migrations/control-plane-migration}/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/policy-monitor/V0_0_1__Init_PolicyMonitor_Database_Schema.sql (100%) rename edc-extensions/{postgresql-migration => migrations/control-plane-migration}/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/policy/V0_0_1__Init_Policy_Database_Schema.sql (100%) rename edc-extensions/{postgresql-migration => migrations/control-plane-migration}/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/policy/V0_0_2__Milestone5_Update.sql (100%) rename edc-extensions/{postgresql-migration => migrations/control-plane-migration}/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/policy/V0_0_3__Snapshot_20220815_Update.sql (100%) rename edc-extensions/{postgresql-migration => migrations/control-plane-migration}/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/policy/V0_0_4__Add_Private_Properties.sql (100%) rename edc-extensions/{postgresql-migration => migrations/control-plane-migration}/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/transferprocess/V0_0_10__Alter_TransferProcess_Rename_transfer_process_column.sql (100%) rename edc-extensions/{postgresql-migration => migrations/control-plane-migration}/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/transferprocess/V0_0_11__Alter_TransferProcess_AddPendingField.sql (100%) rename edc-extensions/{postgresql-migration => migrations/control-plane-migration}/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/transferprocess/V0_0_12__Alter_TransferProcess_AddTransferType.sql (100%) rename edc-extensions/{postgresql-migration => migrations/control-plane-migration}/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/transferprocess/V0_0_13__Alter_TransferProcess_AddProtocolMessages.sql (100%) rename edc-extensions/{postgresql-migration => migrations/control-plane-migration}/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/transferprocess/V0_0_14__Alter_TransferProcess_AddDataPlaneId.sql (100%) rename edc-extensions/{postgresql-migration => migrations/control-plane-migration}/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/transferprocess/V0_0_15__Alter_TransferProcess_InlineDataAddress.sql (100%) rename edc-extensions/{postgresql-migration => migrations/control-plane-migration}/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/transferprocess/V0_0_1__Init_TransferProcess_Database_Schema.sql (100%) rename edc-extensions/{postgresql-migration => migrations/control-plane-migration}/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/transferprocess/V0_0_2__Alter_TransferProcess_Add_DataAddress.sql (100%) rename edc-extensions/{postgresql-migration => migrations/control-plane-migration}/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/transferprocess/V0_0_3__Alter_Rename_Id.sql (100%) rename edc-extensions/{postgresql-migration => migrations/control-plane-migration}/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/transferprocess/V0_0_4__Milestone5_Update.sql (100%) rename edc-extensions/{postgresql-migration => migrations/control-plane-migration}/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/transferprocess/V0_0_5__Snapshot_20220815_Update.sql (100%) rename edc-extensions/{postgresql-migration => migrations/control-plane-migration}/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/transferprocess/V0_0_6__Snapshot_20230109_Update.sql (100%) rename edc-extensions/{postgresql-migration => migrations/control-plane-migration}/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/transferprocess/V0_0_7__Default_Value_For_Properties.sql (100%) rename edc-extensions/{postgresql-migration => migrations/control-plane-migration}/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/transferprocess/V0_0_8__Alter_TransferProcess_Add_Callbacks.sql (100%) rename edc-extensions/{postgresql-migration => migrations/control-plane-migration}/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/transferprocess/V0_0_9__Alter_TransferProcess_Remove_Transfertype.sql (100%) rename edc-extensions/{postgresql-migration => migrations/control-plane-migration}/src/test/java/org/eclipse/tractusx/edc/postgresql/migration/AssetPostgresqlMigrationExtensionTest.java (100%) create mode 100644 edc-extensions/migrations/data-plane-migration/README.md create mode 100644 edc-extensions/migrations/data-plane-migration/build.gradle.kts create mode 100644 edc-extensions/migrations/data-plane-migration/src/main/java/org/eclipse/tractusx/edc/postgresql/migration/AccessTokenDataPostgresqlMigrationExtension.java create mode 100644 edc-extensions/migrations/data-plane-migration/src/main/java/org/eclipse/tractusx/edc/postgresql/migration/DataPlanePostgresqlMigrationExtension.java create mode 100644 edc-extensions/migrations/data-plane-migration/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension create mode 100644 edc-extensions/migrations/data-plane-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/accesstokendata/V0_0_1__Init_AccessTokenData_Database_Schema.sql create mode 100644 edc-extensions/migrations/data-plane-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/dataplane/V0_0_1__Init_Dataplane_Database_Schema.sql rename edc-extensions/{postgresql-migration => migrations/postgresql-migration-lib}/build.gradle.kts (100%) rename edc-extensions/{postgresql-migration => migrations/postgresql-migration-lib}/src/main/java/org/eclipse/tractusx/edc/postgresql/migration/AbstractPostgresqlMigrationExtension.java (95%) rename edc-extensions/{postgresql-migration => migrations/postgresql-migration-lib}/src/main/java/org/eclipse/tractusx/edc/postgresql/migration/FlywayManager.java (100%) diff --git a/DEPENDENCIES b/DEPENDENCIES index 6adb1ad26..3968ca7b4 100644 --- a/DEPENDENCIES +++ b/DEPENDENCIES @@ -333,6 +333,7 @@ maven/mavencentral/org.codehaus.plexus/plexus-utils/3.1.1, , approved, CQ16492 maven/mavencentral/org.codehaus.plexus/plexus-utils/3.3.0, , approved, CQ21066 maven/mavencentral/org.codehaus.woodstox/stax2-api/4.2.2, BSD-2-Clause, approved, #2670 maven/mavencentral/org.eclipse.angus/angus-activation/1.0.0, EPL-2.0 OR GPL-2.0-only with Classpath-exception-2.0, approved, ee4j.angus +maven/mavencentral/org.eclipse.edc/accesstokendata-store-sql/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/api-core/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/api-observability/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/asset-api/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc @@ -392,25 +393,27 @@ maven/mavencentral/org.eclipse.edc/data-plane-signaling-api/0.6.1-SNAPSHOT, Apac maven/mavencentral/org.eclipse.edc/data-plane-signaling-client/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/data-plane-signaling-transform/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/data-plane-spi/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-store-sql/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/data-plane-util/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-api-configuration/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-catalog-api/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-catalog-http-api/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/dsp-catalog-http-dispatcher/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/dsp-catalog-transform/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/dsp-catalog/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-http-api-configuration/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/dsp-http-core/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/dsp-http-spi/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-negotiation-api/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-negotiation-http-api/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/dsp-negotiation-http-dispatcher/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/dsp-negotiation-transform/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/dsp-negotiation/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/dsp-spi/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-transfer-process-api/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-transfer-process-http-api/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/dsp-transfer-process-http-dispatcher/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/dsp-transfer-process-transform/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/dsp-transfer-process/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-version-api/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-version-http-api/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/dsp/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/edr-index-sql/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/edr-store-core/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/edr-store-receiver/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/edr-store-spi/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc @@ -504,6 +507,7 @@ maven/mavencentral/org.eclipse.edc/validator-lib/0.6.1-SNAPSHOT, Apache-2.0, app maven/mavencentral/org.eclipse.edc/validator-spi/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/vault-azure/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/vault-hashicorp/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/verifiable-credentials-spi/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/web-spi/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.jetty.toolchain/jetty-jakarta-servlet-api/5.0.2, EPL-2.0 OR Apache-2.0, approved, rt.jetty maven/mavencentral/org.eclipse.jetty.toolchain/jetty-jakarta-websocket-api/2.0.0, EPL-2.0 OR Apache-2.0, approved, rt.jetty diff --git a/charts/tractusx-connector-azure-vault/templates/deployment-controlplane.yaml b/charts/tractusx-connector-azure-vault/templates/deployment-controlplane.yaml index 98cf57bf6..61510d87d 100644 --- a/charts/tractusx-connector-azure-vault/templates/deployment-controlplane.yaml +++ b/charts/tractusx-connector-azure-vault/templates/deployment-controlplane.yaml @@ -258,6 +258,15 @@ spec: - name: "EDC_DATASOURCE_BPN_URL" value: {{ tpl .Values.postgresql.jdbcUrl . | quote }} + # see extension https://github.com/eclipse-edc/Connector/tree/main/extensions/common/store/sql/edr-index-sql + - name: "EDC_DATASOURCE_EDR_NAME" + value: "edr" + - name: "EDC_DATASOURCE_EDR_USER" + value: {{ .Values.postgresql.auth.username | required ".Values.postgresql.auth.username is required" | quote }} + - name: "EDC_DATASOURCE_EDR_PASSWORD" + value: {{ .Values.postgresql.auth.password | required ".Values.postgresql.auth.password is required" | quote }} + - name: "EDC_DATASOURCE_EDR_URL" + value: {{ tpl .Values.postgresql.jdbcUrl . | quote }} ############################# ## IATP / STS / DIM CONFIG ## diff --git a/charts/tractusx-connector-azure-vault/templates/deployment-dataplane.yaml b/charts/tractusx-connector-azure-vault/templates/deployment-dataplane.yaml index 58984c928..95a332858 100644 --- a/charts/tractusx-connector-azure-vault/templates/deployment-dataplane.yaml +++ b/charts/tractusx-connector-azure-vault/templates/deployment-dataplane.yaml @@ -217,6 +217,39 @@ spec: - name: "EDC_IAM_STS_DIM_URL" value: {{ .Values.iatp.sts.dim.url | required ".Values.iatp.sts.dim.url is required" | quote}} + ################ + ## POSTGRESQL ## + ################ + + # see extension https://github.com/eclipse-edc/Connector/tree/main/extensions/common/store/sql/edr-index-sql + - name: "EDC_DATASOURCE_EDR_NAME" + value: "edr" + - name: "EDC_DATASOURCE_EDR_USER" + value: {{ .Values.postgresql.auth.username | required ".Values.postgresql.auth.username is required" | quote }} + - name: "EDC_DATASOURCE_EDR_PASSWORD" + value: {{ .Values.postgresql.auth.password | required ".Values.postgresql.auth.password is required" | quote }} + - name: "EDC_DATASOURCE_EDR_URL" + value: {{ tpl .Values.postgresql.jdbcUrl . | quote }} + + # see extension https://github.com/eclipse-edc/Connector/tree/main/extensions/data-plane/store/sql/data-plane-store-sql + - name: "EDC_DATASOURCE_DATAPLANE_NAME" + value: "edr" + - name: "EDC_DATASOURCE_DATAPLANE_USER" + value: {{ .Values.postgresql.auth.username | required ".Values.postgresql.auth.username is required" | quote }} + - name: "EDC_DATASOURCE_DATAPLANE_PASSWORD" + value: {{ .Values.postgresql.auth.password | required ".Values.postgresql.auth.password is required" | quote }} + - name: "EDC_DATASOURCE_DATAPLANE_URL" + value: {{ tpl .Values.postgresql.jdbcUrl . | quote }} + + # see extension https://github.com/eclipse-edc/Connector/tree/main/extensions/data-plane/store/sql/accesstokendata-store-sql + - name: "EDC_DATASOURCE_ACCESSTOKENDATA_NAME" + value: "edr" + - name: "EDC_DATASOURCE_ACCESSTOKENDATA_USER" + value: {{ .Values.postgresql.auth.username | required ".Values.postgresql.auth.username is required" | quote }} + - name: "EDC_DATASOURCE_ACCESSTOKENDATA_PASSWORD" + value: {{ .Values.postgresql.auth.password | required ".Values.postgresql.auth.password is required" | quote }} + - name: "EDC_DATASOURCE_ACCESSTOKENDATA_URL" + value: {{ tpl .Values.postgresql.jdbcUrl . | quote }} ######################### ## DATA PLANE PUBLIC API diff --git a/charts/tractusx-connector/templates/deployment-controlplane.yaml b/charts/tractusx-connector/templates/deployment-controlplane.yaml index 4f3196d22..f41a2a633 100644 --- a/charts/tractusx-connector/templates/deployment-controlplane.yaml +++ b/charts/tractusx-connector/templates/deployment-controlplane.yaml @@ -259,6 +259,16 @@ spec: value: {{ tpl .Values.postgresql.jdbcUrl . | quote }} + # see extension https://github.com/eclipse-edc/Connector/tree/main/extensions/common/store/sql/edr-index-sql + - name: "EDC_DATASOURCE_EDR_NAME" + value: "edr" + - name: "EDC_DATASOURCE_EDR_USER" + value: {{ .Values.postgresql.auth.username | required ".Values.postgresql.auth.username is required" | quote }} + - name: "EDC_DATASOURCE_EDR_PASSWORD" + value: {{ .Values.postgresql.auth.password | required ".Values.postgresql.auth.password is required" | quote }} + - name: "EDC_DATASOURCE_EDR_URL" + value: {{ tpl .Values.postgresql.jdbcUrl . | quote }} + ############################# ## IATP / STS / DIM CONFIG ## ############################# diff --git a/charts/tractusx-connector/templates/deployment-dataplane.yaml b/charts/tractusx-connector/templates/deployment-dataplane.yaml index c02094659..c22138a97 100644 --- a/charts/tractusx-connector/templates/deployment-dataplane.yaml +++ b/charts/tractusx-connector/templates/deployment-dataplane.yaml @@ -216,6 +216,39 @@ spec: - name: "EDC_IAM_STS_DIM_URL" value: {{ .Values.iatp.sts.dim.url | required ".Values.iatp.sts.dim.url is required" | quote}} + ################ + ## POSTGRESQL ## + ################ + + # see extension https://github.com/eclipse-edc/Connector/tree/main/extensions/common/store/sql/edr-index-sql + - name: "EDC_DATASOURCE_EDR_NAME" + value: "edr" + - name: "EDC_DATASOURCE_EDR_USER" + value: {{ .Values.postgresql.auth.username | required ".Values.postgresql.auth.username is required" | quote }} + - name: "EDC_DATASOURCE_EDR_PASSWORD" + value: {{ .Values.postgresql.auth.password | required ".Values.postgresql.auth.password is required" | quote }} + - name: "EDC_DATASOURCE_EDR_URL" + value: {{ tpl .Values.postgresql.jdbcUrl . | quote }} + + # see extension https://github.com/eclipse-edc/Connector/tree/main/extensions/data-plane/store/sql/data-plane-store-sql + - name: "EDC_DATASOURCE_DATAPLANE_NAME" + value: "edr" + - name: "EDC_DATASOURCE_DATAPLANE_USER" + value: {{ .Values.postgresql.auth.username | required ".Values.postgresql.auth.username is required" | quote }} + - name: "EDC_DATASOURCE_DATAPLANE_PASSWORD" + value: {{ .Values.postgresql.auth.password | required ".Values.postgresql.auth.password is required" | quote }} + - name: "EDC_DATASOURCE_DATAPLANE_URL" + value: {{ tpl .Values.postgresql.jdbcUrl . | quote }} + + # see extension https://github.com/eclipse-edc/Connector/tree/main/extensions/data-plane/store/sql/accesstokendata-store-sql + - name: "EDC_DATASOURCE_ACCESSTOKENDATA_NAME" + value: "edr" + - name: "EDC_DATASOURCE_ACCESSTOKENDATA_USER" + value: {{ .Values.postgresql.auth.username | required ".Values.postgresql.auth.username is required" | quote }} + - name: "EDC_DATASOURCE_ACCESSTOKENDATA_PASSWORD" + value: {{ .Values.postgresql.auth.password | required ".Values.postgresql.auth.password is required" | quote }} + - name: "EDC_DATASOURCE_ACCESSTOKENDATA_URL" + value: {{ tpl .Values.postgresql.jdbcUrl . | quote }} ######################### ## DATA PLANE PUBLIC API diff --git a/core/core-utils/build.gradle.kts b/core/core-utils/build.gradle.kts index 9eb6a95d7..5a8a90ae2 100644 --- a/core/core-utils/build.gradle.kts +++ b/core/core-utils/build.gradle.kts @@ -24,4 +24,5 @@ plugins { dependencies { implementation(libs.edc.spi.core) implementation(libs.edc.spi.identitytrust) + implementation(libs.edc.spi.vc) } diff --git a/core/core-utils/src/main/java/org/eclipse/tractusx/edc/core/utils/credentials/CredentialTypePredicate.java b/core/core-utils/src/main/java/org/eclipse/tractusx/edc/core/utils/credentials/CredentialTypePredicate.java index 91ad8a92a..5523299f5 100644 --- a/core/core-utils/src/main/java/org/eclipse/tractusx/edc/core/utils/credentials/CredentialTypePredicate.java +++ b/core/core-utils/src/main/java/org/eclipse/tractusx/edc/core/utils/credentials/CredentialTypePredicate.java @@ -19,7 +19,8 @@ package org.eclipse.tractusx.edc.core.utils.credentials; -import org.eclipse.edc.iam.identitytrust.spi.model.VerifiableCredential; + +import org.eclipse.edc.iam.verifiablecredentials.spi.model.VerifiableCredential; import java.util.function.Predicate; diff --git a/edc-controlplane/edc-controlplane-postgresql-azure-vault/build.gradle.kts b/edc-controlplane/edc-controlplane-postgresql-azure-vault/build.gradle.kts index 93a35e3ae..0d86a03a9 100644 --- a/edc-controlplane/edc-controlplane-postgresql-azure-vault/build.gradle.kts +++ b/edc-controlplane/edc-controlplane-postgresql-azure-vault/build.gradle.kts @@ -28,7 +28,7 @@ plugins { dependencies { runtimeOnly(project(":edc-controlplane:edc-controlplane-base")) - runtimeOnly(project(":edc-extensions:postgresql-migration")) + runtimeOnly(project(":edc-extensions:migrations::control-plane-migration")) runtimeOnly(project(":edc-extensions:bpn-validation:business-partner-store-sql")) runtimeOnly(libs.edc.azure.vault) runtimeOnly(libs.bundles.edc.sqlstores) diff --git a/edc-controlplane/edc-controlplane-postgresql-hashicorp-vault/build.gradle.kts b/edc-controlplane/edc-controlplane-postgresql-hashicorp-vault/build.gradle.kts index c5f91e916..778df1b0a 100644 --- a/edc-controlplane/edc-controlplane-postgresql-hashicorp-vault/build.gradle.kts +++ b/edc-controlplane/edc-controlplane-postgresql-hashicorp-vault/build.gradle.kts @@ -28,7 +28,7 @@ plugins { dependencies { runtimeOnly(project(":edc-controlplane:edc-controlplane-base")) - runtimeOnly(project(":edc-extensions:postgresql-migration")) + runtimeOnly(project(":edc-extensions:migrations::control-plane-migration")) runtimeOnly(project(":edc-extensions:bpn-validation:business-partner-store-sql")) runtimeOnly(libs.edc.vault.hashicorp) runtimeOnly(libs.bundles.edc.sqlstores) diff --git a/edc-dataplane/edc-dataplane-azure-vault/build.gradle.kts b/edc-dataplane/edc-dataplane-azure-vault/build.gradle.kts index 627939029..c9bb8619f 100644 --- a/edc-dataplane/edc-dataplane-azure-vault/build.gradle.kts +++ b/edc-dataplane/edc-dataplane-azure-vault/build.gradle.kts @@ -25,6 +25,7 @@ plugins { dependencies { implementation(project(":edc-dataplane:edc-dataplane-base")) + runtimeOnly(project(":edc-extensions:migrations::data-plane-migration")) implementation(libs.edc.azure.vault) constraints { implementation("net.minidev:json-smart:2.5.0") { @@ -35,6 +36,9 @@ dependencies { implementation("com.azure:azure-security-keyvault-secrets:4.8.1") runtimeOnly(libs.edc.transaction.local) runtimeOnly(libs.edc.sql.pool) + runtimeOnly(libs.edc.sql.accesstokendata) + runtimeOnly(libs.edc.sql.edrindex) + runtimeOnly(libs.edc.sql.dataplane) runtimeOnly(libs.postgres) } diff --git a/edc-dataplane/edc-dataplane-hashicorp-vault/build.gradle.kts b/edc-dataplane/edc-dataplane-hashicorp-vault/build.gradle.kts index 5deeb1698..16a144279 100644 --- a/edc-dataplane/edc-dataplane-hashicorp-vault/build.gradle.kts +++ b/edc-dataplane/edc-dataplane-hashicorp-vault/build.gradle.kts @@ -25,9 +25,13 @@ plugins { dependencies { implementation(project(":edc-dataplane:edc-dataplane-base")) + runtimeOnly(project(":edc-extensions:migrations::data-plane-migration")) runtimeOnly(libs.edc.vault.hashicorp) runtimeOnly(libs.edc.transaction.local) runtimeOnly(libs.edc.sql.pool) + runtimeOnly(libs.edc.sql.accesstokendata) + runtimeOnly(libs.edc.sql.edrindex) + runtimeOnly(libs.edc.sql.dataplane) runtimeOnly(libs.postgres) } diff --git a/edc-extensions/cx-policy/build.gradle.kts b/edc-extensions/cx-policy/build.gradle.kts index 15a293e37..b8d56b1ec 100644 --- a/edc-extensions/cx-policy/build.gradle.kts +++ b/edc-extensions/cx-policy/build.gradle.kts @@ -27,6 +27,7 @@ dependencies { implementation(libs.edc.spi.policyengine) implementation(libs.jakartaJson) implementation(libs.edc.spi.identitytrust) + implementation(libs.edc.spi.vc) testImplementation(libs.jacksonJsonP) testImplementation(libs.titaniumJsonLd) } diff --git a/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/common/AbstractDynamicCredentialConstraintFunction.java b/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/common/AbstractDynamicCredentialConstraintFunction.java index e94ac99fb..91d08d29c 100644 --- a/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/common/AbstractDynamicCredentialConstraintFunction.java +++ b/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/common/AbstractDynamicCredentialConstraintFunction.java @@ -19,7 +19,7 @@ package org.eclipse.tractusx.edc.policy.cx.common; -import org.eclipse.edc.iam.identitytrust.spi.model.VerifiableCredential; +import org.eclipse.edc.iam.verifiablecredentials.spi.model.VerifiableCredential; import org.eclipse.edc.policy.engine.spi.DynamicAtomicConstraintFunction; import org.eclipse.edc.policy.engine.spi.PolicyContext; import org.eclipse.edc.policy.model.Operator; diff --git a/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/dismantler/DismantlerCredentialConstraintFunction.java b/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/dismantler/DismantlerCredentialConstraintFunction.java index 008879b71..12c319854 100644 --- a/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/dismantler/DismantlerCredentialConstraintFunction.java +++ b/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/dismantler/DismantlerCredentialConstraintFunction.java @@ -20,7 +20,7 @@ package org.eclipse.tractusx.edc.policy.cx.dismantler; import jakarta.json.JsonObject; -import org.eclipse.edc.iam.identitytrust.spi.model.VerifiableCredential; +import org.eclipse.edc.iam.verifiablecredentials.spi.model.VerifiableCredential; import org.eclipse.edc.policy.engine.spi.PolicyContext; import org.eclipse.edc.policy.model.Operator; import org.eclipse.edc.policy.model.Permission; diff --git a/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/framework/FrameworkAgreementCredentialConstraintFunction.java b/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/framework/FrameworkAgreementCredentialConstraintFunction.java index 2806f26bd..253e01b2c 100644 --- a/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/framework/FrameworkAgreementCredentialConstraintFunction.java +++ b/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/framework/FrameworkAgreementCredentialConstraintFunction.java @@ -19,7 +19,7 @@ package org.eclipse.tractusx.edc.policy.cx.framework; -import org.eclipse.edc.iam.identitytrust.spi.model.VerifiableCredential; +import org.eclipse.edc.iam.verifiablecredentials.spi.model.VerifiableCredential; import org.eclipse.edc.policy.engine.spi.PolicyContext; import org.eclipse.edc.policy.model.Operator; import org.eclipse.edc.policy.model.Permission; diff --git a/edc-extensions/cx-policy/src/test/java/org/eclipse/tractusx/edc/policy/cx/CredentialFunctions.java b/edc-extensions/cx-policy/src/test/java/org/eclipse/tractusx/edc/policy/cx/CredentialFunctions.java index d8551dd17..1aedea42d 100644 --- a/edc-extensions/cx-policy/src/test/java/org/eclipse/tractusx/edc/policy/cx/CredentialFunctions.java +++ b/edc-extensions/cx-policy/src/test/java/org/eclipse/tractusx/edc/policy/cx/CredentialFunctions.java @@ -20,9 +20,9 @@ package org.eclipse.tractusx.edc.policy.cx; -import org.eclipse.edc.iam.identitytrust.spi.model.CredentialSubject; -import org.eclipse.edc.iam.identitytrust.spi.model.Issuer; -import org.eclipse.edc.iam.identitytrust.spi.model.VerifiableCredential; +import org.eclipse.edc.iam.verifiablecredentials.spi.model.CredentialSubject; +import org.eclipse.edc.iam.verifiablecredentials.spi.model.Issuer; +import org.eclipse.edc.iam.verifiablecredentials.spi.model.VerifiableCredential; import java.time.Instant; import java.time.temporal.ChronoUnit; diff --git a/edc-extensions/cx-policy/src/test/java/org/eclipse/tractusx/edc/policy/cx/framework/FrameworkAgreementConstraintFunctionTest.java b/edc-extensions/cx-policy/src/test/java/org/eclipse/tractusx/edc/policy/cx/framework/FrameworkAgreementConstraintFunctionTest.java index bcda76c88..56ef833f1 100644 --- a/edc-extensions/cx-policy/src/test/java/org/eclipse/tractusx/edc/policy/cx/framework/FrameworkAgreementConstraintFunctionTest.java +++ b/edc-extensions/cx-policy/src/test/java/org/eclipse/tractusx/edc/policy/cx/framework/FrameworkAgreementConstraintFunctionTest.java @@ -19,7 +19,7 @@ package org.eclipse.tractusx.edc.policy.cx.framework; -import org.eclipse.edc.iam.identitytrust.spi.model.VerifiableCredential; +import org.eclipse.edc.iam.verifiablecredentials.spi.model.VerifiableCredential; import org.eclipse.edc.policy.engine.spi.PolicyContext; import org.eclipse.edc.policy.model.Operator; import org.eclipse.edc.policy.model.Permission; diff --git a/edc-extensions/iatp/tx-iatp/src/main/java/org/eclipse/tractusx/edc/iam/iatp/identity/IatpIdentityExtractor.java b/edc-extensions/iatp/tx-iatp/src/main/java/org/eclipse/tractusx/edc/iam/iatp/identity/IatpIdentityExtractor.java index ce43b9801..59754f3c1 100644 --- a/edc-extensions/iatp/tx-iatp/src/main/java/org/eclipse/tractusx/edc/iam/iatp/identity/IatpIdentityExtractor.java +++ b/edc-extensions/iatp/tx-iatp/src/main/java/org/eclipse/tractusx/edc/iam/iatp/identity/IatpIdentityExtractor.java @@ -19,7 +19,7 @@ package org.eclipse.tractusx.edc.iam.iatp.identity; -import org.eclipse.edc.iam.identitytrust.spi.model.VerifiableCredential; +import org.eclipse.edc.iam.verifiablecredentials.spi.model.VerifiableCredential; import org.eclipse.edc.spi.EdcException; import org.eclipse.edc.spi.agent.ParticipantAgentServiceExtension; import org.eclipse.edc.spi.iam.ClaimToken; diff --git a/edc-extensions/iatp/tx-iatp/src/test/java/org/eclipse/tractusx/edc/iam/iatp/identity/IatpIdentityExtractorTest.java b/edc-extensions/iatp/tx-iatp/src/test/java/org/eclipse/tractusx/edc/iam/iatp/identity/IatpIdentityExtractorTest.java index 8db77d945..5e2727dea 100644 --- a/edc-extensions/iatp/tx-iatp/src/test/java/org/eclipse/tractusx/edc/iam/iatp/identity/IatpIdentityExtractorTest.java +++ b/edc-extensions/iatp/tx-iatp/src/test/java/org/eclipse/tractusx/edc/iam/iatp/identity/IatpIdentityExtractorTest.java @@ -19,9 +19,9 @@ package org.eclipse.tractusx.edc.iam.iatp.identity; -import org.eclipse.edc.iam.identitytrust.spi.model.CredentialSubject; -import org.eclipse.edc.iam.identitytrust.spi.model.Issuer; -import org.eclipse.edc.iam.identitytrust.spi.model.VerifiableCredential; +import org.eclipse.edc.iam.verifiablecredentials.spi.model.CredentialSubject; +import org.eclipse.edc.iam.verifiablecredentials.spi.model.Issuer; +import org.eclipse.edc.iam.verifiablecredentials.spi.model.VerifiableCredential; import org.eclipse.edc.spi.EdcException; import org.eclipse.edc.spi.iam.ClaimToken; import org.junit.jupiter.api.Test; diff --git a/edc-extensions/postgresql-migration/README.md b/edc-extensions/migrations/control-plane-migration/README.md similarity index 100% rename from edc-extensions/postgresql-migration/README.md rename to edc-extensions/migrations/control-plane-migration/README.md diff --git a/edc-extensions/migrations/control-plane-migration/build.gradle.kts b/edc-extensions/migrations/control-plane-migration/build.gradle.kts new file mode 100644 index 000000000..2ff1aa7fa --- /dev/null +++ b/edc-extensions/migrations/control-plane-migration/build.gradle.kts @@ -0,0 +1,41 @@ +/******************************************************************************** + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +plugins { + `maven-publish` + `java-library` +} + +dependencies { + implementation(project(":edc-extensions:migrations:postgresql-migration-lib")) + implementation(libs.edc.spi.core) + implementation(libs.edc.junit) + implementation(libs.edc.spi.transaction.datasource) + implementation(libs.edc.sql.assetindex) + implementation(libs.edc.sql.core) + runtimeOnly(libs.postgres) + + implementation(libs.flyway.core) + // starting from flyway 10, they've moved to a more modular structure, + // so we need to add PG support explicitly + // https://documentation.red-gate.com/flyway/release-notes-and-older-versions/release-notes-for-flyway-engine + runtimeOnly(libs.flyway.database.postgres) + + testImplementation(testFixtures(libs.edc.sql.core)) +} diff --git a/edc-extensions/postgresql-migration/src/main/java/org/eclipse/tractusx/edc/postgresql/migration/AssetPostgresqlMigrationExtension.java b/edc-extensions/migrations/control-plane-migration/src/main/java/org/eclipse/tractusx/edc/postgresql/migration/AssetPostgresqlMigrationExtension.java similarity index 100% rename from edc-extensions/postgresql-migration/src/main/java/org/eclipse/tractusx/edc/postgresql/migration/AssetPostgresqlMigrationExtension.java rename to edc-extensions/migrations/control-plane-migration/src/main/java/org/eclipse/tractusx/edc/postgresql/migration/AssetPostgresqlMigrationExtension.java diff --git a/edc-extensions/postgresql-migration/src/main/java/org/eclipse/tractusx/edc/postgresql/migration/BusinessGroupPostgresMigrationExtension.java b/edc-extensions/migrations/control-plane-migration/src/main/java/org/eclipse/tractusx/edc/postgresql/migration/BusinessGroupPostgresMigrationExtension.java similarity index 100% rename from edc-extensions/postgresql-migration/src/main/java/org/eclipse/tractusx/edc/postgresql/migration/BusinessGroupPostgresMigrationExtension.java rename to edc-extensions/migrations/control-plane-migration/src/main/java/org/eclipse/tractusx/edc/postgresql/migration/BusinessGroupPostgresMigrationExtension.java diff --git a/edc-extensions/postgresql-migration/src/main/java/org/eclipse/tractusx/edc/postgresql/migration/ContractDefinitionPostgresqlMigrationExtension.java b/edc-extensions/migrations/control-plane-migration/src/main/java/org/eclipse/tractusx/edc/postgresql/migration/ContractDefinitionPostgresqlMigrationExtension.java similarity index 100% rename from edc-extensions/postgresql-migration/src/main/java/org/eclipse/tractusx/edc/postgresql/migration/ContractDefinitionPostgresqlMigrationExtension.java rename to edc-extensions/migrations/control-plane-migration/src/main/java/org/eclipse/tractusx/edc/postgresql/migration/ContractDefinitionPostgresqlMigrationExtension.java diff --git a/edc-extensions/postgresql-migration/src/main/java/org/eclipse/tractusx/edc/postgresql/migration/ContractNegotiationPostgresqlMigrationExtension.java b/edc-extensions/migrations/control-plane-migration/src/main/java/org/eclipse/tractusx/edc/postgresql/migration/ContractNegotiationPostgresqlMigrationExtension.java similarity index 100% rename from edc-extensions/postgresql-migration/src/main/java/org/eclipse/tractusx/edc/postgresql/migration/ContractNegotiationPostgresqlMigrationExtension.java rename to edc-extensions/migrations/control-plane-migration/src/main/java/org/eclipse/tractusx/edc/postgresql/migration/ContractNegotiationPostgresqlMigrationExtension.java diff --git a/edc-extensions/migrations/control-plane-migration/src/main/java/org/eclipse/tractusx/edc/postgresql/migration/EdrIndexPostgresqlMigrationExtension.java b/edc-extensions/migrations/control-plane-migration/src/main/java/org/eclipse/tractusx/edc/postgresql/migration/EdrIndexPostgresqlMigrationExtension.java new file mode 100644 index 000000000..1e16364ae --- /dev/null +++ b/edc-extensions/migrations/control-plane-migration/src/main/java/org/eclipse/tractusx/edc/postgresql/migration/EdrIndexPostgresqlMigrationExtension.java @@ -0,0 +1,34 @@ +/******************************************************************************** + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +package org.eclipse.tractusx.edc.postgresql.migration; + +public class EdrIndexPostgresqlMigrationExtension extends AbstractPostgresqlMigrationExtension { + private static final String NAME_SUBSYSTEM = "edr"; + + @Override + protected String getSubsystemName() { + return NAME_SUBSYSTEM; + } + + @Override + protected String getMigrationSubsystem() { + return NAME_SUBSYSTEM + "-index"; + } +} diff --git a/edc-extensions/postgresql-migration/src/main/java/org/eclipse/tractusx/edc/postgresql/migration/PolicyMonitorPostgresqlMigrationExtension.java b/edc-extensions/migrations/control-plane-migration/src/main/java/org/eclipse/tractusx/edc/postgresql/migration/PolicyMonitorPostgresqlMigrationExtension.java similarity index 100% rename from edc-extensions/postgresql-migration/src/main/java/org/eclipse/tractusx/edc/postgresql/migration/PolicyMonitorPostgresqlMigrationExtension.java rename to edc-extensions/migrations/control-plane-migration/src/main/java/org/eclipse/tractusx/edc/postgresql/migration/PolicyMonitorPostgresqlMigrationExtension.java diff --git a/edc-extensions/postgresql-migration/src/main/java/org/eclipse/tractusx/edc/postgresql/migration/PolicyPostgresqlMigrationExtension.java b/edc-extensions/migrations/control-plane-migration/src/main/java/org/eclipse/tractusx/edc/postgresql/migration/PolicyPostgresqlMigrationExtension.java similarity index 100% rename from edc-extensions/postgresql-migration/src/main/java/org/eclipse/tractusx/edc/postgresql/migration/PolicyPostgresqlMigrationExtension.java rename to edc-extensions/migrations/control-plane-migration/src/main/java/org/eclipse/tractusx/edc/postgresql/migration/PolicyPostgresqlMigrationExtension.java diff --git a/edc-extensions/postgresql-migration/src/main/java/org/eclipse/tractusx/edc/postgresql/migration/TransferProcessPostgresqlMigrationExtension.java b/edc-extensions/migrations/control-plane-migration/src/main/java/org/eclipse/tractusx/edc/postgresql/migration/TransferProcessPostgresqlMigrationExtension.java similarity index 100% rename from edc-extensions/postgresql-migration/src/main/java/org/eclipse/tractusx/edc/postgresql/migration/TransferProcessPostgresqlMigrationExtension.java rename to edc-extensions/migrations/control-plane-migration/src/main/java/org/eclipse/tractusx/edc/postgresql/migration/TransferProcessPostgresqlMigrationExtension.java diff --git a/edc-extensions/postgresql-migration/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension b/edc-extensions/migrations/control-plane-migration/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension similarity index 95% rename from edc-extensions/postgresql-migration/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension rename to edc-extensions/migrations/control-plane-migration/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension index 1d524a071..20a17d939 100644 --- a/edc-extensions/postgresql-migration/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension +++ b/edc-extensions/migrations/control-plane-migration/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension @@ -26,3 +26,4 @@ org.eclipse.tractusx.edc.postgresql.migration.PolicyPostgresqlMigrationExtension org.eclipse.tractusx.edc.postgresql.migration.PolicyMonitorPostgresqlMigrationExtension org.eclipse.tractusx.edc.postgresql.migration.TransferProcessPostgresqlMigrationExtension org.eclipse.tractusx.edc.postgresql.migration.BusinessGroupPostgresMigrationExtension +org.eclipse.tractusx.edc.postgresql.migration.EdrIndexPostgresqlMigrationExtension \ No newline at end of file diff --git a/edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/asset/V0_0_1__Init_Asset_Database_Schema.sql b/edc-extensions/migrations/control-plane-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/asset/V0_0_1__Init_Asset_Database_Schema.sql similarity index 100% rename from edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/asset/V0_0_1__Init_Asset_Database_Schema.sql rename to edc-extensions/migrations/control-plane-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/asset/V0_0_1__Init_Asset_Database_Schema.sql diff --git a/edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/asset/V0_0_2__Milestone5_Update.sql b/edc-extensions/migrations/control-plane-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/asset/V0_0_2__Milestone5_Update.sql similarity index 100% rename from edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/asset/V0_0_2__Milestone5_Update.sql rename to edc-extensions/migrations/control-plane-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/asset/V0_0_2__Milestone5_Update.sql diff --git a/edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/asset/V0_0_3__Snapshot_20220815_Update.sql b/edc-extensions/migrations/control-plane-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/asset/V0_0_3__Snapshot_20220815_Update.sql similarity index 100% rename from edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/asset/V0_0_3__Snapshot_20220815_Update.sql rename to edc-extensions/migrations/control-plane-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/asset/V0_0_3__Snapshot_20220815_Update.sql diff --git a/edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/asset/V0_0_4__Alter_Asset_Property_add_IsPrivateFlag.sql b/edc-extensions/migrations/control-plane-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/asset/V0_0_4__Alter_Asset_Property_add_IsPrivateFlag.sql similarity index 100% rename from edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/asset/V0_0_4__Alter_Asset_Property_add_IsPrivateFlag.sql rename to edc-extensions/migrations/control-plane-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/asset/V0_0_4__Alter_Asset_Property_add_IsPrivateFlag.sql diff --git a/edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/asset/V0_0_5__Alter_Asset_Internalize_Properties.sql b/edc-extensions/migrations/control-plane-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/asset/V0_0_5__Alter_Asset_Internalize_Properties.sql similarity index 100% rename from edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/asset/V0_0_5__Alter_Asset_Internalize_Properties.sql rename to edc-extensions/migrations/control-plane-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/asset/V0_0_5__Alter_Asset_Internalize_Properties.sql diff --git a/edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/asset/V0_0_6__Transform_Property_Array_To_Map.sql b/edc-extensions/migrations/control-plane-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/asset/V0_0_6__Transform_Property_Array_To_Map.sql similarity index 100% rename from edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/asset/V0_0_6__Transform_Property_Array_To_Map.sql rename to edc-extensions/migrations/control-plane-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/asset/V0_0_6__Transform_Property_Array_To_Map.sql diff --git a/edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/bpn/V0_0_1__Init_BusinessGroup_Schema.sql b/edc-extensions/migrations/control-plane-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/bpn/V0_0_1__Init_BusinessGroup_Schema.sql similarity index 100% rename from edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/bpn/V0_0_1__Init_BusinessGroup_Schema.sql rename to edc-extensions/migrations/control-plane-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/bpn/V0_0_1__Init_BusinessGroup_Schema.sql diff --git a/edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/contractdefinition/V0_0_1__Init_ContractDefinition_Database_Schema.sql b/edc-extensions/migrations/control-plane-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/contractdefinition/V0_0_1__Init_ContractDefinition_Database_Schema.sql similarity index 100% rename from edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/contractdefinition/V0_0_1__Init_ContractDefinition_Database_Schema.sql rename to edc-extensions/migrations/control-plane-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/contractdefinition/V0_0_1__Init_ContractDefinition_Database_Schema.sql diff --git a/edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/contractdefinition/V0_0_2__Alter_ContractDefinition_Access_Contract_Policy_Id_Schema.sql b/edc-extensions/migrations/control-plane-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/contractdefinition/V0_0_2__Alter_ContractDefinition_Access_Contract_Policy_Id_Schema.sql similarity index 100% rename from edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/contractdefinition/V0_0_2__Alter_ContractDefinition_Access_Contract_Policy_Id_Schema.sql rename to edc-extensions/migrations/control-plane-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/contractdefinition/V0_0_2__Alter_ContractDefinition_Access_Contract_Policy_Id_Schema.sql diff --git a/edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/contractdefinition/V0_0_3__Snapshot_20220815_Update.sql b/edc-extensions/migrations/control-plane-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/contractdefinition/V0_0_3__Snapshot_20220815_Update.sql similarity index 100% rename from edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/contractdefinition/V0_0_3__Snapshot_20220815_Update.sql rename to edc-extensions/migrations/control-plane-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/contractdefinition/V0_0_3__Snapshot_20220815_Update.sql diff --git a/edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/contractdefinition/V0_0_4__Snapshot_20221201_Update.sql b/edc-extensions/migrations/control-plane-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/contractdefinition/V0_0_4__Snapshot_20221201_Update.sql similarity index 100% rename from edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/contractdefinition/V0_0_4__Snapshot_20221201_Update.sql rename to edc-extensions/migrations/control-plane-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/contractdefinition/V0_0_4__Snapshot_20221201_Update.sql diff --git a/edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/contractdefinition/V0_0_5__Alter_ContractDefinition_Remove_validity.sql b/edc-extensions/migrations/control-plane-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/contractdefinition/V0_0_5__Alter_ContractDefinition_Remove_validity.sql similarity index 100% rename from edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/contractdefinition/V0_0_5__Alter_ContractDefinition_Remove_validity.sql rename to edc-extensions/migrations/control-plane-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/contractdefinition/V0_0_5__Alter_ContractDefinition_Remove_validity.sql diff --git a/edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/contractdefinition/V0_0_6__Alter_ContractDefinition_Rename_selector_expression.sql b/edc-extensions/migrations/control-plane-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/contractdefinition/V0_0_6__Alter_ContractDefinition_Rename_selector_expression.sql similarity index 100% rename from edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/contractdefinition/V0_0_6__Alter_ContractDefinition_Rename_selector_expression.sql rename to edc-extensions/migrations/control-plane-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/contractdefinition/V0_0_6__Alter_ContractDefinition_Rename_selector_expression.sql diff --git a/edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/contractdefinition/V0_0_7__Alter_ContractDefinition_Add_Private_Properties.sql b/edc-extensions/migrations/control-plane-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/contractdefinition/V0_0_7__Alter_ContractDefinition_Add_Private_Properties.sql similarity index 100% rename from edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/contractdefinition/V0_0_7__Alter_ContractDefinition_Add_Private_Properties.sql rename to edc-extensions/migrations/control-plane-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/contractdefinition/V0_0_7__Alter_ContractDefinition_Add_Private_Properties.sql diff --git a/edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/contractdefinition/V0_0_8__Alter_ContractDefinition_Switch_Assets_Selector_Json.sql b/edc-extensions/migrations/control-plane-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/contractdefinition/V0_0_8__Alter_ContractDefinition_Switch_Assets_Selector_Json.sql similarity index 100% rename from edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/contractdefinition/V0_0_8__Alter_ContractDefinition_Switch_Assets_Selector_Json.sql rename to edc-extensions/migrations/control-plane-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/contractdefinition/V0_0_8__Alter_ContractDefinition_Switch_Assets_Selector_Json.sql diff --git a/edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/contractnegotiation/V0_0_1__Init_ContractNegotiation_Database_Schema.sql b/edc-extensions/migrations/control-plane-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/contractnegotiation/V0_0_1__Init_ContractNegotiation_Database_Schema.sql similarity index 100% rename from edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/contractnegotiation/V0_0_1__Init_ContractNegotiation_Database_Schema.sql rename to edc-extensions/migrations/control-plane-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/contractnegotiation/V0_0_1__Init_ContractNegotiation_Database_Schema.sql diff --git a/edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/contractnegotiation/V0_0_2__Alter_ContractNegotation_Contract_Agreement_Id_Schema.sql b/edc-extensions/migrations/control-plane-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/contractnegotiation/V0_0_2__Alter_ContractNegotation_Contract_Agreement_Id_Schema.sql similarity index 100% rename from edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/contractnegotiation/V0_0_2__Alter_ContractNegotation_Contract_Agreement_Id_Schema.sql rename to edc-extensions/migrations/control-plane-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/contractnegotiation/V0_0_2__Alter_ContractNegotation_Contract_Agreement_Id_Schema.sql diff --git a/edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/contractnegotiation/V0_0_3__Milestone5_Update.sql b/edc-extensions/migrations/control-plane-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/contractnegotiation/V0_0_3__Milestone5_Update.sql similarity index 100% rename from edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/contractnegotiation/V0_0_3__Milestone5_Update.sql rename to edc-extensions/migrations/control-plane-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/contractnegotiation/V0_0_3__Milestone5_Update.sql diff --git a/edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/contractnegotiation/V0_0_4__Snapshot_20220815_Update.sql b/edc-extensions/migrations/control-plane-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/contractnegotiation/V0_0_4__Snapshot_20220815_Update.sql similarity index 100% rename from edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/contractnegotiation/V0_0_4__Snapshot_20220815_Update.sql rename to edc-extensions/migrations/control-plane-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/contractnegotiation/V0_0_4__Snapshot_20220815_Update.sql diff --git a/edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/contractnegotiation/V0_0_5__Alter_ContractNegotiation_Add_Callbacks.sql b/edc-extensions/migrations/control-plane-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/contractnegotiation/V0_0_5__Alter_ContractNegotiation_Add_Callbacks.sql similarity index 100% rename from edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/contractnegotiation/V0_0_5__Alter_ContractNegotiation_Add_Callbacks.sql rename to edc-extensions/migrations/control-plane-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/contractnegotiation/V0_0_5__Alter_ContractNegotiation_Add_Callbacks.sql diff --git a/edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/contractnegotiation/V0_0_6__Alter_ContractNegotiation_Change_Type.sql b/edc-extensions/migrations/control-plane-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/contractnegotiation/V0_0_6__Alter_ContractNegotiation_Change_Type.sql similarity index 100% rename from edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/contractnegotiation/V0_0_6__Alter_ContractNegotiation_Change_Type.sql rename to edc-extensions/migrations/control-plane-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/contractnegotiation/V0_0_6__Alter_ContractNegotiation_Change_Type.sql diff --git a/edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/contractnegotiation/V0_0_7__Alter_ContractNegotiation_AddPendingField.sql b/edc-extensions/migrations/control-plane-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/contractnegotiation/V0_0_7__Alter_ContractNegotiation_AddPendingField.sql similarity index 100% rename from edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/contractnegotiation/V0_0_7__Alter_ContractNegotiation_AddPendingField.sql rename to edc-extensions/migrations/control-plane-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/contractnegotiation/V0_0_7__Alter_ContractNegotiation_AddPendingField.sql diff --git a/edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/contractnegotiation/V0_0_8__Alter_ContractNegotiation_AddProtocolMessagesField.sql b/edc-extensions/migrations/control-plane-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/contractnegotiation/V0_0_8__Alter_ContractNegotiation_AddProtocolMessagesField.sql similarity index 100% rename from edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/contractnegotiation/V0_0_8__Alter_ContractNegotiation_AddProtocolMessagesField.sql rename to edc-extensions/migrations/control-plane-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/contractnegotiation/V0_0_8__Alter_ContractNegotiation_AddProtocolMessagesField.sql diff --git a/edc-extensions/migrations/control-plane-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/edr-index/V0_0_1__Init_EdrIndex_Database_Schema.sql b/edc-extensions/migrations/control-plane-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/edr-index/V0_0_1__Init_EdrIndex_Database_Schema.sql new file mode 100644 index 000000000..868430225 --- /dev/null +++ b/edc-extensions/migrations/control-plane-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/edr-index/V0_0_1__Init_EdrIndex_Database_Schema.sql @@ -0,0 +1,31 @@ +-- +-- Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +-- +-- This program and the accompanying materials are made available under the +-- terms of the Apache License, Version 2.0 which is available at +-- https://www.apache.org/licenses/LICENSE-2.0 +-- +-- SPDX-License-Identifier: Apache-2.0 +-- +-- Contributors: +-- Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - initial API and implementation +-- + +-- +-- table: edc_edr_entry +-- + +CREATE TABLE IF NOT EXISTS edc_edr_entry +( + transfer_process_id VARCHAR NOT NULL PRIMARY KEY, + agreement_id VARCHAR NOT NULL, + asset_id VARCHAR NOT NULL, + provider_id VARCHAR NOT NULL, + contract_negotiation_id VARCHAR, + created_at BIGINT NOT NULL +); + + +CREATE INDEX IF NOT EXISTS asset_id_index ON edc_edr_entry (asset_id); + + diff --git a/edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/policy-monitor/V0_0_1__Init_PolicyMonitor_Database_Schema.sql b/edc-extensions/migrations/control-plane-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/policy-monitor/V0_0_1__Init_PolicyMonitor_Database_Schema.sql similarity index 100% rename from edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/policy-monitor/V0_0_1__Init_PolicyMonitor_Database_Schema.sql rename to edc-extensions/migrations/control-plane-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/policy-monitor/V0_0_1__Init_PolicyMonitor_Database_Schema.sql diff --git a/edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/policy/V0_0_1__Init_Policy_Database_Schema.sql b/edc-extensions/migrations/control-plane-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/policy/V0_0_1__Init_Policy_Database_Schema.sql similarity index 100% rename from edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/policy/V0_0_1__Init_Policy_Database_Schema.sql rename to edc-extensions/migrations/control-plane-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/policy/V0_0_1__Init_Policy_Database_Schema.sql diff --git a/edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/policy/V0_0_2__Milestone5_Update.sql b/edc-extensions/migrations/control-plane-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/policy/V0_0_2__Milestone5_Update.sql similarity index 100% rename from edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/policy/V0_0_2__Milestone5_Update.sql rename to edc-extensions/migrations/control-plane-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/policy/V0_0_2__Milestone5_Update.sql diff --git a/edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/policy/V0_0_3__Snapshot_20220815_Update.sql b/edc-extensions/migrations/control-plane-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/policy/V0_0_3__Snapshot_20220815_Update.sql similarity index 100% rename from edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/policy/V0_0_3__Snapshot_20220815_Update.sql rename to edc-extensions/migrations/control-plane-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/policy/V0_0_3__Snapshot_20220815_Update.sql diff --git a/edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/policy/V0_0_4__Add_Private_Properties.sql b/edc-extensions/migrations/control-plane-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/policy/V0_0_4__Add_Private_Properties.sql similarity index 100% rename from edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/policy/V0_0_4__Add_Private_Properties.sql rename to edc-extensions/migrations/control-plane-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/policy/V0_0_4__Add_Private_Properties.sql diff --git a/edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/transferprocess/V0_0_10__Alter_TransferProcess_Rename_transfer_process_column.sql b/edc-extensions/migrations/control-plane-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/transferprocess/V0_0_10__Alter_TransferProcess_Rename_transfer_process_column.sql similarity index 100% rename from edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/transferprocess/V0_0_10__Alter_TransferProcess_Rename_transfer_process_column.sql rename to edc-extensions/migrations/control-plane-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/transferprocess/V0_0_10__Alter_TransferProcess_Rename_transfer_process_column.sql diff --git a/edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/transferprocess/V0_0_11__Alter_TransferProcess_AddPendingField.sql b/edc-extensions/migrations/control-plane-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/transferprocess/V0_0_11__Alter_TransferProcess_AddPendingField.sql similarity index 100% rename from edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/transferprocess/V0_0_11__Alter_TransferProcess_AddPendingField.sql rename to edc-extensions/migrations/control-plane-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/transferprocess/V0_0_11__Alter_TransferProcess_AddPendingField.sql diff --git a/edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/transferprocess/V0_0_12__Alter_TransferProcess_AddTransferType.sql b/edc-extensions/migrations/control-plane-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/transferprocess/V0_0_12__Alter_TransferProcess_AddTransferType.sql similarity index 100% rename from edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/transferprocess/V0_0_12__Alter_TransferProcess_AddTransferType.sql rename to edc-extensions/migrations/control-plane-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/transferprocess/V0_0_12__Alter_TransferProcess_AddTransferType.sql diff --git a/edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/transferprocess/V0_0_13__Alter_TransferProcess_AddProtocolMessages.sql b/edc-extensions/migrations/control-plane-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/transferprocess/V0_0_13__Alter_TransferProcess_AddProtocolMessages.sql similarity index 100% rename from edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/transferprocess/V0_0_13__Alter_TransferProcess_AddProtocolMessages.sql rename to edc-extensions/migrations/control-plane-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/transferprocess/V0_0_13__Alter_TransferProcess_AddProtocolMessages.sql diff --git a/edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/transferprocess/V0_0_14__Alter_TransferProcess_AddDataPlaneId.sql b/edc-extensions/migrations/control-plane-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/transferprocess/V0_0_14__Alter_TransferProcess_AddDataPlaneId.sql similarity index 100% rename from edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/transferprocess/V0_0_14__Alter_TransferProcess_AddDataPlaneId.sql rename to edc-extensions/migrations/control-plane-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/transferprocess/V0_0_14__Alter_TransferProcess_AddDataPlaneId.sql diff --git a/edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/transferprocess/V0_0_15__Alter_TransferProcess_InlineDataAddress.sql b/edc-extensions/migrations/control-plane-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/transferprocess/V0_0_15__Alter_TransferProcess_InlineDataAddress.sql similarity index 100% rename from edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/transferprocess/V0_0_15__Alter_TransferProcess_InlineDataAddress.sql rename to edc-extensions/migrations/control-plane-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/transferprocess/V0_0_15__Alter_TransferProcess_InlineDataAddress.sql diff --git a/edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/transferprocess/V0_0_1__Init_TransferProcess_Database_Schema.sql b/edc-extensions/migrations/control-plane-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/transferprocess/V0_0_1__Init_TransferProcess_Database_Schema.sql similarity index 100% rename from edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/transferprocess/V0_0_1__Init_TransferProcess_Database_Schema.sql rename to edc-extensions/migrations/control-plane-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/transferprocess/V0_0_1__Init_TransferProcess_Database_Schema.sql diff --git a/edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/transferprocess/V0_0_2__Alter_TransferProcess_Add_DataAddress.sql b/edc-extensions/migrations/control-plane-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/transferprocess/V0_0_2__Alter_TransferProcess_Add_DataAddress.sql similarity index 100% rename from edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/transferprocess/V0_0_2__Alter_TransferProcess_Add_DataAddress.sql rename to edc-extensions/migrations/control-plane-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/transferprocess/V0_0_2__Alter_TransferProcess_Add_DataAddress.sql diff --git a/edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/transferprocess/V0_0_3__Alter_Rename_Id.sql b/edc-extensions/migrations/control-plane-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/transferprocess/V0_0_3__Alter_Rename_Id.sql similarity index 100% rename from edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/transferprocess/V0_0_3__Alter_Rename_Id.sql rename to edc-extensions/migrations/control-plane-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/transferprocess/V0_0_3__Alter_Rename_Id.sql diff --git a/edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/transferprocess/V0_0_4__Milestone5_Update.sql b/edc-extensions/migrations/control-plane-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/transferprocess/V0_0_4__Milestone5_Update.sql similarity index 100% rename from edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/transferprocess/V0_0_4__Milestone5_Update.sql rename to edc-extensions/migrations/control-plane-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/transferprocess/V0_0_4__Milestone5_Update.sql diff --git a/edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/transferprocess/V0_0_5__Snapshot_20220815_Update.sql b/edc-extensions/migrations/control-plane-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/transferprocess/V0_0_5__Snapshot_20220815_Update.sql similarity index 100% rename from edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/transferprocess/V0_0_5__Snapshot_20220815_Update.sql rename to edc-extensions/migrations/control-plane-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/transferprocess/V0_0_5__Snapshot_20220815_Update.sql diff --git a/edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/transferprocess/V0_0_6__Snapshot_20230109_Update.sql b/edc-extensions/migrations/control-plane-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/transferprocess/V0_0_6__Snapshot_20230109_Update.sql similarity index 100% rename from edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/transferprocess/V0_0_6__Snapshot_20230109_Update.sql rename to edc-extensions/migrations/control-plane-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/transferprocess/V0_0_6__Snapshot_20230109_Update.sql diff --git a/edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/transferprocess/V0_0_7__Default_Value_For_Properties.sql b/edc-extensions/migrations/control-plane-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/transferprocess/V0_0_7__Default_Value_For_Properties.sql similarity index 100% rename from edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/transferprocess/V0_0_7__Default_Value_For_Properties.sql rename to edc-extensions/migrations/control-plane-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/transferprocess/V0_0_7__Default_Value_For_Properties.sql diff --git a/edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/transferprocess/V0_0_8__Alter_TransferProcess_Add_Callbacks.sql b/edc-extensions/migrations/control-plane-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/transferprocess/V0_0_8__Alter_TransferProcess_Add_Callbacks.sql similarity index 100% rename from edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/transferprocess/V0_0_8__Alter_TransferProcess_Add_Callbacks.sql rename to edc-extensions/migrations/control-plane-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/transferprocess/V0_0_8__Alter_TransferProcess_Add_Callbacks.sql diff --git a/edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/transferprocess/V0_0_9__Alter_TransferProcess_Remove_Transfertype.sql b/edc-extensions/migrations/control-plane-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/transferprocess/V0_0_9__Alter_TransferProcess_Remove_Transfertype.sql similarity index 100% rename from edc-extensions/postgresql-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/transferprocess/V0_0_9__Alter_TransferProcess_Remove_Transfertype.sql rename to edc-extensions/migrations/control-plane-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/transferprocess/V0_0_9__Alter_TransferProcess_Remove_Transfertype.sql diff --git a/edc-extensions/postgresql-migration/src/test/java/org/eclipse/tractusx/edc/postgresql/migration/AssetPostgresqlMigrationExtensionTest.java b/edc-extensions/migrations/control-plane-migration/src/test/java/org/eclipse/tractusx/edc/postgresql/migration/AssetPostgresqlMigrationExtensionTest.java similarity index 100% rename from edc-extensions/postgresql-migration/src/test/java/org/eclipse/tractusx/edc/postgresql/migration/AssetPostgresqlMigrationExtensionTest.java rename to edc-extensions/migrations/control-plane-migration/src/test/java/org/eclipse/tractusx/edc/postgresql/migration/AssetPostgresqlMigrationExtensionTest.java diff --git a/edc-extensions/migrations/data-plane-migration/README.md b/edc-extensions/migrations/data-plane-migration/README.md new file mode 100644 index 000000000..e4ce1d0de --- /dev/null +++ b/edc-extensions/migrations/data-plane-migration/README.md @@ -0,0 +1,14 @@ +# Postgresql SQL Migration Extension + +This extension applies SQL migrations to these stores: + +* dataplane +* accesstokendata + +## Configuration + +| Key | Description | Mandatory | Default | +|:--------------------------------------------------------------------------|:-------------------------------------------------|-----------|----------| +| org.eclipse.tractusx.edc.postgresql.migration.dataplane.enabled | Enable migration for data flow tables | | true | +| org.eclipse.tractusx.edc.postgresql.migration.accesstokendata.enabled | Enable migration for access token data tables | | true | +| org.eclipse.tractusx.edc.postgresql.migration.schema | The DB schema to be used during migration | | "public" | diff --git a/edc-extensions/migrations/data-plane-migration/build.gradle.kts b/edc-extensions/migrations/data-plane-migration/build.gradle.kts new file mode 100644 index 000000000..2ff1aa7fa --- /dev/null +++ b/edc-extensions/migrations/data-plane-migration/build.gradle.kts @@ -0,0 +1,41 @@ +/******************************************************************************** + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +plugins { + `maven-publish` + `java-library` +} + +dependencies { + implementation(project(":edc-extensions:migrations:postgresql-migration-lib")) + implementation(libs.edc.spi.core) + implementation(libs.edc.junit) + implementation(libs.edc.spi.transaction.datasource) + implementation(libs.edc.sql.assetindex) + implementation(libs.edc.sql.core) + runtimeOnly(libs.postgres) + + implementation(libs.flyway.core) + // starting from flyway 10, they've moved to a more modular structure, + // so we need to add PG support explicitly + // https://documentation.red-gate.com/flyway/release-notes-and-older-versions/release-notes-for-flyway-engine + runtimeOnly(libs.flyway.database.postgres) + + testImplementation(testFixtures(libs.edc.sql.core)) +} diff --git a/edc-extensions/migrations/data-plane-migration/src/main/java/org/eclipse/tractusx/edc/postgresql/migration/AccessTokenDataPostgresqlMigrationExtension.java b/edc-extensions/migrations/data-plane-migration/src/main/java/org/eclipse/tractusx/edc/postgresql/migration/AccessTokenDataPostgresqlMigrationExtension.java new file mode 100644 index 000000000..d1ab69723 --- /dev/null +++ b/edc-extensions/migrations/data-plane-migration/src/main/java/org/eclipse/tractusx/edc/postgresql/migration/AccessTokenDataPostgresqlMigrationExtension.java @@ -0,0 +1,29 @@ +/******************************************************************************** + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +package org.eclipse.tractusx.edc.postgresql.migration; + +public class AccessTokenDataPostgresqlMigrationExtension extends AbstractPostgresqlMigrationExtension { + private static final String NAME_SUBSYSTEM = "accesstokendata"; + + @Override + protected String getSubsystemName() { + return NAME_SUBSYSTEM; + } +} diff --git a/edc-extensions/migrations/data-plane-migration/src/main/java/org/eclipse/tractusx/edc/postgresql/migration/DataPlanePostgresqlMigrationExtension.java b/edc-extensions/migrations/data-plane-migration/src/main/java/org/eclipse/tractusx/edc/postgresql/migration/DataPlanePostgresqlMigrationExtension.java new file mode 100644 index 000000000..bcbea63f9 --- /dev/null +++ b/edc-extensions/migrations/data-plane-migration/src/main/java/org/eclipse/tractusx/edc/postgresql/migration/DataPlanePostgresqlMigrationExtension.java @@ -0,0 +1,30 @@ +/******************************************************************************** + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +package org.eclipse.tractusx.edc.postgresql.migration; + +public class DataPlanePostgresqlMigrationExtension extends AbstractPostgresqlMigrationExtension { + private static final String NAME_SUBSYSTEM = "dataplane"; + + @Override + protected String getSubsystemName() { + return NAME_SUBSYSTEM; + } + +} diff --git a/edc-extensions/migrations/data-plane-migration/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension b/edc-extensions/migrations/data-plane-migration/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension new file mode 100644 index 000000000..6212ad5dd --- /dev/null +++ b/edc-extensions/migrations/data-plane-migration/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension @@ -0,0 +1,21 @@ +################################################################################# +# Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License, Version 2.0 which is available at +# https://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. +# +# SPDX-License-Identifier: Apache-2.0 +################################################################################# + +org.eclipse.tractusx.edc.postgresql.migration.DataPlanePostgresqlMigrationExtension +org.eclipse.tractusx.edc.postgresql.migration.AccessTokenDataPostgresqlMigrationExtension diff --git a/edc-extensions/migrations/data-plane-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/accesstokendata/V0_0_1__Init_AccessTokenData_Database_Schema.sql b/edc-extensions/migrations/data-plane-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/accesstokendata/V0_0_1__Init_AccessTokenData_Database_Schema.sql new file mode 100644 index 000000000..6796e9afc --- /dev/null +++ b/edc-extensions/migrations/data-plane-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/accesstokendata/V0_0_1__Init_AccessTokenData_Database_Schema.sql @@ -0,0 +1,28 @@ +-- +-- Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +-- +-- This program and the accompanying materials are made available under the +-- terms of the Apache License, Version 2.0 which is available at +-- https://www.apache.org/licenses/LICENSE-2.0 +-- +-- SPDX-License-Identifier: Apache-2.0 +-- +-- Contributors: +-- Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - initial API and implementation +-- + +-- +-- table: edc_accesstokendata +-- + +CREATE TABLE IF NOT EXISTS edc_accesstokendata +( + id VARCHAR NOT NULL PRIMARY KEY, + claim_token JSON NOT NULL, + data_address JSON NOT NULL, + additional_properties JSON DEFAULT '{}' +); + +COMMENT ON COLUMN edc_accesstokendata.claim_token IS 'ClaimToken serialized as JSON map'; +COMMENT ON COLUMN edc_accesstokendata.data_address IS 'DataAddress serialized as JSON map'; +COMMENT ON COLUMN edc_accesstokendata.additional_properties IS 'Optional Additional properties serialized as JSON map'; diff --git a/edc-extensions/migrations/data-plane-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/dataplane/V0_0_1__Init_Dataplane_Database_Schema.sql b/edc-extensions/migrations/data-plane-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/dataplane/V0_0_1__Init_Dataplane_Database_Schema.sql new file mode 100644 index 000000000..c83548bd5 --- /dev/null +++ b/edc-extensions/migrations/data-plane-migration/src/main/resources/org/eclipse/tractusx/edc/postgresql/migration/dataplane/V0_0_1__Init_Dataplane_Database_Schema.sql @@ -0,0 +1,55 @@ +-- +-- Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +-- +-- This program and the accompanying materials are made available under the +-- terms of the Apache License, Version 2.0 which is available at +-- https://www.apache.org/licenses/LICENSE-2.0 +-- +-- SPDX-License-Identifier: Apache-2.0 +-- +-- Contributors: +-- Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - initial API and implementation +-- + +-- +-- tables: edc_data_plane, edc_lease +-- + +CREATE TABLE IF NOT EXISTS edc_lease +( + leased_by VARCHAR NOT NULL, + leased_at BIGINT, + lease_duration INTEGER NOT NULL, + lease_id VARCHAR NOT NULL + CONSTRAINT lease_pk + PRIMARY KEY +); + +COMMENT ON COLUMN edc_lease.leased_at IS 'posix timestamp of lease'; +COMMENT ON COLUMN edc_lease.lease_duration IS 'duration of lease in milliseconds'; + +CREATE TABLE IF NOT EXISTS edc_data_plane +( + process_id VARCHAR NOT NULL PRIMARY KEY, + state INTEGER NOT NULL , + created_at BIGINT NOT NULL , + updated_at BIGINT NOT NULL , + state_count INTEGER DEFAULT 0 NOT NULL, + state_time_stamp BIGINT, + trace_context JSON, + error_detail VARCHAR, + callback_address VARCHAR, + lease_id VARCHAR + CONSTRAINT data_plane_lease_lease_id_fk + REFERENCES edc_lease + ON DELETE SET NULL, + source JSON, + destination JSON, + properties JSON, + flow_type VARCHAR +); + +COMMENT ON COLUMN edc_data_plane.trace_context IS 'Java Map serialized as JSON'; +COMMENT ON COLUMN edc_data_plane.source IS 'DataAddress serialized as JSON'; +COMMENT ON COLUMN edc_data_plane.destination IS 'DataAddress serialized as JSON'; +COMMENT ON COLUMN edc_data_plane.properties IS 'Java Map serialized as JSON'; diff --git a/edc-extensions/postgresql-migration/build.gradle.kts b/edc-extensions/migrations/postgresql-migration-lib/build.gradle.kts similarity index 100% rename from edc-extensions/postgresql-migration/build.gradle.kts rename to edc-extensions/migrations/postgresql-migration-lib/build.gradle.kts diff --git a/edc-extensions/postgresql-migration/src/main/java/org/eclipse/tractusx/edc/postgresql/migration/AbstractPostgresqlMigrationExtension.java b/edc-extensions/migrations/postgresql-migration-lib/src/main/java/org/eclipse/tractusx/edc/postgresql/migration/AbstractPostgresqlMigrationExtension.java similarity index 95% rename from edc-extensions/postgresql-migration/src/main/java/org/eclipse/tractusx/edc/postgresql/migration/AbstractPostgresqlMigrationExtension.java rename to edc-extensions/migrations/postgresql-migration-lib/src/main/java/org/eclipse/tractusx/edc/postgresql/migration/AbstractPostgresqlMigrationExtension.java index 6c894b4d2..20ca7979f 100644 --- a/edc-extensions/postgresql-migration/src/main/java/org/eclipse/tractusx/edc/postgresql/migration/AbstractPostgresqlMigrationExtension.java +++ b/edc-extensions/migrations/postgresql-migration-lib/src/main/java/org/eclipse/tractusx/edc/postgresql/migration/AbstractPostgresqlMigrationExtension.java @@ -78,7 +78,7 @@ public void initialize(final ServiceExtensionContext context) { var dataSource = new ConnectionFactoryDataSource(driverManagerConnectionFactory, jdbcUrl, jdbcProperties); var defaultSchema = config.getString(MIGRATION_SCHEMA, DEFAULT_MIGRATION_SCHEMA); - var migrateResult = FlywayManager.migrate(dataSource, subSystemName, defaultSchema, LATEST); + var migrateResult = FlywayManager.migrate(dataSource, getMigrationSubsystem(), defaultSchema, LATEST); if (!migrateResult.success) { throw new EdcPersistenceException( @@ -90,4 +90,8 @@ public void initialize(final ServiceExtensionContext context) { protected abstract String getSubsystemName(); + protected String getMigrationSubsystem() { + return getSubsystemName(); + } + } diff --git a/edc-extensions/postgresql-migration/src/main/java/org/eclipse/tractusx/edc/postgresql/migration/FlywayManager.java b/edc-extensions/migrations/postgresql-migration-lib/src/main/java/org/eclipse/tractusx/edc/postgresql/migration/FlywayManager.java similarity index 100% rename from edc-extensions/postgresql-migration/src/main/java/org/eclipse/tractusx/edc/postgresql/migration/FlywayManager.java rename to edc-extensions/migrations/postgresql-migration-lib/src/main/java/org/eclipse/tractusx/edc/postgresql/migration/FlywayManager.java diff --git a/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/runtimes/PgParticipantRuntime.java b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/runtimes/PgParticipantRuntime.java index b3bfe98f4..7e37030ac 100644 --- a/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/runtimes/PgParticipantRuntime.java +++ b/edc-tests/edc-controlplane/fixtures/src/testFixtures/java/org/eclipse/tractusx/edc/tests/runtimes/PgParticipantRuntime.java @@ -36,7 +36,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.stream.Stream; import static java.lang.String.format; import static org.eclipse.tractusx.edc.tests.TestRuntimeConfiguration.DB_SCHEMA_NAME; @@ -46,6 +45,9 @@ public class PgParticipantRuntime extends ParticipantRuntime implements AfterAll private static final String POSTGRES_IMAGE_NAME = "postgres:14.2"; private static final String USER = "postgres"; private static final String PASSWORD = "password"; + private static final List DATASOURCES = List.of("asset", "contractdefinition", + "contractnegotiation", "policy", "transferprocess", "bpn", + "policy-monitor", "edr", "dataplane", "accesstokendata"); private final String dbName; public PostgreSQLContainer postgreSqlContainer; @@ -77,18 +79,24 @@ public void afterAll(ExtensionContext context) throws Exception { postgreSqlContainer.close(); } + @Override + protected void bootExtensions(ServiceExtensionContext context, List> serviceExtensions) { + PostgresqlLocalInstance helper = new PostgresqlLocalInstance(postgreSqlContainer.getUsername(), postgreSqlContainer.getPassword(), baseJdbcUrl(), postgreSqlContainer.getDatabaseName()); + helper.createDatabase(); + super.bootExtensions(context, serviceExtensions); + } + public Map postgresqlConfiguration(String name) { var jdbcUrl = jdbcUrl(name); return new HashMap<>() { { - Stream.of("asset", "contractdefinition", "contractnegotiation", "policy", "transferprocess", "bpn", "policy-monitor") - .forEach(context -> { - var group = "edc.datasource." + context; - put(group + ".name", context); - put(group + ".url", jdbcUrl); - put(group + ".user", USER); - put(group + ".password", PASSWORD); - }); + DATASOURCES.forEach(context -> { + var group = "edc.datasource." + context; + put(group + ".name", context); + put(group + ".url", jdbcUrl); + put(group + ".user", USER); + put(group + ".password", PASSWORD); + }); // use non-default schema name to test usage of non-default schema put("org.eclipse.tractusx.edc.postgresql.migration.schema", DB_SCHEMA_NAME); } @@ -103,13 +111,6 @@ public String baseJdbcUrl() { return format("jdbc:postgresql://%s:%s/", postgreSqlContainer.getHost(), postgreSqlContainer.getFirstMappedPort()); } - @Override - protected void bootExtensions(ServiceExtensionContext context, List> serviceExtensions) { - PostgresqlLocalInstance helper = new PostgresqlLocalInstance(postgreSqlContainer.getUsername(), postgreSqlContainer.getPassword(), baseJdbcUrl(), postgreSqlContainer.getDatabaseName()); - helper.createDatabase(); - super.bootExtensions(context, serviceExtensions); - } - protected void mockVault() { this.registerServiceMock(Vault.class, new InMemoryVaultOverride(new ConsoleMonitor())); } diff --git a/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/iatp/harness/DataspaceIssuer.java b/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/iatp/harness/DataspaceIssuer.java index 37ce54ec1..6a03cd8eb 100644 --- a/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/iatp/harness/DataspaceIssuer.java +++ b/edc-tests/edc-controlplane/iatp-tests/src/test/java/org/eclipse/tractusx/edc/tests/transfer/iatp/harness/DataspaceIssuer.java @@ -26,11 +26,11 @@ import jakarta.json.JsonObject; import org.eclipse.edc.iam.did.spi.document.DidDocument; import org.eclipse.edc.iam.did.spi.document.VerificationMethod; -import org.eclipse.edc.iam.identitytrust.spi.model.CredentialFormat; -import org.eclipse.edc.iam.identitytrust.spi.model.CredentialSubject; -import org.eclipse.edc.iam.identitytrust.spi.model.Issuer; -import org.eclipse.edc.iam.identitytrust.spi.model.VerifiableCredential; -import org.eclipse.edc.iam.identitytrust.spi.model.VerifiableCredentialContainer; +import org.eclipse.edc.iam.verifiablecredentials.spi.model.CredentialFormat; +import org.eclipse.edc.iam.verifiablecredentials.spi.model.CredentialSubject; +import org.eclipse.edc.iam.verifiablecredentials.spi.model.Issuer; +import org.eclipse.edc.iam.verifiablecredentials.spi.model.VerifiableCredential; +import org.eclipse.edc.iam.verifiablecredentials.spi.model.VerifiableCredentialContainer; import org.eclipse.edc.identityhub.spi.model.VerifiableCredentialResource; import org.eclipse.edc.jsonld.spi.JsonLd; import org.eclipse.edc.security.signature.jws2020.JwkMethod; diff --git a/edc-tests/runtime/runtime-postgresql/build.gradle.kts b/edc-tests/runtime/runtime-postgresql/build.gradle.kts index a03e1746d..8297ca00a 100644 --- a/edc-tests/runtime/runtime-postgresql/build.gradle.kts +++ b/edc-tests/runtime/runtime-postgresql/build.gradle.kts @@ -38,8 +38,9 @@ dependencies { implementation(project(":edc-tests:runtime:extensions")) // use basic (all in-mem) data plane - runtimeOnly(project(":edc-dataplane:edc-dataplane-base")) { + runtimeOnly(project(":edc-dataplane:edc-dataplane-hashicorp-vault")) { exclude("org.eclipse.edc", "api-observability") + exclude(group = "org.eclipse.edc", "vault-hashicorp") } implementation(libs.edc.core.controlplane) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 7ecb3c1cc..a3bec4cb4 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -45,6 +45,7 @@ edc-spi-jwt = { module = "org.eclipse.edc:jwt-spi", version.ref = "edc" } edc-spi-token = { module = "org.eclipse.edc:token-spi", version.ref = "edc" } edc-spi-transform = { module = "org.eclipse.edc:transform-spi", version.ref = "edc" } edc-spi-identity-did = { module = "org.eclipse.edc:identity-did-spi", version.ref = "edc" } +edc-spi-vc = { module = "org.eclipse.edc:verifiable-credentials-spi", version.ref = "edc" } edc-spi-edrstore = { module = "org.eclipse.edc:edr-store-spi", version.ref = "edc" } edc-token-core = { module = "org.eclipse.edc:token-core", version.ref = "edc" } edc-spi-oauth2 = { module = "org.eclipse.edc:oauth2-spi", version.ref = "edc" } @@ -107,6 +108,9 @@ edc-sql-core = { module = "org.eclipse.edc:sql-core", version.ref = "edc" } edc-sql-lease = { module = "org.eclipse.edc:sql-lease", version.ref = "edc" } edc-sql-pool = { module = "org.eclipse.edc:sql-pool-apache-commons", version.ref = "edc" } edc-sql-policy-monitor = { module = "org.eclipse.edc:policy-monitor-store-sql", version.ref = "edc" } +edc-sql-edrindex = { module = "org.eclipse.edc:edr-index-sql", version.ref = "edc" } +edc-sql-accesstokendata = { module = "org.eclipse.edc:accesstokendata-store-sql", version.ref = "edc" } +edc-sql-dataplane = { module = "org.eclipse.edc:data-plane-store-sql", version.ref = "edc" } # azure stuff edc-azure-vault = { module = "org.eclipse.edc:vault-azure", version.ref = "edc" } @@ -214,6 +218,6 @@ titaniumJsonLd = { module = "com.apicatalog:titanium-json-ld", version.ref = "ti [bundles] edc-connector = ["edc.boot", "edc.core-connector", "edc.core-controlplane", "edc.api-observability"] edc-dpf = ["edc.dpf-transfer-signaling", "edc.dpf-selector-core", "edc.spi-dataplane-selector"] -edc-sqlstores = ["edc.sql-assetindex", "edc.sql-contract-definition", "edc.sql-contract-negotiation", "edc.sql-transferprocess", "edc.sql-policydef", "edc.sql-policy-monitor"] +edc-sqlstores = ["edc.sql-assetindex", "edc.sql-contract-definition", "edc.sql-contract-negotiation", "edc.sql-transferprocess", "edc.sql-policydef", "edc.sql-policy-monitor", "edc.sql-edrindex"] edc-monitoring = ["edc.micrometer-core", "edc.micrometer-jersey", "edc.micrometer-jetty"] edc-sts = ["edc-identity-trust-sts-core", "edc-identity-trust-sts-api", "edc-identity-trust-sts-client-configuration"] diff --git a/settings.gradle.kts b/settings.gradle.kts index 586fba727..c33a612e9 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -38,7 +38,9 @@ include(":edc-extensions:bpn-validation:bpn-validation-api") include(":edc-extensions:bpn-validation:bpn-validation-spi") include(":edc-extensions:bpn-validation:bpn-validation-core") include(":edc-extensions:bpn-validation:business-partner-store-sql") -include(":edc-extensions:postgresql-migration") +include(":edc-extensions:migrations:postgresql-migration-lib") +include(":edc-extensions:migrations:control-plane-migration") +include(":edc-extensions:migrations:data-plane-migration") include(":edc-extensions:tokenrefresh-handler") include(":edc-extensions:bdrs-client") include(":edc-extensions:provision-additional-headers") From d97a021eb84e4d20af4fc5f2a0ac02747c806ef1 Mon Sep 17 00:00:00 2001 From: Enrico Risa Date: Fri, 5 Apr 2024 12:34:58 +0200 Subject: [PATCH 096/100] chore: fixes after testing (#1191) --- DEPENDENCIES | 1 + .../tractusx-connector-azure-vault/README.md | 4 +-- .../templates/_helpers.tpl | 7 ++-- .../templates/deployment-controlplane.yaml | 9 ++--- .../templates/deployment-dataplane.yaml | 11 +++--- .../templates/service-dataplane.yaml | 6 ++-- .../values.yaml | 4 +-- charts/tractusx-connector-memory/README.md | 4 ++- .../templates/_helpers.tpl | 6 ++-- .../templates/deployment-runtime.yaml | 9 ++++- .../templates/service-runtime.yaml | 4 +++ charts/tractusx-connector-memory/values.yaml | 5 +++ charts/tractusx-connector/README.md | 4 +-- .../tractusx-connector/templates/_helpers.tpl | 6 ++-- .../templates/deployment-controlplane.yaml | 8 +++-- .../templates/deployment-dataplane.yaml | 11 +++--- .../templates/service-dataplane.yaml | 6 ++-- charts/tractusx-connector/values.yaml | 4 +-- .../tractusx/edc/jsonld/JsonLdExtension.java | 3 ++ .../edc-controlplane-base/build.gradle.kts | 4 +++ .../edc-dataplane-base/build.gradle.kts | 1 + .../build.gradle.kts | 1 + .../flow/TxDataFlowPropertiesProvider.java | 3 +- .../TxDataFlowPropertiesProviderTest.java | 3 +- .../asset/ConsumerAssetRequestController.java | 2 +- .../token-refresh-core/build.gradle.kts | 1 + ...DataPlaneTokenRefreshServiceExtension.java | 14 +++++++- .../DataPlaneTokenRefreshServiceImpl.java | 14 +++++++- .../core/rules/AuthTokenAudienceRule.java | 2 +- ...eTokenRefreshServiceImplComponentTest.java | 22 ++++++------ .../DataPlaneTokenRefreshServiceImplTest.java | 11 +++--- .../core/rules/AuthTokenAudienceRuleTest.java | 9 ++--- .../tokenrefresh/TokenRefreshHandlerImpl.java | 34 ++++++++----------- .../TokenRefreshHandlerImplTest.java | 13 +++---- .../tests/edrv2/EdrCacheApiEndToEndTest.java | 4 +++ .../DataPlaneTokenRefreshEndToEndTest.java | 3 +- .../build.gradle.kts | 1 + .../runtime-memory-iatp-ih/build.gradle.kts | 1 + .../iatp/runtime-memory-sts/build.gradle.kts | 1 + .../runtime/runtime-memory/build.gradle.kts | 2 ++ .../runtime-postgresql/build.gradle.kts | 2 ++ samples/multi-tenancy/build.gradle.kts | 1 + .../tractusx/edc/edr/spi/CoreConstants.java | 3 ++ 43 files changed, 169 insertions(+), 95 deletions(-) diff --git a/DEPENDENCIES b/DEPENDENCIES index 3968ca7b4..6c5335b14 100644 --- a/DEPENDENCIES +++ b/DEPENDENCIES @@ -508,6 +508,7 @@ maven/mavencentral/org.eclipse.edc/validator-spi/0.6.1-SNAPSHOT, Apache-2.0, app maven/mavencentral/org.eclipse.edc/vault-azure/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/vault-hashicorp/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/verifiable-credentials-spi/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/verifiable-credentials/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.edc/web-spi/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.jetty.toolchain/jetty-jakarta-servlet-api/5.0.2, EPL-2.0 OR Apache-2.0, approved, rt.jetty maven/mavencentral/org.eclipse.jetty.toolchain/jetty-jakarta-websocket-api/2.0.0, EPL-2.0 OR Apache-2.0, approved, rt.jetty diff --git a/charts/tractusx-connector-azure-vault/README.md b/charts/tractusx-connector-azure-vault/README.md index 6720cd354..34ad00c99 100644 --- a/charts/tractusx-connector-azure-vault/README.md +++ b/charts/tractusx-connector-azure-vault/README.md @@ -178,8 +178,6 @@ helm install my-release tractusx-edc/tractusx-connector-azure-vault --version 0. | dataplane.debug.enabled | bool | `false` | | | dataplane.debug.port | int | `1044` | | | dataplane.debug.suspendOnStart | bool | `false` | | -| dataplane.endpoints.control.path | string | `"/api/dataplane/control"` | | -| dataplane.endpoints.control.port | int | `8083` | | | dataplane.endpoints.default.path | string | `"/api"` | | | dataplane.endpoints.default.port | int | `8080` | | | dataplane.endpoints.metrics.path | string | `"/metrics"` | | @@ -189,6 +187,8 @@ helm install my-release tractusx-edc/tractusx-connector-azure-vault --version 0. | dataplane.endpoints.proxy.port | int | `8186` | | | dataplane.endpoints.public.path | string | `"/api/public"` | | | dataplane.endpoints.public.port | int | `8081` | | +| dataplane.endpoints.signaling.path | string | `"/api/signaling"` | | +| dataplane.endpoints.signaling.port | int | `8083` | | | dataplane.env | object | `{}` | | | dataplane.envConfigMapNames | list | `[]` | | | dataplane.envSecretNames | list | `[]` | | diff --git a/charts/tractusx-connector-azure-vault/templates/_helpers.tpl b/charts/tractusx-connector-azure-vault/templates/_helpers.tpl index b3c570bb1..17bcddc86 100644 --- a/charts/tractusx-connector-azure-vault/templates/_helpers.tpl +++ b/charts/tractusx-connector-azure-vault/templates/_helpers.tpl @@ -8,6 +8,7 @@ Expand the name of the chart. {{/* Create a default fully qualified app name. We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). If release name contains chart name it will be used as a full name. */}} {{- define "txdc.fullname" -}} @@ -143,10 +144,10 @@ Control Plane URL {{- end }} {{/* -Data Control URL +Data Signaling URL */}} -{{- define "txdc.dataplane.url.control" -}} -{{- printf "http://%s-dataplane:%v%s" (include "txdc.fullname" . ) .Values.dataplane.endpoints.control.port .Values.dataplane.endpoints.control.path -}} +{{- define "txdc.dataplane.url.signaling" -}} +{{- printf "http://%s-dataplane:%v%s" (include "txdc.fullname" . ) .Values.dataplane.endpoints.signaling.port .Values.dataplane.endpoints.signaling.path -}} {{- end }} {{/* diff --git a/charts/tractusx-connector-azure-vault/templates/deployment-controlplane.yaml b/charts/tractusx-connector-azure-vault/templates/deployment-controlplane.yaml index 61510d87d..c0b7c5697 100644 --- a/charts/tractusx-connector-azure-vault/templates/deployment-controlplane.yaml +++ b/charts/tractusx-connector-azure-vault/templates/deployment-controlplane.yaml @@ -299,18 +299,19 @@ spec: # see extension https://github.com/eclipse-tractusx/tractusx-edc/tree/main/edc-extensions/dataplane-selector-configuration - name: "EDC_DATAPLANE_SELECTOR_DEFAULTPLANE_URL" - value: {{ include "txdc.dataplane.url.control" . }}/transfer + value: {{ include "txdc.dataplane.url.signaling" . }}/v1/dataflows + - name: "EDC_DATAPLANE_SELECTOR_DEFAULTPLANE_TRANSFERTYPES" + value: "HttpData-PULL,AmazonS3-PUSH,AzureStorage-PUSH" - name: "EDC_DATAPLANE_SELECTOR_DEFAULTPLANE_SOURCETYPES" - value: "HttpData,AmazonS3" + value: "HttpData,AmazonS3,AzureStorage" - name: "EDC_DATAPLANE_SELECTOR_DEFAULTPLANE_DESTINATIONTYPES" - value: "HttpProxy,AmazonS3" + value: "HttpProxy,AmazonS3,AzureStorage" - name: "EDC_DATAPLANE_SELECTOR_DEFAULTPLANE_PROPERTIES" value: |- {{ printf "{ \"publicApiUrl\": \"%s\" }" (include "txdc.dataplane.url.public" . ) }} - ########### ## VAULT ## ########### diff --git a/charts/tractusx-connector-azure-vault/templates/deployment-dataplane.yaml b/charts/tractusx-connector-azure-vault/templates/deployment-dataplane.yaml index 95a332858..564ecdaa6 100644 --- a/charts/tractusx-connector-azure-vault/templates/deployment-dataplane.yaml +++ b/charts/tractusx-connector-azure-vault/templates/deployment-dataplane.yaml @@ -157,10 +157,10 @@ spec: value: {{ .Values.dataplane.endpoints.default.port | quote }} - name: "WEB_HTTP_DEFAULT_PATH" value: {{ .Values.dataplane.endpoints.default.path | quote }} - - name: "WEB_HTTP_CONTROL_PORT" - value: {{ .Values.dataplane.endpoints.control.port | quote }} - - name: "WEB_HTTP_CONTROL_PATH" - value: {{ .Values.dataplane.endpoints.control.path | quote }} + - name: "WEB_HTTP_SIGNALING_PORT" + value: {{ .Values.dataplane.endpoints.signaling.port | quote }} + - name: "WEB_HTTP_SIGNALING_PATH" + value: {{ .Values.dataplane.endpoints.signaling.path | quote }} - name: "WEB_HTTP_PUBLIC_PORT" value: {{ .Values.dataplane.endpoints.public.port | quote }} - name: "WEB_HTTP_PUBLIC_PATH" @@ -274,6 +274,9 @@ spec: {{- if .Values.dataplane.token.refresh.refresh_endpoint }} - name: "EDC_DATAPLANE_TOKEN_REFRESH_ENDPOINT" value: {{ .Values.dataplane.token.refresh.refresh_endpoint }} + {{- else}} + - name: "EDC_DATAPLANE_TOKEN_REFRESH_ENDPOINT" + value: {{ include "txdc.dataplane.url.public" . }}/token {{- end}} - name: "EDC_TRANSFER_PROXY_TOKEN_SIGNER_PRIVATEKEY_ALIAS" diff --git a/charts/tractusx-connector-azure-vault/templates/service-dataplane.yaml b/charts/tractusx-connector-azure-vault/templates/service-dataplane.yaml index 14230b9de..807eba45f 100644 --- a/charts/tractusx-connector-azure-vault/templates/service-dataplane.yaml +++ b/charts/tractusx-connector-azure-vault/templates/service-dataplane.yaml @@ -32,10 +32,10 @@ spec: targetPort: default protocol: TCP name: default - - port: {{ .Values.dataplane.endpoints.control.port }} - targetPort: control + - port: {{ .Values.dataplane.endpoints.signaling.port }} + targetPort: signaling protocol: TCP - name: control + name: signaling - port: {{ .Values.dataplane.endpoints.public.port }} targetPort: public protocol: TCP diff --git a/charts/tractusx-connector-azure-vault/values.yaml b/charts/tractusx-connector-azure-vault/values.yaml index e0bbc34c9..06d109072 100644 --- a/charts/tractusx-connector-azure-vault/values.yaml +++ b/charts/tractusx-connector-azure-vault/values.yaml @@ -353,9 +353,9 @@ dataplane: public: port: 8081 path: /api/public - control: + signaling: port: 8083 - path: /api/dataplane/control + path: /api/signaling proxy: port: 8186 path: /proxy diff --git a/charts/tractusx-connector-memory/README.md b/charts/tractusx-connector-memory/README.md index 76a3c8126..e94606898 100644 --- a/charts/tractusx-connector-memory/README.md +++ b/charts/tractusx-connector-memory/README.md @@ -76,7 +76,7 @@ helm install my-release tractusx-edc/tractusx-connector-memory --version 0.6.0 \ | runtime.debug.enabled | bool | `false` | | | runtime.debug.port | int | `1044` | | | runtime.debug.suspendOnStart | bool | `false` | | -| runtime.endpoints | object | `{"control":{"path":"/control","port":8083},"default":{"path":"/api","port":8080},"management":{"authKey":"password","path":"/management","port":8081},"protocol":{"path":"/api/v1/dsp","port":8084},"proxy":{"path":"/proxy","port":8186},"public":{"path":"/api/public","port":8086}}` | endpoints of the control plane | +| runtime.endpoints | object | `{"control":{"path":"/control","port":8083},"default":{"path":"/api","port":8080},"management":{"authKey":"password","path":"/management","port":8081},"protocol":{"path":"/api/v1/dsp","port":8084},"proxy":{"path":"/proxy","port":8186},"public":{"path":"/api/public","port":8086},"signaling":{"path":"/api/signaling","port":8087}}` | endpoints of the control plane | | runtime.endpoints.control | object | `{"path":"/control","port":8083}` | control api, used for internal control calls. can be added to the internal ingress, but should probably not | | runtime.endpoints.control.path | string | `"/control"` | path for incoming api calls | | runtime.endpoints.control.port | int | `8083` | port for incoming api calls | @@ -90,6 +90,8 @@ helm install my-release tractusx-edc/tractusx-connector-memory --version 0.6.0 \ | runtime.endpoints.protocol | object | `{"path":"/api/v1/dsp","port":8084}` | dsp api, used for inter connector communication and must be internet facing | | runtime.endpoints.protocol.path | string | `"/api/v1/dsp"` | path for incoming api calls | | runtime.endpoints.protocol.port | int | `8084` | port for incoming api calls | +| runtime.endpoints.signaling.path | string | `"/api/signaling"` | path for incoming api calls | +| runtime.endpoints.signaling.port | int | `8087` | port for incoming api calls | | runtime.env | object | `{}` | | | runtime.envConfigMapNames | list | `[]` | | | runtime.envSecretNames | list | `[]` | | diff --git a/charts/tractusx-connector-memory/templates/_helpers.tpl b/charts/tractusx-connector-memory/templates/_helpers.tpl index c65ba8c52..84f590f08 100644 --- a/charts/tractusx-connector-memory/templates/_helpers.tpl +++ b/charts/tractusx-connector-memory/templates/_helpers.tpl @@ -118,10 +118,10 @@ Control URL {{- end }} {{/* -Data Control URL +Data Signaling URL */}} -{{- define "txdc.dataplane.url.control" -}} -{{- printf "http://%s-dataplane:%v%s" (include "txdc.fullname" . ) .Values.runtime.endpoints.control.port .Values.runtime.endpoints.control.path -}} +{{- define "txdc.dataplane.url.signaling" -}} +{{- printf "http://%s-dataplane:%v%s" (include "txdc.fullname" . ) .Values.runtime.endpoints.signaling.port .Values.runtime.endpoints.signaling.path -}} {{- end }} {{/* diff --git a/charts/tractusx-connector-memory/templates/deployment-runtime.yaml b/charts/tractusx-connector-memory/templates/deployment-runtime.yaml index a5d4c0e3f..de0168256 100644 --- a/charts/tractusx-connector-memory/templates/deployment-runtime.yaml +++ b/charts/tractusx-connector-memory/templates/deployment-runtime.yaml @@ -177,6 +177,10 @@ spec: value: {{ .Values.runtime.endpoints.control.port | quote }} - name: "WEB_HTTP_CONTROL_PATH" value: {{ .Values.runtime.endpoints.control.path | quote }} + - name: "WEB_HTTP_SIGNALING_PORT" + value: {{ .Values.runtime.endpoints.signaling.port | quote }} + - name: "WEB_HTTP_SIGNALING_PATH" + value: {{ .Values.runtime.endpoints.signaling.path | quote }} - name: "WEB_HTTP_PROTOCOL_PORT" value: {{ .Values.runtime.endpoints.protocol.port | quote }} - name: "WEB_HTTP_PROTOCOL_PATH" @@ -230,7 +234,7 @@ spec: # see extension https://github.com/eclipse-tractusx/tractusx-edc/tree/develop/edc-extensions/dataplane-selector-configuration - name: "EDC_DATAPLANE_SELECTOR_DEFAULTPLANE_URL" - value: {{ include "txdc.dataplane.url.control" . }}/transfer + value: {{ include "txdc.dataplane.url.signaling" . }}/v1/dataflows - name: "EDC_DATAPLANE_SELECTOR_DEFAULTPLANE_SOURCETYPES" value: "HttpData,AmazonS3" - name: "EDC_DATAPLANE_SELECTOR_DEFAULTPLANE_DESTINATIONTYPES" @@ -260,6 +264,9 @@ spec: {{- if .Values.runtime.token.refresh.refresh_endpoint }} - name: "EDC_DATAPLANE_TOKEN_REFRESH_ENDPOINT" value: {{ .Values.runtime.token.refresh.refresh_endpoint }} + {{- else }} + - name: "EDC_DATAPLANE_TOKEN_REFRESH_ENDPOINT" + value: {{ include "txdc.dataplane.url.public" . }}/token {{- end}} - name: "EDC_TRANSFER_PROXY_TOKEN_SIGNER_PRIVATEKEY_ALIAS" diff --git a/charts/tractusx-connector-memory/templates/service-runtime.yaml b/charts/tractusx-connector-memory/templates/service-runtime.yaml index d6c441b85..e7536bbcb 100644 --- a/charts/tractusx-connector-memory/templates/service-runtime.yaml +++ b/charts/tractusx-connector-memory/templates/service-runtime.yaml @@ -51,5 +51,9 @@ spec: targetPort: public protocol: TCP name: public + - port: {{ .Values.runtime.endpoints.signaling.port }} + targetPort: signaling + protocol: TCP + name: signaling selector: {{- include "txdc.runtime.selectorLabels" . | nindent 4 }} diff --git a/charts/tractusx-connector-memory/values.yaml b/charts/tractusx-connector-memory/values.yaml index 3289edfcf..7f3cbd2af 100644 --- a/charts/tractusx-connector-memory/values.yaml +++ b/charts/tractusx-connector-memory/values.yaml @@ -121,6 +121,11 @@ runtime: proxy: port: 8186 path: /proxy + signaling: + # -- port for incoming api calls + port: 8087 + # -- path for incoming api calls + path: /api/signaling businessPartnerValidation: log: diff --git a/charts/tractusx-connector/README.md b/charts/tractusx-connector/README.md index a6db95db8..67bfa298f 100644 --- a/charts/tractusx-connector/README.md +++ b/charts/tractusx-connector/README.md @@ -172,8 +172,6 @@ helm install my-release tractusx-edc/tractusx-connector --version 0.6.0 \ | dataplane.debug.enabled | bool | `false` | | | dataplane.debug.port | int | `1044` | | | dataplane.debug.suspendOnStart | bool | `false` | | -| dataplane.endpoints.control.path | string | `"/api/dataplane/control"` | | -| dataplane.endpoints.control.port | int | `8083` | | | dataplane.endpoints.default.path | string | `"/api"` | | | dataplane.endpoints.default.port | int | `8080` | | | dataplane.endpoints.metrics.path | string | `"/metrics"` | | @@ -183,6 +181,8 @@ helm install my-release tractusx-edc/tractusx-connector --version 0.6.0 \ | dataplane.endpoints.proxy.port | int | `8186` | | | dataplane.endpoints.public.path | string | `"/api/public"` | | | dataplane.endpoints.public.port | int | `8081` | | +| dataplane.endpoints.signaling.path | string | `"/api/signaling"` | | +| dataplane.endpoints.signaling.port | int | `8083` | | | dataplane.env | object | `{}` | | | dataplane.envConfigMapNames | list | `[]` | | | dataplane.envSecretNames | list | `[]` | | diff --git a/charts/tractusx-connector/templates/_helpers.tpl b/charts/tractusx-connector/templates/_helpers.tpl index 46bc283dc..21581f158 100644 --- a/charts/tractusx-connector/templates/_helpers.tpl +++ b/charts/tractusx-connector/templates/_helpers.tpl @@ -143,10 +143,10 @@ Control Plane URL {{- end }} {{/* -Data Control URL +Data Signaling URL */}} -{{- define "txdc.dataplane.url.control" -}} -{{- printf "http://%s-dataplane:%v%s" (include "txdc.fullname" . ) .Values.dataplane.endpoints.control.port .Values.dataplane.endpoints.control.path -}} +{{- define "txdc.dataplane.url.signaling" -}} +{{- printf "http://%s-dataplane:%v%s" (include "txdc.fullname" . ) .Values.dataplane.endpoints.signaling.port .Values.dataplane.endpoints.signaling.path -}} {{- end }} {{/* diff --git a/charts/tractusx-connector/templates/deployment-controlplane.yaml b/charts/tractusx-connector/templates/deployment-controlplane.yaml index f41a2a633..9ab02e54a 100644 --- a/charts/tractusx-connector/templates/deployment-controlplane.yaml +++ b/charts/tractusx-connector/templates/deployment-controlplane.yaml @@ -300,11 +300,13 @@ spec: # see extension https://github.com/eclipse-tractusx/tractusx-edc/tree/main/edc-extensions/dataplane-selector-configuration - name: "EDC_DATAPLANE_SELECTOR_DEFAULTPLANE_URL" - value: {{ include "txdc.dataplane.url.control" . }}/transfer + value: {{ include "txdc.dataplane.url.signaling" . }}/v1/dataflows + - name: "EDC_DATAPLANE_SELECTOR_DEFAULTPLANE_TRANSFERTYPES" + value: "HttpData-PULL,AmazonS3-PUSH,AzureStorage-PUSH" - name: "EDC_DATAPLANE_SELECTOR_DEFAULTPLANE_SOURCETYPES" - value: "HttpData,AmazonS3" + value: "HttpData,AmazonS3,AzureStorage" - name: "EDC_DATAPLANE_SELECTOR_DEFAULTPLANE_DESTINATIONTYPES" - value: "HttpProxy,AmazonS3" + value: "HttpProxy,AmazonS3,AzureStorage" - name: "EDC_DATAPLANE_SELECTOR_DEFAULTPLANE_PROPERTIES" value: |- {{ printf "{ \"publicApiUrl\": \"%s\" }" (include "txdc.dataplane.url.public" . ) }} diff --git a/charts/tractusx-connector/templates/deployment-dataplane.yaml b/charts/tractusx-connector/templates/deployment-dataplane.yaml index c22138a97..1b633269b 100644 --- a/charts/tractusx-connector/templates/deployment-dataplane.yaml +++ b/charts/tractusx-connector/templates/deployment-dataplane.yaml @@ -157,10 +157,10 @@ spec: value: {{ .Values.dataplane.endpoints.default.port | quote }} - name: "WEB_HTTP_DEFAULT_PATH" value: {{ .Values.dataplane.endpoints.default.path | quote }} - - name: "WEB_HTTP_CONTROL_PORT" - value: {{ .Values.dataplane.endpoints.control.port | quote }} - - name: "WEB_HTTP_CONTROL_PATH" - value: {{ .Values.dataplane.endpoints.control.path | quote }} + - name: "WEB_HTTP_SIGNALING_PORT" + value: {{ .Values.dataplane.endpoints.signaling.port | quote }} + - name: "WEB_HTTP_SIGNALING_PATH" + value: {{ .Values.dataplane.endpoints.signaling.path | quote }} - name: "WEB_HTTP_PUBLIC_PORT" value: {{ .Values.dataplane.endpoints.public.port | quote }} - name: "WEB_HTTP_PUBLIC_PATH" @@ -273,6 +273,9 @@ spec: {{- if .Values.dataplane.token.refresh.refresh_endpoint }} - name: "EDC_DATAPLANE_TOKEN_REFRESH_ENDPOINT" value: {{ .Values.dataplane.token.refresh.refresh_endpoint }} + {{- else}} + - name: "EDC_DATAPLANE_TOKEN_REFRESH_ENDPOINT" + value: {{ include "txdc.dataplane.url.public" . }}/token {{- end}} - name: "EDC_TRANSFER_PROXY_TOKEN_SIGNER_PRIVATEKEY_ALIAS" diff --git a/charts/tractusx-connector/templates/service-dataplane.yaml b/charts/tractusx-connector/templates/service-dataplane.yaml index 0f1fc5e8c..97e8c07ea 100644 --- a/charts/tractusx-connector/templates/service-dataplane.yaml +++ b/charts/tractusx-connector/templates/service-dataplane.yaml @@ -36,10 +36,10 @@ spec: targetPort: default protocol: TCP name: default - - port: {{ .Values.dataplane.endpoints.control.port }} - targetPort: control + - port: {{ .Values.dataplane.endpoints.signaling.port }} + targetPort: signaling protocol: TCP - name: control + name: signaling - port: {{ .Values.dataplane.endpoints.public.port }} targetPort: public protocol: TCP diff --git a/charts/tractusx-connector/values.yaml b/charts/tractusx-connector/values.yaml index 70e046c0b..160445e09 100644 --- a/charts/tractusx-connector/values.yaml +++ b/charts/tractusx-connector/values.yaml @@ -351,9 +351,9 @@ dataplane: public: port: 8081 path: /api/public - control: + signaling: port: 8083 - path: /api/dataplane/control + path: /api/signaling proxy: port: 8186 path: /proxy diff --git a/core/json-ld-core/src/main/java/org/eclipse/tractusx/edc/jsonld/JsonLdExtension.java b/core/json-ld-core/src/main/java/org/eclipse/tractusx/edc/jsonld/JsonLdExtension.java index a4b9e4038..43cdefc81 100644 --- a/core/json-ld-core/src/main/java/org/eclipse/tractusx/edc/jsonld/JsonLdExtension.java +++ b/core/json-ld-core/src/main/java/org/eclipse/tractusx/edc/jsonld/JsonLdExtension.java @@ -35,6 +35,8 @@ import static java.lang.String.format; import static java.nio.file.StandardCopyOption.REPLACE_EXISTING; import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.EDC_CONTEXT; +import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.TX_AUTH_NS; +import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.TX_AUTH_PREFIX; import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.TX_CONTEXT; import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.TX_NAMESPACE; import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.TX_PREFIX; @@ -66,6 +68,7 @@ public class JsonLdExtension implements ServiceExtension { @Override public void initialize(ServiceExtensionContext context) { jsonLdService.registerNamespace(TX_PREFIX, TX_NAMESPACE); + jsonLdService.registerNamespace(TX_AUTH_PREFIX, TX_AUTH_NS); FILES.entrySet().stream().map(this::mapToFile) .forEach(result -> result.onSuccess(entry -> jsonLdService.registerCachedDocument(entry.getKey(), entry.getValue().toURI())) .onFailure(failure -> monitor.warning("Failed to register cached json-ld document: " + failure.getFailureDetail()))); diff --git a/edc-controlplane/edc-controlplane-base/build.gradle.kts b/edc-controlplane/edc-controlplane-base/build.gradle.kts index dc79e212a..c3ef42249 100644 --- a/edc-controlplane/edc-controlplane-base/build.gradle.kts +++ b/edc-controlplane/edc-controlplane-base/build.gradle.kts @@ -41,7 +41,11 @@ dependencies { // needed for IATP integration runtimeOnly(project(":core:json-ld-core")) runtimeOnly(libs.edc.core.did) + runtimeOnly(libs.edc.identity.did.web) runtimeOnly(libs.edc.core.identitytrust) + runtimeOnly(libs.edc.identity.trust.transform) + runtimeOnly(libs.edc.identity.trust.issuers.configuration) + runtimeOnly(project(":edc-extensions:iatp:tx-iatp")) runtimeOnly(project(":edc-extensions:iatp:tx-iatp-sts-dim")) runtimeOnly(project(":edc-extensions:bdrs-client")) runtimeOnly(project(":edc-extensions:data-flow-properties-provider")) diff --git a/edc-dataplane/edc-dataplane-base/build.gradle.kts b/edc-dataplane/edc-dataplane-base/build.gradle.kts index 41a73a75a..e7285164f 100644 --- a/edc-dataplane/edc-dataplane-base/build.gradle.kts +++ b/edc-dataplane/edc-dataplane-base/build.gradle.kts @@ -32,6 +32,7 @@ dependencies { runtimeOnly(libs.edc.jsonld) // needed by the DataPlaneSignalingApi runtimeOnly(libs.edc.core.did) // for the DID Public Key Resolver + runtimeOnly(libs.edc.identity.did.web) runtimeOnly(libs.edc.config.filesystem) runtimeOnly(libs.edc.auth.tokenbased) runtimeOnly(libs.edc.dpf.awss3) diff --git a/edc-extensions/data-flow-properties-provider/build.gradle.kts b/edc-extensions/data-flow-properties-provider/build.gradle.kts index a1c8e165b..1bb930aa9 100644 --- a/edc-extensions/data-flow-properties-provider/build.gradle.kts +++ b/edc-extensions/data-flow-properties-provider/build.gradle.kts @@ -24,6 +24,7 @@ plugins { dependencies { implementation(libs.edc.spi.transfer) + implementation(project(":spi:core-spi")) implementation(project(":spi:bdrs-client-spi")) testImplementation(libs.edc.junit) diff --git a/edc-extensions/data-flow-properties-provider/src/main/java/org/eclipse/tractusx/edc/flow/TxDataFlowPropertiesProvider.java b/edc-extensions/data-flow-properties-provider/src/main/java/org/eclipse/tractusx/edc/flow/TxDataFlowPropertiesProvider.java index d1cc7d0b4..d524d3c55 100644 --- a/edc-extensions/data-flow-properties-provider/src/main/java/org/eclipse/tractusx/edc/flow/TxDataFlowPropertiesProvider.java +++ b/edc-extensions/data-flow-properties-provider/src/main/java/org/eclipse/tractusx/edc/flow/TxDataFlowPropertiesProvider.java @@ -29,13 +29,14 @@ import java.util.Map; +import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.AUDIENCE_PROPERTY; + /** * Extension of {@link DataFlowPropertiesProvider} which provides additional properties in the {@link DataFlowStartMessage} * like the DID of the counter-party BPN. The resolution is made with the {@link BdrsClient} */ public class TxDataFlowPropertiesProvider implements DataFlowPropertiesProvider { - private static final String AUDIENCE_PROPERTY = "audience"; private final BdrsClient bdrsClient; diff --git a/edc-extensions/data-flow-properties-provider/src/test/java/org/eclipse/tractusx/edc/flow/TxDataFlowPropertiesProviderTest.java b/edc-extensions/data-flow-properties-provider/src/test/java/org/eclipse/tractusx/edc/flow/TxDataFlowPropertiesProviderTest.java index f757d5df9..0c7efcf05 100644 --- a/edc-extensions/data-flow-properties-provider/src/test/java/org/eclipse/tractusx/edc/flow/TxDataFlowPropertiesProviderTest.java +++ b/edc-extensions/data-flow-properties-provider/src/test/java/org/eclipse/tractusx/edc/flow/TxDataFlowPropertiesProviderTest.java @@ -26,6 +26,7 @@ import org.junit.jupiter.api.Test; import static org.eclipse.edc.junit.assertions.AbstractResultAssert.assertThat; +import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.AUDIENCE_PROPERTY; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -45,7 +46,7 @@ void propertiesFor() { var result = provider.propertiesFor(TransferProcess.Builder.newInstance().build(), Policy.Builder.newInstance().assignee(bpn).build()); assertThat(result).isSucceeded().satisfies(properties -> { - Assertions.assertThat(properties).containsEntry("audience", did); + Assertions.assertThat(properties).containsEntry(AUDIENCE_PROPERTY, did); }); } diff --git a/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-consumer-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/consumer/api/asset/ConsumerAssetRequestController.java b/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-consumer-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/consumer/api/asset/ConsumerAssetRequestController.java index 7c1e8d44a..b2aa6c08e 100644 --- a/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-consumer-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/consumer/api/asset/ConsumerAssetRequestController.java +++ b/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-consumer-api/src/main/java/org/eclipse/tractusx/edc/dataplane/proxy/consumer/api/asset/ConsumerAssetRequestController.java @@ -149,7 +149,7 @@ private DataAddress dataPlaneAddress(DataAddress edr) { .baseUrl(endpoint) .proxyQueryParams("true") .proxyPath("true") - .property(HEADER_AUTHORIZATION, BEARER_PREFIX + token) + .property(HEADER_AUTHORIZATION, token) .build(); } diff --git a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/build.gradle.kts b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/build.gradle.kts index 71d956150..19c54f505 100644 --- a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/build.gradle.kts +++ b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/build.gradle.kts @@ -24,6 +24,7 @@ plugins { dependencies { api(project(":spi:tokenrefresh-spi")) api(project(":spi:core-spi")) + implementation(project(":core:core-utils")) implementation(libs.edc.spi.core) implementation(libs.edc.spi.token) implementation(libs.edc.spi.keys) diff --git a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceExtension.java b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceExtension.java index 3dd2b5421..75c5d8b5e 100644 --- a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceExtension.java +++ b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceExtension.java @@ -36,6 +36,7 @@ import org.eclipse.edc.spi.types.TypeManager; import org.eclipse.edc.token.JwtGenerationService; import org.eclipse.edc.token.spi.TokenValidationService; +import org.eclipse.tractusx.edc.core.utils.RequiredConfigWarnings; import org.eclipse.tractusx.edc.spi.tokenrefresh.dataplane.DataPlaneTokenRefreshService; import org.jetbrains.annotations.NotNull; @@ -60,6 +61,10 @@ public class DataPlaneTokenRefreshServiceExtension implements ServiceExtension { public static final String TOKEN_VERIFIER_PUBLIC_KEY_ALIAS = "edc.transfer.proxy.token.verifier.publickey.alias"; @Setting(value = "Expiry time of access token in seconds", defaultValue = DEFAULT_TOKEN_EXPIRY_SECONDS + "") public static final String TOKEN_EXPIRY_SECONDS_PROPERTY = "edc.dataplane.token.expiry"; + + @Setting(value = "DID of this connector", required = true) + private static final String PARTICIPANT_DID_PROPERTY = "edc.iam.issuer.id"; + @Inject private TokenValidationService tokenValidationService; @Inject @@ -112,7 +117,7 @@ private DataPlaneTokenRefreshServiceImpl getTokenRefreshService(ServiceExtension monitor.debug("Token refresh endpoint: %s".formatted(refreshEndpoint)); monitor.debug("Token refresh time tolerance: %d s".formatted(expiryTolerance)); tokenRefreshService = new DataPlaneTokenRefreshServiceImpl(clock, tokenValidationService, didPkResolver, localPublicKeyService, accessTokenDataStore, new JwtGenerationService(), - getPrivateKeySupplier(context), context.getMonitor(), refreshEndpoint, expiryTolerance, tokenExpiry, + getPrivateKeySupplier(context), context.getMonitor(), refreshEndpoint, getOwnDid(context), expiryTolerance, tokenExpiry, () -> context.getConfig().getString(TOKEN_VERIFIER_PUBLIC_KEY_ALIAS), vault, typeManager.getMapper()); } return tokenRefreshService; @@ -133,6 +138,13 @@ private String getRefreshEndpointConfig(ServiceExtensionContext context, Monitor return refreshEndpoint; } + private String getOwnDid(ServiceExtensionContext context) { + var did = context.getConfig().getString(PARTICIPANT_DID_PROPERTY, null); + if (did == null) { + RequiredConfigWarnings.warningNotPresent(context.getMonitor().withPrefix("DataPlane Token Refresh"), PARTICIPANT_DID_PROPERTY); + } + return did; + } @NotNull private Supplier getPrivateKeySupplier(ServiceExtensionContext context) { diff --git a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImpl.java b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImpl.java index 64991f0f2..06c7c2000 100644 --- a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImpl.java +++ b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImpl.java @@ -64,7 +64,9 @@ import static org.eclipse.edc.jwt.spi.JwtRegisteredClaimNames.AUDIENCE; import static org.eclipse.edc.jwt.spi.JwtRegisteredClaimNames.EXPIRATION_TIME; +import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.AUDIENCE_PROPERTY; import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.EDR_PROPERTY_EXPIRES_IN; +import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.EDR_PROPERTY_REFRESH_AUDIENCE; import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.EDR_PROPERTY_REFRESH_ENDPOINT; import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.EDR_PROPERTY_REFRESH_TOKEN; @@ -86,10 +88,12 @@ public class DataPlaneTokenRefreshServiceImpl implements DataPlaneTokenRefreshSe private final Supplier publicKeyIdSupplier; private final Monitor monitor; private final String refreshEndpoint; + private final String ownDid; private final Clock clock; private final Vault vault; private final ObjectMapper objectMapper; + public DataPlaneTokenRefreshServiceImpl(Clock clock, TokenValidationService tokenValidationService, DidPublicKeyResolver publicKeyResolver, @@ -99,6 +103,7 @@ public DataPlaneTokenRefreshServiceImpl(Clock clock, Supplier privateKeySupplier, Monitor monitor, String refreshEndpoint, + String ownDid, int tokenExpiryToleranceSeconds, long tokenExpirySeconds, Supplier publicKeyIdSupplier, @@ -114,6 +119,7 @@ public DataPlaneTokenRefreshServiceImpl(Clock clock, this.refreshEndpoint = refreshEndpoint; this.clock = clock; this.publicKeyIdSupplier = publicKeyIdSupplier; + this.ownDid = ownDid; this.vault = vault; this.objectMapper = objectMapper; this.tokenExpirySeconds = tokenExpirySeconds; @@ -148,7 +154,7 @@ public DataPlaneTokenRefreshServiceImpl(Clock clock, public Result refreshToken(String refreshToken, String authenticationToken) { authenticationToken = authenticationToken.replace("Bearer", "").trim(); - + var authTokenRes = tokenValidationService.validate(authenticationToken, publicKeyResolver, authenticationTokenValidationRules); if (authTokenRes.failed()) { return Result.failure("Authentication token validation failed: %s".formatted(authTokenRes.getFailureDetail())); @@ -221,10 +227,16 @@ public Result obtainToken(TokenParameters tokenParameters, tokenExpirySeconds, refreshEndpoint)); // the refresh token information must be returned in the EDR + var audience = additionalDataForStorage.get(AUDIENCE_PROPERTY); + + if (audience == null) { + return Result.failure("Missing audience in the additional properties"); + } var edrAdditionalData = new HashMap<>(additionalTokenData); edrAdditionalData.put(EDR_PROPERTY_REFRESH_TOKEN, refreshTokenResult.getContent().tokenRepresentation().getToken()); edrAdditionalData.put(EDR_PROPERTY_EXPIRES_IN, String.valueOf(tokenExpirySeconds)); edrAdditionalData.put(EDR_PROPERTY_REFRESH_ENDPOINT, refreshEndpoint); + edrAdditionalData.put(EDR_PROPERTY_REFRESH_AUDIENCE, audience); var edrTokenRepresentation = TokenRepresentation.Builder.newInstance() .token(accessTokenResult.getContent().tokenRepresentation().getToken()) // the access token diff --git a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/rules/AuthTokenAudienceRule.java b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/rules/AuthTokenAudienceRule.java index 84acf8f7e..49bf722e3 100644 --- a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/rules/AuthTokenAudienceRule.java +++ b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/main/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/rules/AuthTokenAudienceRule.java @@ -30,6 +30,7 @@ import java.util.Map; import static org.eclipse.tractusx.edc.dataplane.tokenrefresh.core.TokenFunctions.getTokenId; +import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.AUDIENCE_PROPERTY; /** @@ -37,7 +38,6 @@ * that is associated with that token (using the {@code jti} claim). */ public class AuthTokenAudienceRule implements TokenValidationRule { - private static final String AUDIENCE_PROPERTY = "audience"; private final AccessTokenDataStore store; public AuthTokenAudienceRule(AccessTokenDataStore store) { diff --git a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImplComponentTest.java b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImplComponentTest.java index 1fff7c112..ee73ecc67 100644 --- a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImplComponentTest.java +++ b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImplComponentTest.java @@ -54,6 +54,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.eclipse.edc.junit.assertions.AbstractResultAssert.assertThat; +import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.AUDIENCE_PROPERTY; import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.EDR_PROPERTY_EXPIRES_IN; import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.EDR_PROPERTY_REFRESH_ENDPOINT; import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.EDR_PROPERTY_REFRESH_TOKEN; @@ -94,6 +95,7 @@ void setup() throws JOSEException { () -> privateKey, mock(), TEST_REFRESH_ENDPOINT, + PROVIDER_DID, 1, 300L, () -> providerKey.getKeyID(), @@ -111,7 +113,7 @@ void setup() throws JOSEException { @Test void obtainToken() { var tokenId = "test-token-id"; - var edr = tokenRefreshService.obtainToken(tokenParams(tokenId), DataAddress.Builder.newInstance().type("test-type").build(), Map.of("audience", CONSUMER_DID)); + var edr = tokenRefreshService.obtainToken(tokenParams(tokenId), DataAddress.Builder.newInstance().type("test-type").build(), Map.of(AUDIENCE_PROPERTY, CONSUMER_DID)); assertThat(edr).isSucceeded(); // assert access token contents assertThat(asClaims(edr.getContent().getToken())) @@ -131,7 +133,7 @@ void obtainToken() { assertThat(storedData).isNotNull(); assertThat(storedData.additionalProperties()) .hasSize(2) - .containsEntry("audience", CONSUMER_DID) + .containsEntry(AUDIENCE_PROPERTY, CONSUMER_DID) .containsEntry("authType", "bearer"); } @@ -141,7 +143,7 @@ void obtainToken() { void refresh_success() throws JOSEException { var tokenId = "test-token-id"; - var edr = tokenRefreshService.obtainToken(tokenParams(tokenId), DataAddress.Builder.newInstance().type("test-type").build(), Map.of("audience", CONSUMER_DID)) + var edr = tokenRefreshService.obtainToken(tokenParams(tokenId), DataAddress.Builder.newInstance().type("test-type").build(), Map.of(AUDIENCE_PROPERTY, CONSUMER_DID)) .orElseThrow(f -> new RuntimeException(f.getFailureDetail())); var accessToken = edr.getToken(); @@ -169,7 +171,7 @@ void refresh_originalTokenWasIssuedToDifferentPrincipal() throws JOSEException { var tokenId = "test-token-id"; - var edr = tokenRefreshService.obtainToken(tokenParams(tokenId), DataAddress.Builder.newInstance().type("test-type").build(), Map.of("audience", "did:web:trudy")) + var edr = tokenRefreshService.obtainToken(tokenParams(tokenId), DataAddress.Builder.newInstance().type("test-type").build(), Map.of(AUDIENCE_PROPERTY, "did:web:trudy")) .orElseThrow(f -> new RuntimeException(f.getFailureDetail())); // bob attempts to create an auth token with an EDR he stole from trudy @@ -192,7 +194,7 @@ void refresh_issuerNotVerifiable() throws JOSEException { when(didPkResolverMock.resolveKey(eq(trudyKey.getKeyID()))).thenReturn(Result.success(trudyKey.toPublicKey())); var tokenId = "test-token-id"; - var edr = tokenRefreshService.obtainToken(tokenParams(tokenId), DataAddress.Builder.newInstance().type("test-type").build(), Map.of("audience", "did:web:trudy")) + var edr = tokenRefreshService.obtainToken(tokenParams(tokenId), DataAddress.Builder.newInstance().type("test-type").build(), Map.of(AUDIENCE_PROPERTY, "did:web:trudy")) .orElseThrow(f -> new RuntimeException(f.getFailureDetail())); // bob poses as trudy, using her key-ID and DID, but has to use his own private key @@ -211,7 +213,7 @@ void refresh_issuerNotVerifiable() throws JOSEException { @Test void refresh_whenNoAccessTokenClaim() throws JOSEException { var tokenId = "test-token-id"; - var edr = tokenRefreshService.obtainToken(tokenParams(tokenId), DataAddress.Builder.newInstance().type("test-type").build(), Map.of("audience", CONSUMER_DID)) + var edr = tokenRefreshService.obtainToken(tokenParams(tokenId), DataAddress.Builder.newInstance().type("test-type").build(), Map.of(AUDIENCE_PROPERTY, CONSUMER_DID)) .orElseThrow(f -> new RuntimeException(f.getFailureDetail())); var accessToken = edr.getToken(); @@ -231,7 +233,7 @@ void refresh_whenNoAccessTokenClaim() throws JOSEException { @Test void refresh_whenIssNotEqualToSub() throws JOSEException { var tokenId = "test-token-id"; - var edr = tokenRefreshService.obtainToken(tokenParams(tokenId), DataAddress.Builder.newInstance().type("test-type").build(), Map.of("audience", CONSUMER_DID)) + var edr = tokenRefreshService.obtainToken(tokenParams(tokenId), DataAddress.Builder.newInstance().type("test-type").build(), Map.of(AUDIENCE_PROPERTY, CONSUMER_DID)) .orElseThrow(f -> new RuntimeException(f.getFailureDetail())); var accessToken = edr.getToken(); @@ -259,7 +261,7 @@ void resolve_whenExpired_shouldFail() { .claims(JwtRegisteredClaimNames.ISSUED_AT, Instant.now().minusSeconds(600).getEpochSecond()) .claims(JwtRegisteredClaimNames.EXPIRATION_TIME, Instant.now().minusSeconds(300).getEpochSecond()) .build(), - DataAddress.Builder.newInstance().type("test-type").build(), Map.of("audience", CONSUMER_DID)) + DataAddress.Builder.newInstance().type("test-type").build(), Map.of(AUDIENCE_PROPERTY, CONSUMER_DID)) .orElseThrow(f -> new RuntimeException(f.getFailureDetail())); assertThat(tokenRefreshService.resolve(edr.getToken())).isFailed() @@ -274,7 +276,7 @@ void resolve_success() { var edr = tokenRefreshService.obtainToken(tokenParamsBuilder(tokenId) .claims(JwtRegisteredClaimNames.ISSUED_AT, Instant.now().getEpochSecond()) .build(), - DataAddress.Builder.newInstance().type("test-type").build(), Map.of("audience", CONSUMER_DID)) + DataAddress.Builder.newInstance().type("test-type").build(), Map.of(AUDIENCE_PROPERTY, CONSUMER_DID)) .orElseThrow(f -> new RuntimeException(f.getFailureDetail())); assertThat(tokenRefreshService.resolve(edr.getToken())).isSucceeded(); @@ -287,7 +289,7 @@ void resolve_notFound() { var edr = tokenRefreshService.obtainToken(tokenParamsBuilder(tokenId) .claims(JwtRegisteredClaimNames.ISSUED_AT, Instant.now().getEpochSecond()) .build(), - DataAddress.Builder.newInstance().type("test-type").build(), Map.of("audience", CONSUMER_DID)) + DataAddress.Builder.newInstance().type("test-type").build(), Map.of(AUDIENCE_PROPERTY, CONSUMER_DID)) .orElseThrow(f -> new RuntimeException(f.getFailureDetail())); tokenDataStore.deleteById(tokenId).orElseThrow(f -> new AssertionError(f.getFailureDetail())); diff --git a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImplTest.java b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImplTest.java index 173b981ef..1a7ec0ca7 100644 --- a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImplTest.java +++ b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/DataPlaneTokenRefreshServiceImplTest.java @@ -44,6 +44,7 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.eclipse.edc.junit.assertions.AbstractResultAssert.assertThat; import static org.eclipse.tractusx.edc.dataplane.tokenrefresh.core.TestFunctions.createJwt; +import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.AUDIENCE_PROPERTY; import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.EDR_PROPERTY_EXPIRES_IN; import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.EDR_PROPERTY_REFRESH_ENDPOINT; import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.EDR_PROPERTY_REFRESH_TOKEN; @@ -70,7 +71,7 @@ class DataPlaneTokenRefreshServiceImplTest { private final DataPlaneTokenRefreshServiceImpl accessTokenService = new DataPlaneTokenRefreshServiceImpl(Clock.systemUTC(), tokenValidationService, didPublicKeyResolver, localPublicKeyService, accessTokenDataStore, tokenGenService, mock(), mock(), - "https://example.com", 1, 300L, + "https://example.com", "did:web:provider", 1, 300L, () -> "keyid", mock(), new ObjectMapper()); @@ -82,7 +83,7 @@ void obtainToken() { when(tokenGenService.generate(any(), any(TokenDecorator[].class))).thenReturn(Result.success(TokenRepresentation.Builder.newInstance().token("foo-token").build())); when(accessTokenDataStore.store(any(AccessTokenData.class))).thenReturn(StoreResult.success()); - var result = accessTokenService.obtainToken(params, address, Map.of("fizz", "buzz", "refreshToken", "getsOverwritten")); + var result = accessTokenService.obtainToken(params, address, Map.of("fizz", "buzz", "refreshToken", "getsOverwritten", AUDIENCE_PROPERTY, "audience")); assertThat(result).isSucceeded().extracting(TokenRepresentation::getToken).isEqualTo("foo-token"); assertThat(result.getContent().getAdditional()) .containsKeys("fizz", EDR_PROPERTY_REFRESH_TOKEN, EDR_PROPERTY_EXPIRES_IN, EDR_PROPERTY_REFRESH_ENDPOINT) @@ -100,7 +101,7 @@ void obtainToken_withAdditionalProperties() { when(tokenGenService.generate(any(), any(TokenDecorator[].class))).thenReturn(Result.success(TokenRepresentation.Builder.newInstance().token("foo-token").build())); when(accessTokenDataStore.store(any(AccessTokenData.class))).thenReturn(StoreResult.success()); - var result = accessTokenService.obtainToken(params, address, Map.of("foo", "bar")); + var result = accessTokenService.obtainToken(params, address, Map.of("foo", "bar", AUDIENCE_PROPERTY, "audience")); assertThat(result).isSucceeded().extracting(TokenRepresentation::getToken).isEqualTo("foo-token"); verify(tokenGenService, times(2)).generate(any(), any(TokenDecorator[].class)); @@ -124,7 +125,7 @@ void obtainToken_noTokenId() { when(tokenGenService.generate(any(), any(TokenDecorator[].class))).thenReturn(Result.success(TokenRepresentation.Builder.newInstance().token("foo-token").build())); when(accessTokenDataStore.store(any(AccessTokenData.class))).thenReturn(StoreResult.success()); - var result = accessTokenService.obtainToken(params, address, Map.of()); + var result = accessTokenService.obtainToken(params, address, Map.of(AUDIENCE_PROPERTY, "audience")); assertThat(result).isSucceeded().extracting(TokenRepresentation::getToken).isEqualTo("foo-token"); verify(tokenGenService, times(2)).generate(any(), any(TokenDecorator[].class)); @@ -153,7 +154,7 @@ void obtainToken_storingFails() { when(tokenGenService.generate(any(), any(TokenDecorator[].class))).thenReturn(Result.success(TokenRepresentation.Builder.newInstance().token("foo-token").build())); when(accessTokenDataStore.store(any(AccessTokenData.class))).thenReturn(StoreResult.alreadyExists("test failure")); - var result = accessTokenService.obtainToken(params, address, Map.of()); + var result = accessTokenService.obtainToken(params, address, Map.of(AUDIENCE_PROPERTY, "audience")); assertThat(result).isFailed().detail().isEqualTo("test failure"); verify(tokenGenService, times(2)).generate(any(), any(TokenDecorator[].class)); diff --git a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/rules/AuthTokenAudienceRuleTest.java b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/rules/AuthTokenAudienceRuleTest.java index da71521bd..bf4637fe7 100644 --- a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/rules/AuthTokenAudienceRuleTest.java +++ b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-core/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/core/rules/AuthTokenAudienceRuleTest.java @@ -29,6 +29,7 @@ import static org.eclipse.edc.junit.assertions.AbstractResultAssert.assertThat; import static org.eclipse.tractusx.edc.dataplane.tokenrefresh.core.TestFunctions.createAuthenticationToken; +import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.AUDIENCE_PROPERTY; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -44,7 +45,7 @@ void checkRule_issuerDoesNotMatchAudience() { when(store.getById(TEST_TOKEN_ID)).thenReturn(new AccessTokenData(TEST_TOKEN_ID, ClaimToken.Builder.newInstance().build(), DataAddress.Builder.newInstance().type("test-type").build(), - Map.of("audience", "did:web:alice"))); + Map.of(AUDIENCE_PROPERTY, "did:web:alice"))); assertThat(rule.checkRule(createAuthenticationToken(TEST_TOKEN_ID), Map.of())) .isFailed() @@ -57,12 +58,12 @@ void checkRule_audienceNotString() { when(store.getById(TEST_TOKEN_ID)).thenReturn(new AccessTokenData(TEST_TOKEN_ID, ClaimToken.Builder.newInstance().build(), DataAddress.Builder.newInstance().type("test-type").build(), - Map.of("audience", 42L))); + Map.of(AUDIENCE_PROPERTY, 42L))); assertThat(rule.checkRule(createAuthenticationToken(TEST_TOKEN_ID), Map.of())) .isFailed() .detail() - .isEqualTo("Property 'audience' was expected to be java.lang.String but was class java.lang.Long."); + .isEqualTo("Property '%s' was expected to be java.lang.String but was class java.lang.Long.".formatted(AUDIENCE_PROPERTY)); } @Test @@ -75,6 +76,6 @@ void checkRule_audienceNotPresent() { assertThat(rule.checkRule(createAuthenticationToken(TEST_TOKEN_ID), Map.of())) .isFailed() .detail() - .isEqualTo("Property 'audience' was expected to be java.lang.String but was null."); + .isEqualTo("Property '%s' was expected to be java.lang.String but was null.".formatted(AUDIENCE_PROPERTY)); } } \ No newline at end of file diff --git a/edc-extensions/tokenrefresh-handler/src/main/java/org/eclipse/tractusx/edc/common/tokenrefresh/TokenRefreshHandlerImpl.java b/edc-extensions/tokenrefresh-handler/src/main/java/org/eclipse/tractusx/edc/common/tokenrefresh/TokenRefreshHandlerImpl.java index 0d07e8ca4..7ede6ca8e 100644 --- a/edc-extensions/tokenrefresh-handler/src/main/java/org/eclipse/tractusx/edc/common/tokenrefresh/TokenRefreshHandlerImpl.java +++ b/edc-extensions/tokenrefresh-handler/src/main/java/org/eclipse/tractusx/edc/common/tokenrefresh/TokenRefreshHandlerImpl.java @@ -20,7 +20,6 @@ package org.eclipse.tractusx.edc.common.tokenrefresh; import com.fasterxml.jackson.databind.ObjectMapper; -import com.nimbusds.jwt.SignedJWT; import okhttp3.HttpUrl; import okhttp3.Request; import okhttp3.RequestBody; @@ -37,7 +36,6 @@ import org.eclipse.tractusx.edc.spi.tokenrefresh.dataplane.model.TokenResponse; import java.io.IOException; -import java.text.ParseException; import java.util.Map; import static org.eclipse.edc.jwt.spi.JwtRegisteredClaimNames.AUDIENCE; @@ -48,6 +46,7 @@ import static org.eclipse.edc.util.string.StringUtils.isNullOrBlank; import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.EDR_PROPERTY_AUTHORIZATION; import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.EDR_PROPERTY_EXPIRES_IN; +import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.EDR_PROPERTY_REFRESH_AUDIENCE; import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.EDR_PROPERTY_REFRESH_ENDPOINT; import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.EDR_PROPERTY_REFRESH_TOKEN; @@ -97,6 +96,7 @@ public ServiceResult refreshToken(String tokenId, DataAddress edr) var accessToken = edr.getStringProperty(EDR_PROPERTY_AUTHORIZATION); var refreshToken = edr.getProperties().get(EDR_PROPERTY_REFRESH_TOKEN); var refreshEndpoint = edr.getProperties().get(EDR_PROPERTY_REFRESH_ENDPOINT); + var refreshAudience = edr.getProperties().get(EDR_PROPERTY_REFRESH_AUDIENCE); if (isNullOrBlank(accessToken)) { return ServiceResult.badRequest("Cannot perform token refresh: required property 'authorization' not found on EDR."); @@ -107,16 +107,19 @@ public ServiceResult refreshToken(String tokenId, DataAddress edr) if (isNullOrBlank(StringUtils.toString(refreshEndpoint))) { return ServiceResult.badRequest("Cannot perform token refresh: required property 'refreshEndpoint' not found on EDR."); } + if (isNullOrBlank(StringUtils.toString(refreshAudience))) { + return ServiceResult.badRequest("Cannot perform token refresh: required property 'refreshAudience' not found on EDR."); + } + + var claims = Map.of( + JWT_ID, tokenId, + ISSUER, ownDid, + SUBJECT, ownDid, + AUDIENCE, refreshAudience.toString(), + "token", accessToken + ); - var result = getStringClaim(accessToken, ISSUER) - .map(audience -> Map.of( - JWT_ID, tokenId, - ISSUER, ownDid, - SUBJECT, ownDid, - AUDIENCE, audience, - "token", accessToken - )) - .compose(claims -> secureTokenService.createToken(claims, null)) + var result = secureTokenService.createToken(claims, null) .compose(authToken -> createTokenRefreshRequest(refreshEndpoint.toString(), refreshToken.toString(), "Bearer %s".formatted(authToken.getToken()))); if (result.failed()) { @@ -180,13 +183,4 @@ private Result createTokenRefreshRequest(String refreshEndpoint, String .build()); } - private Result getStringClaim(String accessToken, String claimName) { - try { - return success(SignedJWT.parse(accessToken).getJWTClaimsSet().getStringClaim(claimName)); - } catch (ParseException e) { - monitor.warning("Failed to get string claim '%s'".formatted(claimName), e); - return Result.failure("Failed to parse string claim '%s': %s".formatted(claimName, e)); - } - } - } diff --git a/edc-extensions/tokenrefresh-handler/src/test/java/org/eclipse/tractusx/edc/common/tokenrefresh/TokenRefreshHandlerImplTest.java b/edc-extensions/tokenrefresh-handler/src/test/java/org/eclipse/tractusx/edc/common/tokenrefresh/TokenRefreshHandlerImplTest.java index 07a51a0be..e210ecbad 100644 --- a/edc-extensions/tokenrefresh-handler/src/test/java/org/eclipse/tractusx/edc/common/tokenrefresh/TokenRefreshHandlerImplTest.java +++ b/edc-extensions/tokenrefresh-handler/src/test/java/org/eclipse/tractusx/edc/common/tokenrefresh/TokenRefreshHandlerImplTest.java @@ -58,6 +58,7 @@ import static org.eclipse.edc.junit.assertions.AbstractResultAssert.assertThat; import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.EDR_PROPERTY_AUTHORIZATION; import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.EDR_PROPERTY_EXPIRES_IN; +import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.EDR_PROPERTY_REFRESH_AUDIENCE; import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.EDR_PROPERTY_REFRESH_ENDPOINT; import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.EDR_PROPERTY_REFRESH_TOKEN; import static org.mockito.ArgumentMatchers.any; @@ -178,14 +179,7 @@ void refresh_ioException() throws IOException { assertThat(tokenRefreshHandler.refreshToken("token-id")).isFailed() .detail().isEqualTo("Error executing token refresh request: java.io.IOException: test exception"); } - - @Test - void refresh_accessTokenIsNotJwt() { - when(edrCache.get(anyString())).thenReturn(StoreResult.success(createEdr().property(EDR_PROPERTY_AUTHORIZATION, "not-jwt").build())); - assertThat(tokenRefreshHandler.refreshToken("token-id")).isFailed() - .detail().startsWith("Could not execute token refresh: Failed to parse string claim 'iss'"); - } - + @Test void refresh_tokenGenerationFailed() { when(edrCache.get(anyString())).thenReturn(StoreResult.success(createEdr().build())); @@ -211,7 +205,8 @@ private DataAddress.Builder createEdr() { .type("HttpData") .property(EDR_PROPERTY_AUTHORIZATION, createJwt()) .property(EDR_PROPERTY_REFRESH_TOKEN, "foo-refresh-token") - .property(EDR_PROPERTY_REFRESH_ENDPOINT, REFRESH_ENDPOINT); + .property(EDR_PROPERTY_REFRESH_ENDPOINT, REFRESH_ENDPOINT) + .property(EDR_PROPERTY_REFRESH_AUDIENCE, CONSUMER_DID); } private static class InvalidEdrProvider implements ArgumentsProvider { diff --git a/edc-tests/edc-controlplane/edr-api-tests/src/test/java/org/eclipse/tractusx/edc/tests/edrv2/EdrCacheApiEndToEndTest.java b/edc-tests/edc-controlplane/edr-api-tests/src/test/java/org/eclipse/tractusx/edc/tests/edrv2/EdrCacheApiEndToEndTest.java index 69cbb5075..938a0dea4 100644 --- a/edc-tests/edc-controlplane/edr-api-tests/src/test/java/org/eclipse/tractusx/edc/tests/edrv2/EdrCacheApiEndToEndTest.java +++ b/edc-tests/edc-controlplane/edr-api-tests/src/test/java/org/eclipse/tractusx/edc/tests/edrv2/EdrCacheApiEndToEndTest.java @@ -58,6 +58,7 @@ import static org.eclipse.edc.spi.constants.CoreConstants.EDC_NAMESPACE; import static org.eclipse.edc.util.io.Ports.getFreePort; import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.EDR_PROPERTY_EXPIRES_IN; +import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.EDR_PROPERTY_REFRESH_AUDIENCE; import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.EDR_PROPERTY_REFRESH_ENDPOINT; import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.EDR_PROPERTY_REFRESH_TOKEN; import static org.mockserver.integration.ClientAndServer.startClientAndServer; @@ -85,6 +86,7 @@ public class EdrCacheApiEndToEndTest { with(SOKRATES.getConfiguration(), Map.of("edc.iam.issuer.id", "did:web:sokrates"))); private final ObjectMapper mapper = new ObjectMapper(); private String refreshEndpoint; + private String refreshAudience; private ClientAndServer mockedRefreshApi; private ECKey providerSigningKey; @@ -99,6 +101,7 @@ void setup() throws JOSEException { providerSigningKey = new ECKeyGenerator(Curve.P_256).keyID("did:web:provider#key-1").generate(); var port = getFreePort(); refreshEndpoint = "http://localhost:%s/refresh".formatted(port); + refreshAudience = "did:web:sokrates"; mockedRefreshApi = startClientAndServer(port); } @@ -305,6 +308,7 @@ private void storeEdr(String transferProcessId, boolean isExpired) { .property(EDR_PROPERTY_REFRESH_TOKEN, createJwt(providerSigningKey, new JWTClaimsSet.Builder().build())) .property(EDR_PROPERTY_EXPIRES_IN, "300") .property(EDR_PROPERTY_REFRESH_ENDPOINT, refreshEndpoint) + .property(EDR_PROPERTY_REFRESH_AUDIENCE, refreshAudience) .build(); var entry = EndpointDataReferenceEntry.Builder.newInstance() .clock(isExpired ? // defaults to an expired token diff --git a/edc-tests/edc-dataplane/edc-dataplane-tokenrefresh-tests/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/e2e/DataPlaneTokenRefreshEndToEndTest.java b/edc-tests/edc-dataplane/edc-dataplane-tokenrefresh-tests/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/e2e/DataPlaneTokenRefreshEndToEndTest.java index 77e5341dd..ff888c8fc 100644 --- a/edc-tests/edc-dataplane/edc-dataplane-tokenrefresh-tests/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/e2e/DataPlaneTokenRefreshEndToEndTest.java +++ b/edc-tests/edc-dataplane/edc-dataplane-tokenrefresh-tests/src/test/java/org/eclipse/tractusx/edc/dataplane/tokenrefresh/e2e/DataPlaneTokenRefreshEndToEndTest.java @@ -53,6 +53,7 @@ import static org.apache.http.HttpHeaders.AUTHORIZATION; import static org.assertj.core.api.Assertions.assertThat; import static org.eclipse.edc.spi.constants.CoreConstants.EDC_NAMESPACE; +import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.AUDIENCE_PROPERTY; import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.TX_AUTH_NS; import static org.hamcrest.Matchers.containsString; @@ -361,7 +362,7 @@ private DataFlowStartMessage createStartMessage(String processId, String audienc .assetId("test-asset") .callbackAddress(URI.create("https://foo.bar/callback")) .agreementId("test-agreement") - .property("audience", audience) + .property(AUDIENCE_PROPERTY, audience) .build(); } } diff --git a/edc-tests/runtime/iatp/runtime-memory-iatp-dim-ih/build.gradle.kts b/edc-tests/runtime/iatp/runtime-memory-iatp-dim-ih/build.gradle.kts index 8393f81f3..792511dd4 100644 --- a/edc-tests/runtime/iatp/runtime-memory-iatp-dim-ih/build.gradle.kts +++ b/edc-tests/runtime/iatp/runtime-memory-iatp-dim-ih/build.gradle.kts @@ -27,6 +27,7 @@ dependencies { // use basic (all in-mem) control plane implementation(project(":edc-controlplane:edc-controlplane-base")) { exclude(module = "bdrs-client") + exclude("org.eclipse.edc", "identity-trust-issuers-configuration") } implementation(project(":core:json-ld-core")) implementation(project(":edc-extensions:cx-policy")) diff --git a/edc-tests/runtime/iatp/runtime-memory-iatp-ih/build.gradle.kts b/edc-tests/runtime/iatp/runtime-memory-iatp-ih/build.gradle.kts index 12b86309c..8b0fe5b63 100644 --- a/edc-tests/runtime/iatp/runtime-memory-iatp-ih/build.gradle.kts +++ b/edc-tests/runtime/iatp/runtime-memory-iatp-ih/build.gradle.kts @@ -28,6 +28,7 @@ dependencies { implementation(project(":edc-controlplane:edc-controlplane-base")) { exclude(module = "bdrs-client") exclude(module = "tx-iatp-sts-dim") + exclude("org.eclipse.edc", "identity-trust-issuers-configuration") } implementation(project(":edc-extensions:cx-policy")) implementation(project(":core:json-ld-core")) diff --git a/edc-tests/runtime/iatp/runtime-memory-sts/build.gradle.kts b/edc-tests/runtime/iatp/runtime-memory-sts/build.gradle.kts index b83afc130..796408b2b 100644 --- a/edc-tests/runtime/iatp/runtime-memory-sts/build.gradle.kts +++ b/edc-tests/runtime/iatp/runtime-memory-sts/build.gradle.kts @@ -30,6 +30,7 @@ dependencies { exclude(module = "ssi-miw-credential-client") exclude(module = "ssi-identity-extractor") exclude(module = "tx-iatp-sts-dim") + exclude("org.eclipse.edc", "identity-trust-issuers-configuration") } implementation(project(":core:json-ld-core")) implementation(project(":edc-tests:runtime:extensions")) diff --git a/edc-tests/runtime/runtime-memory/build.gradle.kts b/edc-tests/runtime/runtime-memory/build.gradle.kts index 448119c86..b2ff89caf 100644 --- a/edc-tests/runtime/runtime-memory/build.gradle.kts +++ b/edc-tests/runtime/runtime-memory/build.gradle.kts @@ -32,6 +32,8 @@ dependencies { exclude(module = "ssi-miw-credential-client") exclude(module = "ssi-identity-extractor") exclude(module = "tx-iatp-sts-dim") + exclude(module = "tx-iatp") + exclude("org.eclipse.edc", "identity-trust-issuers-configuration") } // use an embedded STS diff --git a/edc-tests/runtime/runtime-postgresql/build.gradle.kts b/edc-tests/runtime/runtime-postgresql/build.gradle.kts index 8297ca00a..39f49763d 100644 --- a/edc-tests/runtime/runtime-postgresql/build.gradle.kts +++ b/edc-tests/runtime/runtime-postgresql/build.gradle.kts @@ -33,6 +33,8 @@ dependencies { exclude(module = "ssi-identity-extractor") exclude(module = "tx-iatp-sts-dim") exclude(group = "org.eclipse.edc", "vault-hashicorp") + exclude(module = "tx-iatp") + exclude("org.eclipse.edc", "identity-trust-issuers-configuration") } implementation(project(":edc-tests:runtime:extensions")) diff --git a/samples/multi-tenancy/build.gradle.kts b/samples/multi-tenancy/build.gradle.kts index a270267dd..ad6cd1d8e 100644 --- a/samples/multi-tenancy/build.gradle.kts +++ b/samples/multi-tenancy/build.gradle.kts @@ -37,6 +37,7 @@ dependencies { exclude(module = "edr-core") exclude(module = "edr-api-v2") exclude(module = "edr-callback") + exclude("org.eclipse.edc", "identity-trust-issuers-configuration") } implementation(libs.edc.core.controlplane) implementation(libs.jakarta.rsApi) diff --git a/spi/core-spi/src/main/java/org/eclipse/tractusx/edc/edr/spi/CoreConstants.java b/spi/core-spi/src/main/java/org/eclipse/tractusx/edc/edr/spi/CoreConstants.java index 91b38e24c..f21301a1b 100644 --- a/spi/core-spi/src/main/java/org/eclipse/tractusx/edc/edr/spi/CoreConstants.java +++ b/spi/core-spi/src/main/java/org/eclipse/tractusx/edc/edr/spi/CoreConstants.java @@ -25,6 +25,7 @@ public final class CoreConstants { public static final String TX_PREFIX = "tx"; + public static final String TX_AUTH_PREFIX = "tx-auth"; public static final String TX_NAMESPACE = "https://w3id.org/tractusx/v0.0.1/ns/"; public static final String TX_CONTEXT = "https://w3id.org/tractusx/edc/v0.0.1"; public static final String TX_AUTH_NS = "https://w3id.org/tractusx/auth/"; @@ -37,6 +38,8 @@ public final class CoreConstants { public static final String EDR_PROPERTY_AUTHORIZATION = EDC_NAMESPACE + "authorization"; public static final String EDR_PROPERTY_REFRESH_TOKEN = TX_AUTH_NS + "refreshToken"; public static final String EDR_PROPERTY_REFRESH_ENDPOINT = TX_AUTH_NS + "refreshEndpoint"; + public static final String EDR_PROPERTY_REFRESH_AUDIENCE = TX_AUTH_NS + "refreshAudience"; + public static final String AUDIENCE_PROPERTY = TX_AUTH_NS + "audience"; public static final String EDR_PROPERTY_EXPIRES_IN = TX_AUTH_NS + "expiresIn"; private CoreConstants() { From 7aa47cf9131b9bc8e9d0543cd8fa4c527b9c9e92 Mon Sep 17 00:00:00 2001 From: Paul Latzelsperger <43503240+paullatzelsperger@users.noreply.github.com> Date: Fri, 5 Apr 2024 14:21:35 +0200 Subject: [PATCH 097/100] chore: pin edc version (#1192) * chore(build): pin EDC version * DEPENDENCIES --- DEPENDENCIES | 350 +++++++++--------- core/edr-core/build.gradle.kts | 2 +- .../build.gradle.kts | 2 +- .../token-refresh-api/build.gradle.kts | 2 +- .../edr/edr-api-v2/build.gradle.kts | 4 +- .../tokenrefresh-handler/build.gradle.kts | 2 +- .../iatp-tests/build.gradle.kts | 2 +- edc-tests/runtime/extensions/build.gradle.kts | 2 +- gradle/libs.versions.toml | 13 +- 9 files changed, 188 insertions(+), 191 deletions(-) diff --git a/DEPENDENCIES b/DEPENDENCIES index 6c5335b14..5f23c4b7d 100644 --- a/DEPENDENCIES +++ b/DEPENDENCIES @@ -333,183 +333,179 @@ maven/mavencentral/org.codehaus.plexus/plexus-utils/3.1.1, , approved, CQ16492 maven/mavencentral/org.codehaus.plexus/plexus-utils/3.3.0, , approved, CQ21066 maven/mavencentral/org.codehaus.woodstox/stax2-api/4.2.2, BSD-2-Clause, approved, #2670 maven/mavencentral/org.eclipse.angus/angus-activation/1.0.0, EPL-2.0 OR GPL-2.0-only with Classpath-exception-2.0, approved, ee4j.angus -maven/mavencentral/org.eclipse.edc/accesstokendata-store-sql/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/api-core/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/api-observability/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/asset-api/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/asset-index-sql/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/asset-spi/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/auth-spi/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/auth-tokenbased/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/autodoc-processor/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/aws-s3-core/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/aws-s3-test/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/azure-blob-core/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/azure-test/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/boot-lib/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/boot-spi/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/boot/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/callback-event-dispatcher/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/callback-http-dispatcher/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/catalog-api/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/catalog-spi/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/configuration-filesystem/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/connector-core/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/contract-agreement-api/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/contract-definition-api/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/contract-definition-store-sql/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/contract-negotiation-api/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/contract-negotiation-store-sql/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/contract-spi/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/control-api-configuration/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/control-plane-aggregate-services/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/control-plane-api-client-spi/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/control-plane-api-client/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/control-plane-api/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/control-plane-catalog/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/control-plane-contract/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/control-plane-core/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/control-plane-policies-lib/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/control-plane-spi/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/control-plane-transfer/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/control-plane-transform/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/core-spi/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/crypto-common-lib/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-address-http-data-spi/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-plane-aws-s3/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-plane-azure-storage/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-plane-client-embedded/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-plane-control-api/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-plane-core/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-plane-http-oauth2-core/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-plane-http-oauth2/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-plane-http-spi/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-plane-http/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-plane-public-api-v2/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-plane-selector-core/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-plane-selector-spi/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-plane-signaling-api-configuration/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-plane-signaling-api/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-plane-signaling-client/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-plane-signaling-transform/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-plane-spi/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-plane-store-sql/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/data-plane-util/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-catalog-http-api/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-catalog-http-dispatcher/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-catalog-transform/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-catalog/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-http-api-configuration/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-http-core/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-http-spi/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-negotiation-http-api/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-negotiation-http-dispatcher/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-negotiation-transform/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-negotiation/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-spi/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-transfer-process-http-api/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-transfer-process-http-dispatcher/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-transfer-process-transform/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-transfer-process/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp-version-http-api/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/dsp/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/edr-index-sql/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/edr-store-core/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/edr-store-receiver/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/edr-store-spi/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/http-lib/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/http-spi/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/http/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/iam-mock/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-did-core/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-did-spi/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-did-web/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-hub-api/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-hub-credentials/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-hub-did-spi/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-hub-did/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-hub-keypairs/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-hub-participants/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-hub-spi/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-hub-store-spi/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-trust-core/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-trust-issuers-configuration/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-trust-service/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-trust-spi/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-trust-sts-api/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-trust-sts-client-configuration/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-trust-sts-core/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-trust-sts-embedded/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-trust-sts-remote-client/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-trust-sts-remote-lib/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-trust-sts-spi/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/identity-trust-transform/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/jersey-core/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/jersey-micrometer/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/jersey-providers-lib/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/jetty-core/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/jetty-micrometer/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/json-ld-lib/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/json-ld-spi/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/json-ld/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/junit-base/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/junit/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/jws2020-lib/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/jws2020/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/jwt-spi/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/jwt-verifiable-credentials/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/keys-lib/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/keys-spi/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/ldp-verifiable-credentials/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/management-api-configuration/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/management-api-test-fixtures/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/management-api/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/micrometer-core/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/oauth2-client/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/oauth2-spi/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/policy-definition-api/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/policy-definition-store-sql/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/policy-engine-lib/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/policy-engine-spi/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/policy-evaluator-lib/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/policy-model/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/policy-monitor-core/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/policy-monitor-spi/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/policy-monitor-store-sql/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/policy-spi/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/query-lib/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/runtime-metamodel/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/security/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/sql-core/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/sql-lease/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/sql-pool-apache-commons/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/state-machine-lib/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/store-lib/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/token-core/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/token-spi/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/transaction-datasource-spi/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/transaction-local/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/transaction-spi/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/transfer-data-plane-signaling/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/transfer-data-plane-spi/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/transfer-process-api/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/transfer-process-store-sql/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/transfer-pull-http-dynamic-receiver/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/transfer-spi/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/transform-core/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/transform-lib/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/transform-spi/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/util-lib/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/util/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/validator-core/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/validator-data-address-http-data/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/validator-lib/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/validator-spi/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/vault-azure/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/vault-hashicorp/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/verifiable-credentials-spi/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/verifiable-credentials/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc -maven/mavencentral/org.eclipse.edc/web-spi/0.6.1-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/accesstokendata-store-sql/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/api-core/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/api-observability/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/asset-api/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/asset-index-sql/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/asset-spi/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/auth-spi/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/auth-tokenbased/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/autodoc-processor/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/aws-s3-core/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/aws-s3-test/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/azure-blob-core/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/azure-test/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/boot-lib/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/boot-spi/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/boot/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/callback-event-dispatcher/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/callback-http-dispatcher/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/catalog-api/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/catalog-spi/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/configuration-filesystem/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/connector-core/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/contract-agreement-api/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/contract-definition-api/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/contract-definition-store-sql/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/contract-negotiation-api/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/contract-negotiation-store-sql/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/contract-spi/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/control-api-configuration/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/control-plane-aggregate-services/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/control-plane-api-client-spi/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/control-plane-api-client/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/control-plane-api/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/control-plane-catalog/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/control-plane-contract/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/control-plane-core/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/control-plane-policies-lib/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/control-plane-spi/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/control-plane-transfer/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/control-plane-transform/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/core-spi/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/crypto-common-lib/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-address-http-data-spi/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-aws-s3/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-azure-storage/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-client-embedded/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-control-api/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-core/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-http-oauth2-core/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-http-oauth2/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-http-spi/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-http/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-public-api-v2/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-selector-core/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-selector-spi/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-signaling-api-configuration/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-signaling-api/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-signaling-client/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-signaling-transform/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-spi/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-store-sql/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/data-plane-util/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-catalog-http-api/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-catalog-http-dispatcher/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-catalog-transform/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-catalog/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-http-api-configuration/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-http-core/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-http-spi/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-negotiation-http-api/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-negotiation-http-dispatcher/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-negotiation-transform/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-negotiation/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-spi/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-transfer-process-http-api/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-transfer-process-http-dispatcher/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-transfer-process-transform/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-transfer-process/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp-version-http-api/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/dsp/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/edr-index-sql/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/edr-store-core/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/edr-store-receiver/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/edr-store-spi/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/http-lib/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/http-spi/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/http/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/iam-mock/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-did-core/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-did-spi/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-did-web/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-hub-api/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-hub-credentials/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-hub-did-spi/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-hub-did/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-hub-keypairs/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-hub-participants/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-hub-spi/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-hub-store-spi/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-trust-core/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-trust-issuers-configuration/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-trust-service/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-trust-spi/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-trust-sts-api/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-trust-sts-client-configuration/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-trust-sts-core/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-trust-sts-embedded/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-trust-sts-remote-client/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-trust-sts-remote-lib/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-trust-sts-spi/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/identity-trust-transform/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/jersey-core/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/jersey-micrometer/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/jersey-providers-lib/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/jetty-core/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/jetty-micrometer/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/json-ld-lib/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/json-ld-spi/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/json-ld/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/junit-base/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/junit/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/jws2020-lib/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/jwt-spi/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/jwt-verifiable-credentials/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/keys-lib/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/keys-spi/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/ldp-verifiable-credentials/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/management-api-configuration/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/management-api-test-fixtures/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/management-api/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/micrometer-core/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/oauth2-client/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/oauth2-spi/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/policy-definition-api/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/policy-definition-store-sql/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/policy-engine-lib/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/policy-engine-spi/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/policy-evaluator-lib/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/policy-model/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/policy-monitor-core/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/policy-monitor-spi/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/policy-monitor-store-sql/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/policy-spi/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/query-lib/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/runtime-metamodel/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/security/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/sql-core/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/sql-lease/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/sql-pool-apache-commons/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/state-machine-lib/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/store-lib/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/token-core/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/token-spi/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/transaction-datasource-spi/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/transaction-local/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/transaction-spi/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/transfer-data-plane-signaling/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/transfer-data-plane-spi/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/transfer-process-api/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/transfer-process-store-sql/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/transfer-pull-http-dynamic-receiver/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/transfer-spi/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/transform-lib/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/transform-spi/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/util-lib/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/validator-data-address-http-data/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/validator-lib/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/validator-spi/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/vault-azure/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/vault-hashicorp/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/verifiable-credentials-spi/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/verifiable-credentials/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc +maven/mavencentral/org.eclipse.edc/web-spi/0.6.1-20240405-SNAPSHOT, Apache-2.0, approved, technology.edc maven/mavencentral/org.eclipse.jetty.toolchain/jetty-jakarta-servlet-api/5.0.2, EPL-2.0 OR Apache-2.0, approved, rt.jetty maven/mavencentral/org.eclipse.jetty.toolchain/jetty-jakarta-websocket-api/2.0.0, EPL-2.0 OR Apache-2.0, approved, rt.jetty maven/mavencentral/org.eclipse.jetty.websocket/websocket-core-client/11.0.20, EPL-2.0 OR Apache-2.0, approved, rt.jetty diff --git a/core/edr-core/build.gradle.kts b/core/edr-core/build.gradle.kts index 96040bb2a..8335ef370 100644 --- a/core/edr-core/build.gradle.kts +++ b/core/edr-core/build.gradle.kts @@ -22,7 +22,7 @@ plugins { } dependencies { - implementation(libs.edc.util) + implementation(libs.edc.lib.util) implementation(libs.edc.spi.edrstore) implementation(libs.edc.spi.transactionspi) diff --git a/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-consumer-api/build.gradle.kts b/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-consumer-api/build.gradle.kts index d76a0fe64..53845bed9 100644 --- a/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-consumer-api/build.gradle.kts +++ b/edc-extensions/dataplane/dataplane-proxy/edc-dataplane-proxy-consumer-api/build.gradle.kts @@ -28,7 +28,7 @@ dependencies { implementation(libs.edc.spi.http) implementation(libs.edc.spi.dataplane.http) - implementation(libs.edc.util) + implementation(libs.edc.lib.util) implementation(libs.edc.dpf.util) implementation(libs.edc.ext.http) implementation(libs.edc.spi.auth) diff --git a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-api/build.gradle.kts b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-api/build.gradle.kts index d86e9ec4d..c99448fc0 100644 --- a/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-api/build.gradle.kts +++ b/edc-extensions/dataplane/dataplane-token-refresh/token-refresh-api/build.gradle.kts @@ -28,7 +28,7 @@ dependencies { implementation(libs.edc.spi.core) implementation(libs.edc.spi.web) implementation(libs.jakarta.rsApi) - implementation(libs.edc.util) + implementation(libs.edc.lib.util) testImplementation(libs.edc.junit) diff --git a/edc-extensions/edr/edr-api-v2/build.gradle.kts b/edc-extensions/edr/edr-api-v2/build.gradle.kts index 3e3b028f5..4db499b1c 100644 --- a/edc-extensions/edr/edr-api-v2/build.gradle.kts +++ b/edc-extensions/edr/edr-api-v2/build.gradle.kts @@ -30,7 +30,7 @@ dependencies { implementation(project(":spi:tokenrefresh-spi")) implementation(libs.edc.api.management) - implementation(libs.edc.core.validator) + implementation(libs.edc.lib.validator) implementation(libs.edc.spi.edrstore) implementation(libs.jakarta.rsApi) @@ -38,6 +38,6 @@ dependencies { testImplementation(libs.restAssured) testImplementation(libs.edc.junit) testImplementation(libs.edc.lib.jersey.providers) - testImplementation(libs.edc.core.transform) + testImplementation(libs.edc.lib.transform) testImplementation(libs.edc.spi.contract) } diff --git a/edc-extensions/tokenrefresh-handler/build.gradle.kts b/edc-extensions/tokenrefresh-handler/build.gradle.kts index d48210726..535170d42 100644 --- a/edc-extensions/tokenrefresh-handler/build.gradle.kts +++ b/edc-extensions/tokenrefresh-handler/build.gradle.kts @@ -32,7 +32,7 @@ dependencies { implementation(libs.edc.spi.token) implementation(libs.edc.spi.jwt) implementation(libs.edc.spi.identitytrust) - implementation(libs.edc.util) + implementation(libs.edc.lib.util) implementation(libs.nimbus.jwt) diff --git a/edc-tests/edc-controlplane/iatp-tests/build.gradle.kts b/edc-tests/edc-controlplane/iatp-tests/build.gradle.kts index d2bbaad5a..23f1f0231 100644 --- a/edc-tests/edc-controlplane/iatp-tests/build.gradle.kts +++ b/edc-tests/edc-controlplane/iatp-tests/build.gradle.kts @@ -31,7 +31,7 @@ dependencies { testImplementation(libs.edc.junit) testImplementation(libs.edc.core.token) testImplementation(libs.edc.identity.vc.ldp) - testImplementation(libs.edc.identity.jws2020) + testImplementation(libs.edc.lib.jws2020) // 3rd party libs testImplementation(libs.netty.mockserver) testImplementation(libs.restAssured) diff --git a/edc-tests/runtime/extensions/build.gradle.kts b/edc-tests/runtime/extensions/build.gradle.kts index c877aadd3..be04ee59e 100644 --- a/edc-tests/runtime/extensions/build.gradle.kts +++ b/edc-tests/runtime/extensions/build.gradle.kts @@ -25,7 +25,7 @@ plugins { dependencies { implementation(libs.edc.core.controlplane) - implementation(libs.edc.util) + implementation(libs.edc.lib.util) implementation(libs.edc.spi.web) } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index a3bec4cb4..30969fcf5 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -2,7 +2,7 @@ format.version = "1.1" [versions] -edc = "0.6.1-SNAPSHOT" +edc = "0.6.1-20240405-SNAPSHOT" apache-sshd = "2.12.1" assertj = "3.25.3" awaitility = "4.2.0" @@ -49,7 +49,6 @@ edc-spi-vc = { module = "org.eclipse.edc:verifiable-credentials-spi", version.re edc-spi-edrstore = { module = "org.eclipse.edc:edr-store-spi", version.ref = "edc" } edc-token-core = { module = "org.eclipse.edc:token-core", version.ref = "edc" } edc-spi-oauth2 = { module = "org.eclipse.edc:oauth2-spi", version.ref = "edc" } -edc-util = { module = "org.eclipse.edc:util", version.ref = "edc" } edc-boot = { module = "org.eclipse.edc:boot", version.ref = "edc" } edc-build-plugin = { module = "org.eclipse.edc.edc-build:org.eclipse.edc.edc-build.gradle.plugin", version.ref = "edc" } edc-config-filesystem = { module = "org.eclipse.edc:configuration-filesystem", version.ref = "edc" } @@ -63,8 +62,6 @@ edc-core-jersey = { module = "org.eclipse.edc:jersey-core", version.ref = "edc" edc-core-api = { module = "org.eclipse.edc:api-core", version.ref = "edc" } edc-core-policy-monitor = { module = "org.eclipse.edc:policy-monitor-core", version.ref = "edc" } edc-core-sql = { module = "org.eclipse.edc:sql-core", version.ref = "edc" } -edc-core-validator = { module = "org.eclipse.edc:validator-core", version.ref = "edc" } -edc-core-transform = { module = "org.eclipse.edc:transform-core", version.ref = "edc" } edc-core-token = { module = "org.eclipse.edc:token-core", version.ref = "edc" } edc-core-edrstore = { module = "org.eclipse.edc:edr-store-core", version.ref = "edc" } edc-junit = { module = "org.eclipse.edc:junit", version.ref = "edc" } @@ -87,16 +84,21 @@ edc-ext-azure-cosmos-core = { module = "org.eclipse.edc:azure-cosmos-core", vers edc-ext-azure-test = { module = "org.eclipse.edc:azure-test", version.ref = "edc" } edc-ext-jsonld = { module = "org.eclipse.edc:json-ld", version.ref = "edc" } edc-validator-data-address-http-data = { module = "org.eclipse.edc:validator-data-address-http-data", version.ref = "edc" } + +# EDC lib dependencies edc-lib-boot = { module = "org.eclipse.edc:boot-lib", version.ref = "edc" } edc-lib-cryptocommon = { module = "org.eclipse.edc:crypto-common-lib", version.ref = "edc" } edc-lib-http = { module = "org.eclipse.edc:http-lib", version.ref = "edc" } edc-lib-jersey-providers = { module = "org.eclipse.edc:jersey-providers-lib", version.ref = "edc" } edc-lib-jsonld = { module = "org.eclipse.edc:json-ld-lib", version.ref = "edc" } +edc-lib-jws2020 = { module = "org.eclipse.edc:jws2020-lib", version.ref = "edc" } edc-lib-policyengine = { module = "org.eclipse.edc:policy-engine-lib", version.ref = "edc" } edc-lib-query = { module = "org.eclipse.edc:query-lib", version.ref = "edc" } edc-lib-store = { module = "org.eclipse.edc:store-lib", version.ref = "edc" } edc-lib-statemachine = { module = "org.eclipse.edc:state-machine-lib", version.ref = "edc" } - +edc-lib-util = { module = "org.eclipse.edc:util-lib", version.ref = "edc" } +edc-lib-validator = { module = "org.eclipse.edc:validator-lib", version.ref = "edc" } +edc-lib-transform = { module = "org.eclipse.edc:transform-lib", version.ref = "edc" } # implementations edc-sql-assetindex = { module = "org.eclipse.edc:asset-index-sql", version.ref = "edc" } @@ -134,7 +136,6 @@ edc-core-did = { module = "org.eclipse.edc:identity-did-core", version.ref = "ed edc-identity-did-web = { module = "org.eclipse.edc:identity-did-web", version.ref = "edc" } edc-identity-vc-ldp = { module = "org.eclipse.edc:ldp-verifiable-credentials", version.ref = "edc" } edc-identity-vc-jwt = { module = "org.eclipse.edc:jwt-verifiable-credentials", version.ref = "edc" } -edc-identity-jws2020 = { module = "org.eclipse.edc:jws2020", version.ref = "edc" } edc-identity-trust-transform = { module = "org.eclipse.edc:identity-trust-transform", version.ref = "edc" } edc-identity-trust-issuers-configuration = { module = "org.eclipse.edc:identity-trust-issuers-configuration", version.ref = "edc" } From d129e1a5e67d4aea0e718ee5011e6a6662516cfa Mon Sep 17 00:00:00 2001 From: Paul Latzelsperger Date: Fri, 5 Apr 2024 14:40:48 +0200 Subject: [PATCH 098/100] fix: remove newline --- build.gradle.kts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 42c028ca8..6b27934d4 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -150,8 +150,7 @@ subprojects { val agentFile = buildDir.resolve("opentelemetry-javaagent.jar") // create task to download the opentelemetry agent - val openTelemetryAgentUrl = - "https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/download/v1.32.0/opentelemetry-javaagent.jar" + val openTelemetryAgentUrl = "https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/download/v1.32.0/opentelemetry-javaagent.jar" val downloadOtel = tasks.create("downloadOtel") { // only execute task if the opentelemetry agent does not exist. invoke the "clean" task to force onlyIf { From dd240ae308058ca6510001b043e17eb490a99cce Mon Sep 17 00:00:00 2001 From: Paul Latzelsperger Date: Fri, 5 Apr 2024 14:56:22 +0200 Subject: [PATCH 099/100] fix(javadoc): update references --- .../BusinessPartnerValidationExtension.java | 7 +++---- .../membership/MembershipCredentialConstraintFunction.java | 3 ++- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/edc-extensions/bpn-validation/bpn-validation-core/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/BusinessPartnerValidationExtension.java b/edc-extensions/bpn-validation/bpn-validation-core/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/BusinessPartnerValidationExtension.java index 8e52a6ee3..322620ddc 100644 --- a/edc-extensions/bpn-validation/bpn-validation-core/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/BusinessPartnerValidationExtension.java +++ b/edc-extensions/bpn-validation/bpn-validation-core/src/main/java/org/eclipse/tractusx/edc/validation/businesspartner/BusinessPartnerValidationExtension.java @@ -37,9 +37,9 @@ /** * Registers a {@link org.eclipse.tractusx.edc.validation.businesspartner.functions.BusinessPartnerGroupFunction} for the following scopes: *

        - *
      • {@link org.eclipse.edc.connector.controlplane.contract.spi.offer.ContractDefinitionResolver.CATALOGING_SCOPE}
      • - *
      • {@link org.eclipse.edc.connector.controlplane.contract.spi.validation.ContractValidationService.NEGOTIATION_SCOPE}
      • - *
      • {@link org.eclipse.edc.connector.controlplane.contract.spi.validation.ContractValidationService.TRANSFER_SCOPE}
      • + *
      • {@code catalog}
      • + *
      • {@code contract.negotiation}
      • + *
      • {@code transfer.process}
      • *
      * The rule to which the function is bound is {@link BusinessPartnerGroupFunction#BUSINESS_PARTNER_CONSTRAINT_KEY}. That means, that policies that are bound to these scopes look * like this: @@ -57,7 +57,6 @@ */ @Extension(value = "Registers a function to evaluate whether a BPN number is covered by a certain policy or not", categories = { "policy", "contract" }) public class BusinessPartnerValidationExtension implements ServiceExtension { - private static final String USE = "USE"; @Inject private RuleBindingRegistry ruleBindingRegistry; diff --git a/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/membership/MembershipCredentialConstraintFunction.java b/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/membership/MembershipCredentialConstraintFunction.java index 6c85ce75e..b44593dfa 100644 --- a/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/membership/MembershipCredentialConstraintFunction.java +++ b/edc-extensions/cx-policy/src/main/java/org/eclipse/tractusx/edc/policy/cx/membership/MembershipCredentialConstraintFunction.java @@ -19,6 +19,7 @@ package org.eclipse.tractusx.edc.policy.cx.membership; +import org.eclipse.edc.iam.verifiablecredentials.spi.model.VerifiableCredential; import org.eclipse.edc.policy.engine.spi.PolicyContext; import org.eclipse.edc.policy.model.Operator; import org.eclipse.edc.policy.model.Permission; @@ -31,7 +32,7 @@ /** - * This constraint function checks that a MembershipCredential is present in a list of {@link org.eclipse.edc.identitytrust.model.VerifiableCredential} + * This constraint function checks that a MembershipCredential is present in a list of {@link VerifiableCredential} * objects extracted from a {@link ParticipantAgent} which is expected to be present on the {@link PolicyContext}. */ public class MembershipCredentialConstraintFunction extends AbstractDynamicCredentialConstraintFunction { From 11a2813c87e3790759a55becfe1a5621dfd6a81a Mon Sep 17 00:00:00 2001 From: eclipse-tractusx-bot Date: Fri, 5 Apr 2024 13:13:26 +0000 Subject: [PATCH 100/100] Prepare release 0.7.0-rc1 --- charts/tractusx-connector-azure-vault/Chart.yaml | 4 ++-- charts/tractusx-connector-azure-vault/README.md | 4 ++-- charts/tractusx-connector-memory/Chart.yaml | 4 ++-- charts/tractusx-connector-memory/README.md | 4 ++-- charts/tractusx-connector/Chart.yaml | 4 ++-- charts/tractusx-connector/README.md | 4 ++-- gradle.properties | 2 +- 7 files changed, 13 insertions(+), 13 deletions(-) diff --git a/charts/tractusx-connector-azure-vault/Chart.yaml b/charts/tractusx-connector-azure-vault/Chart.yaml index 1a3d03ca6..0ff024d86 100644 --- a/charts/tractusx-connector-azure-vault/Chart.yaml +++ b/charts/tractusx-connector-azure-vault/Chart.yaml @@ -41,12 +41,12 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.6.0 +version: 0.7.0-rc1 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to # follow Semantic Versioning. They should reflect the version the application is using. # It is recommended to use it with quotes. -appVersion: "0.6.0" +appVersion: "0.7.0-rc1" home: https://github.com/eclipse-tractusx/tractusx-edc/tree/main/charts/tractusx-connector sources: - https://github.com/eclipse-tractusx/tractusx-edc/tree/main/charts/tractusx-connector diff --git a/charts/tractusx-connector-azure-vault/README.md b/charts/tractusx-connector-azure-vault/README.md index 34ad00c99..f4a42d029 100644 --- a/charts/tractusx-connector-azure-vault/README.md +++ b/charts/tractusx-connector-azure-vault/README.md @@ -1,6 +1,6 @@ # tractusx-connector-azure-vault -![Version: 0.6.0](https://img.shields.io/badge/Version-0.6.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 0.6.0](https://img.shields.io/badge/AppVersion-0.6.0-informational?style=flat-square) +![Version: 0.7.0-rc1](https://img.shields.io/badge/Version-0.7.0--rc1-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 0.7.0-rc1](https://img.shields.io/badge/AppVersion-0.7.0--rc1-informational?style=flat-square) A Helm chart for Tractus-X Eclipse Data Space Connector. The connector deployment consists of two runtime consists of a Control Plane and a Data Plane. Note that _no_ external dependencies such as a PostgreSQL database and Azure KeyVault are included. @@ -45,7 +45,7 @@ Combined, run this shell command to start the in-memory Tractus-X EDC runtime: ```shell helm repo add tractusx-edc https://eclipse-tractusx.github.io/charts/dev -helm install my-release tractusx-edc/tractusx-connector-azure-vault --version 0.6.0 \ +helm install my-release tractusx-edc/tractusx-connector-azure-vault --version 0.7.0-rc1 \ -f /tractusx-connector-azure-vault-test.yaml \ --set vault.azure.name=$AZURE_VAULT_NAME \ --set vault.azure.client=$AZURE_CLIENT_ID \ diff --git a/charts/tractusx-connector-memory/Chart.yaml b/charts/tractusx-connector-memory/Chart.yaml index ae59aac76..919bff1ad 100644 --- a/charts/tractusx-connector-memory/Chart.yaml +++ b/charts/tractusx-connector-memory/Chart.yaml @@ -35,12 +35,12 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.6.0 +version: 0.7.0-rc1 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to # follow Semantic Versioning. They should reflect the version the application is using. # It is recommended to use it with quotes. -appVersion: "0.6.0" +appVersion: "0.7.0-rc1" home: https://github.com/eclipse-tractusx/tractusx-edc/tree/main/charts/tractusx-connector-memory sources: - https://github.com/eclipse-tractusx/tractusx-edc/tree/main/charts/tractusx-connector-memory diff --git a/charts/tractusx-connector-memory/README.md b/charts/tractusx-connector-memory/README.md index e94606898..c01e61614 100644 --- a/charts/tractusx-connector-memory/README.md +++ b/charts/tractusx-connector-memory/README.md @@ -1,6 +1,6 @@ # tractusx-connector-memory -![Version: 0.6.0](https://img.shields.io/badge/Version-0.6.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 0.6.0](https://img.shields.io/badge/AppVersion-0.6.0-informational?style=flat-square) +![Version: 0.7.0-rc1](https://img.shields.io/badge/Version-0.7.0--rc1-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 0.7.0-rc1](https://img.shields.io/badge/AppVersion-0.7.0--rc1-informational?style=flat-square) A Helm chart for Tractus-X Eclipse Data Space Connector based on memory. Please only use this for development or testing purposes, never in production workloads! @@ -39,7 +39,7 @@ Combined, run this shell command to start the in-memory Tractus-X EDC runtime: ```shell helm repo add tractusx-edc https://eclipse-tractusx.github.io/charts/dev -helm install my-release tractusx-edc/tractusx-connector-memory --version 0.6.0 \ +helm install my-release tractusx-edc/tractusx-connector-memory --version 0.7.0-rc1 \ -f /tractusx-connector-memory-test.yaml \ --set vault.secrets="client-secret:$YOUR_CLIENT_SECRET" ``` diff --git a/charts/tractusx-connector/Chart.yaml b/charts/tractusx-connector/Chart.yaml index b01a54b2e..ed18a582e 100644 --- a/charts/tractusx-connector/Chart.yaml +++ b/charts/tractusx-connector/Chart.yaml @@ -41,12 +41,12 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.6.0 +version: 0.7.0-rc1 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to # follow Semantic Versioning. They should reflect the version the application is using. # It is recommended to use it with quotes. -appVersion: "0.6.0" +appVersion: "0.7.0-rc1" home: https://github.com/eclipse-tractusx/tractusx-edc/tree/main/charts/tractusx-connector sources: - https://github.com/eclipse-tractusx/tractusx-edc/tree/main/charts/tractusx-connector diff --git a/charts/tractusx-connector/README.md b/charts/tractusx-connector/README.md index 67bfa298f..a734c214a 100644 --- a/charts/tractusx-connector/README.md +++ b/charts/tractusx-connector/README.md @@ -1,6 +1,6 @@ # tractusx-connector -![Version: 0.6.0](https://img.shields.io/badge/Version-0.6.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 0.6.0](https://img.shields.io/badge/AppVersion-0.6.0-informational?style=flat-square) +![Version: 0.7.0-rc1](https://img.shields.io/badge/Version-0.7.0--rc1-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 0.7.0-rc1](https://img.shields.io/badge/AppVersion-0.7.0--rc1-informational?style=flat-square) A Helm chart for Tractus-X Eclipse Data Space Connector. The connector deployment consists of two runtime consists of a Control Plane and a Data Plane. Note that _no_ external dependencies such as a PostgreSQL database and HashiCorp Vault are included. @@ -42,7 +42,7 @@ Combined, run this shell command to start the in-memory Tractus-X EDC runtime: ```shell helm repo add tractusx-edc https://eclipse-tractusx.github.io/charts/dev -helm install my-release tractusx-edc/tractusx-connector --version 0.6.0 \ +helm install my-release tractusx-edc/tractusx-connector --version 0.7.0-rc1 \ -f /tractusx-connector-test.yaml ``` diff --git a/gradle.properties b/gradle.properties index 223a9a840..1e6531c7e 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,5 +1,5 @@ group=org.eclipse.tractusx.edc -version=0.6.1-SNAPSHOT +version=0.7.0-rc1 # configure the build: txScmConnection=scm:git:git@github.com:eclipse-tractusx/tractusx-edc.git txWebsiteUrl=https://github.com/eclipse-tractusx/tractusx-edc.git