Skip to content

Commit

Permalink
feat: adds default scope extractor (#973)
Browse files Browse the repository at this point in the history
* feat: add default scope extractor + E2E test with iatp EDC components

* pr suggestions
  • Loading branch information
wolf4ood authored Jan 9, 2024
1 parent 07c2bcf commit d7adb17
Show file tree
Hide file tree
Showing 34 changed files with 1,635 additions and 55 deletions.
143 changes: 91 additions & 52 deletions DEPENDENCIES

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ public class JsonLdExtension implements ServiceExtension {
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";
public static final String SECURITY_ED25519_V1 = "https://w3id.org/security/suites/ed25519-2020/v1";

public static final String BUSINESS_PARTNER_DATA = "https://catenax-ng.github.io/product-core-schemas/businessPartnerData.json";
private static final String PREFIX = "document" + File.separator;
private static final Map<String, String> FILES = Map.of(
CREDENTIALS_V_1, PREFIX + "credential-v1.jsonld",
Expand All @@ -50,7 +52,8 @@ public class JsonLdExtension implements ServiceExtension {
SECURITY_JWS_V1, PREFIX + "security-jws-2020.jsonld",
SECURITY_ED25519_V1, PREFIX + "security-ed25519-2020.jsonld",
TX_CONTEXT, PREFIX + "tx-v1.jsonld",
EDC_CONTEXT, PREFIX + "edc-v1.jsonld");
EDC_CONTEXT, PREFIX + "edc-v1.jsonld",
BUSINESS_PARTNER_DATA, PREFIX + "businessPartnerData.json");
@Inject
private JsonLd jsonLdService;

Expand Down
192 changes: 192 additions & 0 deletions core/json-ld-core/src/main/resources/document/businessPartnerData.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
{
"@context": {
"@version": 1.1,
"@protected": true,
"BpnCredential": {
"@id": "https://raw.githubusercontent.com/catenax-ng/product-core-schemas/main/businessPartnerData#BpnCredential",
"@context": {
"@version": 1.1,
"@protected": true,
"id": "@id",
"type": "@type",
"bpn": "http://schema.org/identifier"
}
},
"MembershipCredential": {
"@id": "https://raw.githubusercontent.com/catenax-ng/product-core-schemas/main/businessPartnerData#MembershipCredential",
"@context": {
"@version": 1.1,
"@protected": true,
"id": "@id",
"type": "@type",
"ex": "https://example.org/examples#",
"startTime": {
"@id": "https://schema.org/startTime",
"@type": "https://schema.org/DateTime"
},
"memberOf": {
"@id": "https://schema.org/memberOf",
"@type": "https://schema.org/Text"
},
"status": {
"@id": "ex:status",
"@type": "https://schema.org/Text"
},
"holderIdentifier": {
"@id": "ctx:holderIdentifier"
}
}
},
"NameCredential": {
"@id": "https://raw.githubusercontent.com/catenax-ng/product-core-schemas/main/businessPartnerData#NameCredential",
"@context": {
"@version": 1.1,
"id": "@id",
"type": "@type",
"uuid": "http://schema.org/identifier",
"value": {
"@id": "ex:value",
"@type": "https://schema.org/Text"
},
"name": {
"@id": "ex:name",
"@type": "https://schema.org/Text"
},
"shortName": {
"@id": "ex:shortName",
"@type": "https://schema.org/Text"
},
"fipsCode": {
"@id": "ex:fipsCode",
"@type": "https://schema.org/Text"
},
"number": {
"@id": "ex:number",
"@type": "https://schema.org/Text"
},
"direction": {
"@id": "ex:direction",
"@type": "https://schema.org/Text"
},
"nameType": {
"@id": "ex:nameType",
"@type": "https://schema.org/object"
},
"language": {
"@id": "ex:language",
"@type": "https://schema.org/object"
},
"holderIdentifier": {
"@id": "ctx:holderIdentifier"
}
}
},
"BankAccountCredential": {
"@id": "https://raw.githubusercontent.com/catenax-ng/product-core-schemas/main/businessPartnerData#BankAccountCredential",
"@context": {
"@version": 1.1,
"id": "@id",
"type": "@type",
"uuid": "http://schema.org/identifier",
"trustScores": {
"@id": "ex:trustScores"
},
"nationalBankIdentifier": {
"@id": "ex:nationalBankIdentifier",
"@type": "https://schema.org/Text"
},
"nationalBankAccountIdentifier": {
"@id": "ex:nationalBankAccountIdentifier",
"@type": "https://schema.org/Text"
},
"internationalBankIdentifier": {
"@id": "ex:internationalBankIdentifier",
"@type": "https://schema.org/Text"
},
"internationalBankAccountIdentifier": {
"@id": "ex:internationalBankAccountIdentifier",
"@type": "https://schema.org/Text"
},
"currency": {
"@id": "ex:typeOf",
"@type": "https://schema.org/object"
},
"holderIdentifier": {
"@id": "ctx:holderIdentifier"
}
}
},
"AddressCredential": {
"@id": "https://raw.githubusercontent.com/catenax-ng/product-core-schemas/main/businessPartnerData#AddressCredential",
"@context": {
"@version": 1.1,
"id": "@id",
"type": "@type",
"uuid": "http://schema.org/identifier",
"version": {
"@id": "ex:typeOf",
"@type": "https://schema.org/object"
},
"careOf": {
"@id": "ex:careOf",
"@type": "https://schema.org/Text"
},
"contexts": {
"@id": "ex:contexts"
},
"bpn": {
"@id": "ex:bpn"
},
"country": {
"@id": "ex:country",
"@type": "https://schema.org/object"
},
"administrativeAreas": {
"@id": "ex:administrativeAreas"
},
"postCodes": {
"@id": "ex:postCodes"
},
"localities": {
"@id": "ex:localities"
},
"thoroughfares": {
"@id": "ex:thoroughfares"
},
"premises": {
"@id": "ex:premises"
},
"postalDeliveryPoints": {
"@id": "ex:postalDeliveryPoints"
},
"geographicCoordinates": {
"@id": "ex:geographicCoordinates",
"@type": "https://schema.org/object"
},
"types": {
"@id": "ex:types"
},
"holderIdentifier": {
"@id": "ctx:holderIdentifier"
}
}
},
"LegalFormCredential": {
"@id": "https://raw.githubusercontent.com/catenax-ng/product-core-schemas/main/businessPartnerData#LegalFormCredential",
"@context": {
"@version": 1.1,
"id": "@id",
"type": "@type",
"technicalKey": {"@id": "ex:technicalKey", "@type":"https://schema.org/Text"},
"name": {"@id": "ex:name", "@type":"https://schema.org/Text"},
"url": {"@id": "ex:url", "@type":"https://schema.org/Text"},
"mainAbbreviation": {"@id": "https://schema.org/Text#4", "@type":"https://schema.org/Text"},
"language": {"@id": "https://schema.org/Text#5", "@type":"https://schema.org/object"},
"categories": {"@id": "https://schema.org/Text#6", "@type":"https://schema.org/ItemList"},
"holderIdentifier": {
"@id": "ctx:holderIdentifier"
}
}
}
}
}
26 changes: 26 additions & 0 deletions edc-extensions/iatp/tx-iatp/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
* Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
*
* This program and the accompanying materials are made available under the
* terms of the Apache License, Version 2.0 which is available at
* https://www.apache.org/licenses/LICENSE-2.0
*
* SPDX-License-Identifier: Apache-2.0
*
* Contributors:
* Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - initial API and implementation
*
*/

plugins {
`java-library`
`maven-publish`
}

dependencies {
implementation(libs.edc.spi.core)
implementation(libs.edc.spi.policyengine)
implementation(libs.edc.identity.core.trust)

testImplementation(libs.edc.junit)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
/*
* Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
*
* This program and the accompanying materials are made available under the
* terms of the Apache License, Version 2.0 which is available at
* https://www.apache.org/licenses/LICENSE-2.0
*
* SPDX-License-Identifier: Apache-2.0
*
* Contributors:
* Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - initial API and implementation
*
*/

package org.eclipse.tractusx.edc.iam.iatp;

import org.eclipse.edc.policy.engine.spi.PolicyEngine;
import org.eclipse.edc.runtime.metamodel.annotation.Extension;
import org.eclipse.edc.runtime.metamodel.annotation.Inject;
import org.eclipse.edc.runtime.metamodel.annotation.Setting;
import org.eclipse.edc.spi.monitor.Monitor;
import org.eclipse.edc.spi.system.ServiceExtension;
import org.eclipse.edc.spi.system.ServiceExtensionContext;
import org.eclipse.edc.spi.system.configuration.Config;
import org.eclipse.tractusx.edc.iam.iatp.scope.DefaultScopeExtractor;

import java.util.Set;
import java.util.stream.Collectors;

import static java.lang.String.format;
import static org.eclipse.edc.iam.identitytrust.core.IatpScopeExtractorExtension.CATALOG_REQUEST_SCOPE;
import static org.eclipse.edc.iam.identitytrust.core.IatpScopeExtractorExtension.NEGOTIATION_REQUEST_SCOPE;
import static org.eclipse.edc.iam.identitytrust.core.IatpScopeExtractorExtension.TRANSFER_PROCESS_REQUEST_SCOPE;
import static org.eclipse.tractusx.edc.iam.iatp.IatpScopeExtension.NAME;

@Extension(NAME)
public class IatpScopeExtension implements ServiceExtension {

public static final String TX_IATP_DEFAULT_SCOPE_PREFIX = "edc.iam.iatp.default-scopes";

public static final String TX_IATP_DEFAULT_SCOPE_PREFIX_CONFIG_ALIAS = TX_IATP_DEFAULT_SCOPE_PREFIX + ".<scopeAlias>.";

@Setting(context = TX_IATP_DEFAULT_SCOPE_PREFIX_CONFIG_ALIAS, value = "The alias of the scope e.g. org.eclipse.edc.vc.type", required = true)
public static final String ALIAS = "alias";

@Setting(context = TX_IATP_DEFAULT_SCOPE_PREFIX_CONFIG_ALIAS, value = "The alias of the scope e.g. MembershipCredential", required = true)
public static final String TYPE = "type";

@Setting(context = TX_IATP_DEFAULT_SCOPE_PREFIX_CONFIG_ALIAS, value = "The alias of the scope e.g. read", required = true)
public static final String OPERATION = "operation";

public static final Set<String> DEFAULT_SCOPES = Set.of("org.eclipse.tractusx.vc.type:MembershipCredential:read");

static final String NAME = "Tractusx scope mapping extension";

@Inject
private PolicyEngine policyEngine;

@Inject
private Monitor monitor;

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

@Override
public void initialize(ServiceExtensionContext context) {
var contextMappingFunction = new DefaultScopeExtractor(defaultScopes(context));
policyEngine.registerPostValidator(CATALOG_REQUEST_SCOPE, contextMappingFunction);
policyEngine.registerPostValidator(NEGOTIATION_REQUEST_SCOPE, contextMappingFunction);
policyEngine.registerPostValidator(TRANSFER_PROCESS_REQUEST_SCOPE, contextMappingFunction);
}


private Set<String> defaultScopes(ServiceExtensionContext context) {
var config = context.getConfig(TX_IATP_DEFAULT_SCOPE_PREFIX);
var scopes = config.partition().map(this::createScope).collect(Collectors.toSet());

if (scopes.isEmpty()) {
monitor.info(format("No default scope from configuration. Using the default ones %s", DEFAULT_SCOPES));
return DEFAULT_SCOPES;
} else {
return scopes;
}
}

private String createScope(Config config) {
var alias = config.getString(ALIAS);
var type = config.getString(TYPE);
var operation = config.getString(OPERATION);
return format("%s:%s:%s", alias, type, operation);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
*
* This program and the accompanying materials are made available under the
* terms of the Apache License, Version 2.0 which is available at
* https://www.apache.org/licenses/LICENSE-2.0
*
* SPDX-License-Identifier: Apache-2.0
*
* Contributors:
* Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - initial API and implementation
*
*/

package org.eclipse.tractusx.edc.iam.iatp.scope;

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.TokenParameters;

import java.util.HashSet;
import java.util.Set;
import java.util.function.BiFunction;

import static java.lang.String.format;

/**
* Extract for TX default scopes e.g. MembershipCredential scope
*/
public class DefaultScopeExtractor implements BiFunction<Policy, PolicyContext, Boolean> {

private final Set<String> defaultScopes;

public DefaultScopeExtractor(Set<String> defaultScopes) {
this.defaultScopes = defaultScopes;
}

@Override
public Boolean apply(Policy policy, PolicyContext policyContext) {
var tokenBuilder = policyContext.getContextData(TokenParameters.Builder.class);
if (tokenBuilder == null) {
throw new EdcException(format("%s not set in policy context", TokenParameters.Builder.class.getName()));
}

var tokenParam = tokenBuilder.build();
var existingScope = tokenParam.getScope();
var newScopes = new HashSet<>(defaultScopes);
newScopes.add(existingScope);
tokenBuilder.scope(String.join(" ", newScopes).trim());
return true;
}

public Set<String> getDefaultScopes() {
return defaultScopes;
}
}
Loading

0 comments on commit d7adb17

Please sign in to comment.