Skip to content

Commit

Permalink
feat: register CX Policy Functions (#1075)
Browse files Browse the repository at this point in the history
* register new policy eval functions + e2e tests

* register new policy eval functions + e2e tests

* add e2e tests

* add negative tests

* fix tests

* DEPENDENCIES

* fixed test

* revert policy helper fct

* DEPENDENCIES, disabled MIW e2e tests

* disable tests involving MIW

* re-enable MIW tests

* rename cx-policy -> cx-policy-legacy

* add new module for new CX policy functions
  • Loading branch information
paullatzelsperger authored Feb 21, 2024
1 parent c99a8eb commit 08bd745
Show file tree
Hide file tree
Showing 54 changed files with 1,032 additions and 471 deletions.
4 changes: 1 addition & 3 deletions .github/workflows/verify.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -155,11 +155,9 @@ jobs:
miw-integration-tests:
runs-on: ubuntu-latest
needs: [ verify-formatting, verify-license-headers ]

steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/setup-java

- uses: actions/checkout@v4
- name: Starting MIW, Keycloak and Postgres Servers
run: |
Expand All @@ -172,7 +170,7 @@ jobs:
timeout_minutes: 5
max_attempts: 3
command: |
code=$(curl -IL -sw "%{http_code}" http://localhost:8000/api/actuator/health -o /dev/null)
code=$(curl -IL -sw "%{http_code}" http://localhost:8000/api/actuator/health -o /dev/null)
if [ "$code" -ne "401" ]; then
echo "MIW not ready yet, status = $code"
exit 1;
Expand Down
340 changes: 153 additions & 187 deletions DEPENDENCIES

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion edc-controlplane/edc-controlplane-base/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ dependencies {
runtimeOnly(project(":edc-extensions:ssi:ssi-identity-core"))
runtimeOnly(project(":edc-extensions:ssi:ssi-miw-credential-client"))
runtimeOnly(project(":edc-extensions:ssi:ssi-identity-extractor"))
runtimeOnly(project(":edc-extensions:cx-policy"))
runtimeOnly(project(":edc-extensions:cx-policy-legacy"))

runtimeOnly(libs.edc.core.controlplane)
runtimeOnly(libs.edc.core.policy.monitor)
Expand Down
33 changes: 33 additions & 0 deletions edc-extensions/cx-policy-legacy/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/********************************************************************************
* Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
*
* See the NOTICE file(s) distributed with this work for additional
* information regarding copyright ownership.
*
* This program and the accompanying materials are made available under the
* terms of the Apache License, Version 2.0 which is available at
* https://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* SPDX-License-Identifier: Apache-2.0
********************************************************************************/

plugins {
`java-library`
}

dependencies {
implementation(project(":spi:core-spi"))
implementation(project(":spi:ssi-spi"))
implementation(libs.edc.spi.policyengine)
implementation(libs.jakartaJson)
implementation(libs.edc.spi.identitytrust)
testImplementation(libs.jacksonJsonP)
testImplementation(libs.titaniumJsonLd)
testImplementation(testFixtures(project(":spi:ssi-spi")))
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/********************************************************************************
* Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
*
* See the NOTICE file(s) distributed with this work for additional
* information regarding copyright ownership.
*
* This program and the accompanying materials are made available under the
* terms of the Apache License, Version 2.0 which is available at
* https://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* SPDX-License-Identifier: Apache-2.0
********************************************************************************/

package org.eclipse.tractusx.edc.policy.cx;

import org.eclipse.edc.policy.engine.spi.PolicyEngine;
import org.eclipse.edc.policy.engine.spi.RuleBindingRegistry;
import org.eclipse.edc.runtime.metamodel.annotation.Inject;
import org.eclipse.edc.spi.system.ServiceExtension;
import org.eclipse.edc.spi.system.ServiceExtensionContext;

import static org.eclipse.tractusx.edc.policy.cx.summary.SummaryConstraintFunctionsProvider.registerBindings;
import static org.eclipse.tractusx.edc.policy.cx.summary.SummaryConstraintFunctionsProvider.registerFunctions;


/**
* Provides implementations of standard CX usage policies.
*/
public class CxPolicyExtension implements ServiceExtension {
private static final String NAME = "CX Policy";

@Inject
private PolicyEngine policyEngine;

@Inject
private RuleBindingRegistry bindingRegistry;

@Override
public String name() {
return NAME;
}

@Override
public void initialize(ServiceExtensionContext context) {

registerBindings(bindingRegistry);
registerFunctions(policyEngine);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/********************************************************************************
* Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
*
* See the NOTICE file(s) distributed with this work for additional
* information regarding copyright ownership.
*
* This program and the accompanying materials are made available under the
* terms of the Apache License, Version 2.0 which is available at
* https://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* SPDX-License-Identifier: Apache-2.0
********************************************************************************/

package org.eclipse.tractusx.edc.policy.cx.common;

import org.eclipse.edc.identitytrust.model.VerifiableCredential;
import org.eclipse.edc.policy.engine.spi.DynamicAtomicConstraintFunction;
import org.eclipse.edc.policy.engine.spi.PolicyContext;
import org.eclipse.edc.policy.model.Operator;
import org.eclipse.edc.policy.model.Permission;
import org.eclipse.edc.spi.agent.ParticipantAgent;
import org.eclipse.edc.spi.result.Result;

import java.util.Collection;
import java.util.List;

/**
* This is a base class for dynamically bound Tractus-X constraint evaluation functions that implements some basic common functionality and defines some
* common constants
*/
public abstract class AbstractDynamicCredentialConstraintFunction implements DynamicAtomicConstraintFunction<Permission> {
public static final String VC_CLAIM = "vc";
public static final String ACTIVE = "active";
public static final String CREDENTIAL_LITERAL = "Credential";
protected static final Collection<Operator> EQUALITY_OPERATORS = List.of(Operator.EQ, Operator.NEQ);

protected boolean checkOperator(Operator actual, PolicyContext context, Collection<Operator> 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<ParticipantAgent> 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<List<VerifiableCredential>> 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<VerifiableCredential>) 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);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -17,22 +17,21 @@
* SPDX-License-Identifier: Apache-2.0
********************************************************************************/

package org.eclipse.tractusx.edc.tests.transfer;
package org.eclipse.tractusx.edc.policy.cx.common;

import jakarta.json.JsonObject;
import org.eclipse.edc.junit.annotations.EndToEndTest;
import org.eclipse.edc.identitytrust.model.VerifiableCredential;

import java.util.Map;
import java.util.function.Predicate;

import static org.eclipse.tractusx.edc.helpers.PolicyHelperFunctions.TX_CREDENTIAL_NAMESPACE;
import static org.eclipse.tractusx.edc.helpers.PolicyHelperFunctions.frameworkPolicy;
public class CredentialTypePredicate implements Predicate<VerifiableCredential> {
private final String expectedType;

@EndToEndTest
public class IatpFrameworkAgreementHttpConsumerPullWithProxyInMemoryTest extends IatpHttpConsumerPullWithProxyInMemoryTest {
public CredentialTypePredicate(String expectedType) {
this.expectedType = expectedType;
}

@Override
protected JsonObject createContractPolicy(String bpn) {
return frameworkPolicy(Map.of(TX_CREDENTIAL_NAMESPACE + "FrameworkAgreement.pcf", "active"));
public boolean test(VerifiableCredential credential) {
return credential.getType().contains(expectedType);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/********************************************************************************
* Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
*
* See the NOTICE file(s) distributed with this work for additional
* information regarding copyright ownership.
*
* This program and the accompanying materials are made available under the
* terms of the Apache License, Version 2.0 which is available at
* https://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* SPDX-License-Identifier: Apache-2.0
********************************************************************************/

package org.eclipse.tractusx.edc.policy.cx.common;

/**
* Defines standard EDC policy scopes.
*/
public interface PolicyScopes {
String CATALOG_REQUEST_SCOPE = "request.catalog";
String NEGOTIATION_REQUEST_SCOPE = "request.contract.negotiation";
String TRANSFER_PROCESS_REQUEST_SCOPE = "request.transfer.process";

String CATALOG_SCOPE = "catalog";
String NEGOTIATION_SCOPE = "contract.negotiation";
String TRANSFER_PROCESS_SCOPE = "transfer.process";
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#################################################################################
# Copyright (c) 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
#
# See the NOTICE file(s) distributed with this work for additional
# information regarding copyright ownership.
#
# This program and the accompanying materials are made available under the
# terms of the Apache License, Version 2.0 which is available at
# https://www.apache.org/licenses/LICENSE-2.0.
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
# SPDX-License-Identifier: Apache-2.0
#################################################################################

org.eclipse.tractusx.edc.policy.cx.CxPolicyExtension

Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
/********************************************************************************
* Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
*
* See the NOTICE file(s) distributed with this work for additional
* information regarding copyright ownership.
*
* This program and the accompanying materials are made available under the
* terms of the Apache License, Version 2.0 which is available at
* https://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* SPDX-License-Identifier: Apache-2.0
********************************************************************************/

package org.eclipse.tractusx.edc.policy.cx;

import org.eclipse.edc.identitytrust.model.CredentialSubject;
import org.eclipse.edc.identitytrust.model.Issuer;
import org.eclipse.edc.identitytrust.model.VerifiableCredential;

import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.CX_CREDENTIAL_NS;

public class CredentialFunctions {

public static VerifiableCredential.Builder createCredential(String type, String version) {
return VerifiableCredential.Builder.newInstance()
.types(List.of(CX_CREDENTIAL_NS + "VerifiableCredential", CX_CREDENTIAL_NS + type))
.id(UUID.randomUUID().toString())
.issuer(new Issuer(UUID.randomUUID().toString(), Map.of("prop1", "val1")))
.expirationDate(Instant.now().plus(365, ChronoUnit.DAYS))
.issuanceDate(Instant.now())
.credentialSubject(CredentialSubject.Builder.newInstance()
.id("subject-id")
.claim(CX_CREDENTIAL_NS + "holderIdentifier", "did:web:holder")
.claim(CX_CREDENTIAL_NS + "contractVersion", version)
.claim(CX_CREDENTIAL_NS + "contractTemplate", "https://public.catena-x.org/contracts/pcf.v1.pdf")
.build());
}

public static VerifiableCredential.Builder createPcfCredential() {
return createCredential("PcfCredential", "1.0.0");
}

public static VerifiableCredential.Builder createDismantlerCredential(String... brands) {
return createDismantlerCredential(Arrays.asList(brands), "vehicleDismantle");
}

public static VerifiableCredential.Builder createDismantlerCredential(Collection<String> 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());
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,9 @@
import org.eclipse.edc.spi.system.ServiceExtension;
import org.eclipse.edc.spi.system.ServiceExtensionContext;

import static org.eclipse.tractusx.edc.policy.cx.summary.SummaryConstraintFunctionsProvider.registerBindings;
import static org.eclipse.tractusx.edc.policy.cx.summary.SummaryConstraintFunctionsProvider.registerFunctions;
import static org.eclipse.tractusx.edc.policy.cx.CxPolicyRegistration.registerBindings;
import static org.eclipse.tractusx.edc.policy.cx.CxPolicyRegistration.registerFunctions;


/**
* Provides implementations of standard CX usage policies.
Expand Down
Loading

0 comments on commit 08bd745

Please sign in to comment.