Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: add binding to tx namespace for credential policy #713

Merged
merged 1 commit into from
Aug 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions core/json-ld-core/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ plugins {
}

dependencies {
implementation(project(":spi:core-spi"))
implementation(libs.edc.spi.core)
implementation(libs.edc.spi.jsonld)
testImplementation(testFixtures(libs.edc.junit))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,15 @@

import static java.lang.String.format;
import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.EDC_CONTEXT;
import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.TX_CONTEXT;
import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.TX_NAMESPACE;
import static org.eclipse.tractusx.edc.edr.spi.CoreConstants.TX_PREFIX;

public class JsonLdExtension implements ServiceExtension {

public static final String CREDENTIALS_V_1 = "https://www.w3.org/2018/credentials/v1";

public static final String CREDENTIALS_SUMMARY_V_1 = "https://w3id.org/2023/catenax/credentials/summary/v1";
public static final String CREDENTIALS_SUMMARY_V_1_FALLBACK = "https://catenax-ng.github.io/product-core-schemas/SummaryVC.json";
public static final String SECURITY_JWS_V1 = "https://w3id.org/security/suites/jws-2020/v1";
Expand All @@ -43,7 +48,9 @@ public class JsonLdExtension implements ServiceExtension {
CREDENTIALS_SUMMARY_V_1, PREFIX + "summary-vc-context-v1.jsonld",
CREDENTIALS_SUMMARY_V_1_FALLBACK, PREFIX + "summary-vc-context-v1.jsonld",
SECURITY_JWS_V1, PREFIX + "security-jws-2020.jsonld",
SECURITY_ED25519_V1, PREFIX + "security-ed25519-2020.jsonld");
SECURITY_ED25519_V1, PREFIX + "security-ed25519-2020.jsonld",
TX_CONTEXT, PREFIX + "tx-v1.jsonld",
EDC_CONTEXT, PREFIX + "edc-v1.jsonld");
@Inject
private JsonLd jsonLdService;

Expand All @@ -52,6 +59,7 @@ public class JsonLdExtension implements ServiceExtension {

@Override
public void initialize(ServiceExtensionContext context) {
jsonLdService.registerNamespace(TX_PREFIX, TX_NAMESPACE);
FILES.entrySet().stream().map(this::mapToFile)
.forEach(result -> result.onSuccess(entry -> jsonLdService.registerCachedDocument(entry.getKey(), entry.getValue()))
.onFailure(failure -> monitor.warning("Failed to register cached json-ld document: " + failure.getFailureDetail())));
Expand Down
47 changes: 47 additions & 0 deletions core/json-ld-core/src/main/resources/document/edc-v1.jsonld
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
{
"@context": {
"edc": "https://w3id.org/edc/v0.0.1/ns/",
"@vocab": "https://w3id.org/edc/v0.0.1/ns/",
"schema": "http://schema.org/",
"PolicyDefinition": "edc:PolicyDefinition",
"AssetEntryNewDto": "edc:AssetEntryNewDto",
"DataAddress": "edc:DataAddress",
"NegotiationState": "edc:NegotiationState",
"TerminateNegotiation": "edc:TerminateNegotiation",
"ContractRequest": "edc:ContractRequest",
"policy": {
"@id": "edc:policy",
"@type": "@id",
"@context": [
"http://www.w3.org/ns/odrl.jsonld"
]
},
"createdAt": "edc:createdAt",
"properties": "edc:properties",
"privateProperties": "edc:privateProperties",
"dataAddress": "edc:dataAddress",
"type": "edc:type",
"counterPartyAddress": "edc:counterPartyAddress",
"protocol": "edc:protocol",
"querySpec": "edc:querySpec",
"accessPolicyId": "edc:accessPolicyId",
"contractPolicyId": "edc:contractPolicyId",
"assetsSelector": "edc:assetsSelector",
"state": "edc:state",
"reason": "edc:reason",
"connectorAddress": "edc:connectorAddress",
"offer": "edc:offer",
"asset": "edc:asset",
"offerId": "edc:offerId",
"assetId": "edc:assetId",
"contractId": "edc:contractId",
"connectorId": "edc:connectorId",
"callbackAddresses": "edc:callbackAddresses",
"dataDestination": "edc:dataDestination",
"baseUrl": "edc:baseUrl",
"providerId": "edc:providerId",
"uri": "edc:uri",
"events": "edc:events",
"transactional": "edc:transactional"
}
}
21 changes: 21 additions & 0 deletions core/json-ld-core/src/main/resources/document/tx-v1.jsonld
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"@context": {
"@version": 1.1,
"@protected": true,
"tx": "https://w3id.org/tractusx/v0.0.1/ns/",
"BusinessPartnerNumber": "tx:BusinessPartnerNumber",
"NegotiationInitiateRequestDto": "tx:NegotiationInitiateRequestDto",
"BusinessPartnerGroup": "tx:BusinessPartnerGroup",
"EndpointDataReferenceEntry": "tx:EndpointDataReferenceEntry",
"Membership": "tx:Membership",
"Dismantler": "tx:Dismantler",
"FrameworkAgreement.pcf": "tx:FrameworkAgreement.pcf",
"FrameworkAgreement.sustainability": "tx:FrameworkAgreement.sustainability",
"FrameworkAgreement.quality": "tx:FrameworkAgreement.quality",
"FrameworkAgreement.traceability": "tx:FrameworkAgreement.traceability",
"FrameworkAgreement.behavioraltwin": "tx:FrameworkAgreement.behavioraltwin",
"BPN": "tx:BPN",
"expirationDate": "tx:expirationDate",
"edrState": "tx:edrState"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import static org.eclipse.edc.connector.contract.spi.offer.ContractDefinitionResolver.CATALOGING_SCOPE;
import static org.eclipse.edc.connector.contract.spi.validation.ContractValidationService.NEGOTIATION_SCOPE;
import static org.eclipse.edc.connector.contract.spi.validation.ContractValidationService.TRANSFER_SCOPE;
import static org.eclipse.edc.policy.model.OdrlNamespace.ODRL_SCHEMA;

/**
* Registers a {@link org.eclipse.tractusx.edc.validation.businesspartner.functions.BusinessPartnerGroupFunction} for the following scopes:
Expand All @@ -49,7 +50,7 @@
* <p>
* Note that the {@link BusinessPartnerGroupFunction} is an {@link org.eclipse.edc.policy.engine.spi.AtomicConstraintFunction}, thus it is registered with the {@link PolicyEngine} for the {@link Permission} class.
*/
@Extension(value = "Registers a function to evaluate whether a BPN number is covered by a certain policy or not", categories = {"policy", "contract"})
@Extension(value = "Registers a function to evaluate whether a BPN number is covered by a certain policy or not", categories = { "policy", "contract" })
public class BusinessPartnerValidationExtension implements ServiceExtension {

private static final String USE = "USE";
Expand All @@ -71,6 +72,7 @@ public void initialize(ServiceExtensionContext context) {

private void bindToScope(BusinessPartnerGroupFunction function, String scope) {
ruleBindingRegistry.bind(USE, scope);
ruleBindingRegistry.bind(ODRL_SCHEMA + "use", scope);
ruleBindingRegistry.bind(BusinessPartnerGroupFunction.BUSINESS_PARTNER_CONSTRAINT_KEY, scope);

policyEngine.registerFunction(scope, Permission.class, BusinessPartnerGroupFunction.BUSINESS_PARTNER_CONSTRAINT_KEY, function);
Expand Down
1 change: 1 addition & 0 deletions edc-extensions/cx-policy/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ plugins {
}

dependencies {
implementation(project(":spi:core-spi"))
implementation(project(":spi:ssi-spi"))
implementation(libs.edc.spi.policyengine)
implementation(libs.jakartaJson)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,12 @@
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;
Expand All @@ -35,16 +39,26 @@ public class SummaryConstraintFunctionsProvider {
/**
* Mappings from policy constraint left operand values to the corresponding item value in the summary VP.
*/
static final Map<String, String> CREDENTIAL_MAPPINGS = Map.of(
"Membership", "MembershipCredential",
"Dismantler", "DismantlerCredential",
"FrameworkAgreement.pcf", "PcfCredential",
"FrameworkAgreement.sustainability", "SustainabilityCredential",
"FrameworkAgreement.quality", "QualityCredential",
"FrameworkAgreement.traceability", "TraceabilityCredential",
"FrameworkAgreement.behavioraltwin", "BehaviorTwinCredential",
"BPN", "BpnCredential"
);
static final Map<String, String> 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.
Expand Down Expand Up @@ -84,6 +98,11 @@ public static void registerBindings(RuleBindingRegistry registry) {
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);

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@

public class NegotiateEdrRequestDto {

public static final String EDR_REQUEST_DTO_TYPE = TX_NAMESPACE + "NegotiateEdrRequestDto";
public static final String EDR_REQUEST_SIMPLE_DTO_TYPE = "NegotiateEdrRequestDto";
public static final String EDR_REQUEST_DTO_TYPE = TX_NAMESPACE + EDR_REQUEST_SIMPLE_DTO_TYPE;
public static final String EDR_REQUEST_DTO_CONNECTOR_ADDRESS = EDC_NAMESPACE + "connectorAddress";
public static final String EDR_REQUEST_DTO_PROTOCOL = EDC_NAMESPACE + "protocol";
public static final String EDR_REQUEST_DTO_CONNECTOR_ID = EDC_NAMESPACE + "connectorId";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,18 @@
package org.eclipse.tractusx.edc.helpers;


import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.json.Json;
import jakarta.json.JsonArrayBuilder;
import jakarta.json.JsonObject;
import jakarta.json.JsonObjectBuilder;
import org.eclipse.edc.connector.policy.spi.PolicyDefinition;
import org.eclipse.edc.jsonld.util.JacksonJsonLd;
import org.eclipse.edc.policy.model.AtomicConstraint;
import org.eclipse.edc.policy.model.Operator;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Collection;
import java.util.Map;
Expand All @@ -42,6 +46,8 @@ public class PolicyHelperFunctions {
private static final String BUSINESS_PARTNER_EVALUATION_KEY = "BusinessPartnerNumber";
private static final String BUSINESS_PARTNER_CONSTRAINT_KEY = TX_NAMESPACE + "BusinessPartnerGroup";

private static final ObjectMapper MAPPER = JacksonJsonLd.createObjectMapper();

/**
* Creates a {@link PolicyDefinition} using the given ID, that contains equality constraints for each of the given BusinessPartnerNumbers:
* each BPN is converted into an {@link AtomicConstraint} {@code BusinessPartnerNumber EQ [BPN]}.
Expand Down Expand Up @@ -89,6 +95,30 @@ public static JsonObject frameworkPolicy(String id, Map<String, String> permissi
.build();
}


/**
* Creates a {@link PolicyDefinition} using the given ID, that contains equality constraints for each of the given BusinessPartnerNumbers:
* each BPN is converted into an {@link AtomicConstraint} {@code BusinessPartnerNumber EQ [BPN]}.
*/
public static JsonObject frameworkTemplatePolicy(String id, String frameworkKind) {
var template = fetchFrameworkTemplate().replace("${POLICY_ID}", id).replace("${FRAMEWORK_CREDENTIAL}", frameworkKind);
try {
return MAPPER.readValue(template, JsonObject.class);
} catch (IOException e) {
throw new RuntimeException(e);
}
}


private static String fetchFrameworkTemplate() {
try (var stream = PolicyHelperFunctions.class.getClassLoader().getResourceAsStream("framework-policy.json")) {
return new String(stream.readAllBytes(), StandardCharsets.UTF_8);
} catch (IOException e) {
throw new RuntimeException(e);
}

}

public static JsonObjectBuilder policyDefinitionBuilder() {
return Json.createObjectBuilder()
.add(TYPE, EDC_NAMESPACE + "PolicyDefinitionDto");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import static org.assertj.core.api.Assertions.assertThat;
import static org.eclipse.tractusx.edc.helpers.CatalogHelperFunctions.getDatasetAssetId;
import static org.eclipse.tractusx.edc.helpers.PolicyHelperFunctions.frameworkPolicy;
import static org.eclipse.tractusx.edc.helpers.PolicyHelperFunctions.frameworkTemplatePolicy;
import static org.eclipse.tractusx.edc.helpers.PolicyHelperFunctions.noConstraintPolicyDefinition;
import static org.eclipse.tractusx.edc.lifecycle.TestRuntimeConfiguration.SOKRATES_BPN;
import static org.eclipse.tractusx.edc.lifecycle.TestRuntimeConfiguration.SOKRATES_DSP_CALLBACK;
Expand Down Expand Up @@ -85,6 +86,38 @@ void requestCatalog_fulfillsPolicy_shouldReturnOffer() {
SOKRATES.createContractDefinition("test-asset-1", "test-def-2", "test-ap2", "test-cp1");


// act
var catalog = SOKRATES.getCatalogDatasets(SOKRATES);

// assert
assertThat(catalog).isNotEmpty()
.hasSize(1)
.allSatisfy(co -> {
assertThat(getDatasetAssetId(co)).isEqualTo("test-asset");
});

}


@Test
@DisplayName("Verify that Sokrates receives only the offers he is permitted to using @context")
void requestCatalog_fulfillsPolicy_shouldReturnOffer_withContexts() {
// arrange
SOKRATES.createAsset("test-asset");
SOKRATES.createAsset("test-asset-1");

var bpnAccessPolicy = frameworkTemplatePolicy("test-ap1", "BPN");
var contractPolicy = noConstraintPolicyDefinition("test-cp1");
var dismantlerAccessPolicy = frameworkTemplatePolicy("test-ap2", "Dismantler");

SOKRATES.createPolicy(bpnAccessPolicy);
SOKRATES.createPolicy(contractPolicy);
SOKRATES.createPolicy(dismantlerAccessPolicy);

SOKRATES.createContractDefinition("test-asset", "test-def", "test-ap1", "test-cp1");
SOKRATES.createContractDefinition("test-asset-1", "test-def-2", "test-ap2", "test-cp1");


// act
var catalog = SOKRATES.getCatalogDatasets(SOKRATES);

Expand Down
24 changes: 24 additions & 0 deletions edc-tests/e2e-tests/src/test/resources/framework-policy.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"@context": [
"https://w3id.org/edc/v0.0.1",
"https://w3id.org/tractusx/edc/v0.0.1",
"http://www.w3.org/ns/odrl.jsonld"
],
"@type": "PolicyDefinitionRequest",
"@id": "${POLICY_ID}",
"policy": {
"@type": "Set",
"permission": [
{
"action": "use",
"constraint": [
{
"leftOperand": "${FRAMEWORK_CREDENTIAL}",
"operator": "eq",
"rightOperand": "active"
}
]
}
]
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@ public final class CoreConstants {

public static final String TX_PREFIX = "tx";
public static final String TX_NAMESPACE = "https://w3id.org/tractusx/v0.0.1/ns/";

public static final String TX_CONTEXT = "https://w3id.org/tractusx/edc/v0.0.1";
public static final String EDC_CONTEXT = "https://w3id.org/edc/v0.0.1";


private CoreConstants() {
}
}
Loading