diff --git a/.github/workflows/verify.yaml b/.github/workflows/verify.yaml index a1df254d0..e37f48b13 100644 --- a/.github/workflows/verify.yaml +++ b/.github/workflows/verify.yaml @@ -154,39 +154,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/edc-controlplane/edc-controlplane-base/build.gradle.kts b/edc-controlplane/edc-controlplane-base/build.gradle.kts index 85fbd011c..4a9b0b3bb 100644 --- a/edc-controlplane/edc-controlplane-base/build.gradle.kts +++ b/edc-controlplane/edc-controlplane-base/build.gradle.kts @@ -42,10 +42,6 @@ dependencies { // needed for SSI 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.connector) runtimeOnly(libs.edc.core.controlplane) 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/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/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-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..be42726fc 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,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") } implementation(project(":core:json-ld-core")) implementation(project(":edc-extensions:iatp:tx-iatp")) 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..a6adb4869 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 @@ -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") } implementation(project(":edc-extensions:cx-policy")) implementation(project(":core:json-ld-core")) 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..007398b09 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 @@ -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(":edc-extensions:cx-policy")) 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/settings.gradle.kts b/settings.gradle.kts index 88ad36697..713b84750 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,9 +64,7 @@ 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") 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"} - } - } - """; - - -}