diff --git a/edc-extension4aas/src/main/java/de/fraunhofer/iosb/app/client/ClientEndpoint.java b/edc-extension4aas/src/main/java/de/fraunhofer/iosb/app/client/ClientEndpoint.java index ba16bbb3..0a860398 100644 --- a/edc-extension4aas/src/main/java/de/fraunhofer/iosb/app/client/ClientEndpoint.java +++ b/edc-extension4aas/src/main/java/de/fraunhofer/iosb/app/client/ClientEndpoint.java @@ -24,6 +24,7 @@ import jakarta.ws.rs.core.MediaType; import jakarta.ws.rs.core.Response; import org.eclipse.edc.connector.contract.spi.types.agreement.ContractAgreement; +import org.eclipse.edc.connector.contract.spi.types.negotiation.ContractRequest; import org.eclipse.edc.connector.contract.spi.types.offer.ContractOffer; import org.eclipse.edc.connector.policy.spi.PolicyDefinition; import org.eclipse.edc.policy.model.Policy; @@ -34,6 +35,7 @@ import java.util.concurrent.ExecutionException; import static java.lang.String.format; +import static org.eclipse.edc.protocol.dsp.spi.types.HttpMessageProtocol.DATASPACE_PROTOCOL_HTTP; /** * Automated contract negotiation @@ -87,6 +89,7 @@ public ClientEndpoint(PolicyService policyService, @POST @Path(NEGOTIATE_PATH) public Response negotiateContract(@QueryParam("providerUrl") URL providerUrl, + @QueryParam("providerId") String providerId, @QueryParam("assetId") String assetId, @QueryParam("dataDestinationUrl") URL dataDestinationUrl) { LOGGER.debug(format("Received a %s POST request", NEGOTIATE_PATH)); @@ -103,16 +106,22 @@ public Response negotiateContract(@QueryParam("providerUrl") URL providerUrl, .build(); } - ContractOffer offer = ContractOffer.Builder.newInstance() + var offer = ContractOffer.Builder.newInstance() .id(idPolicyPair.getFirst()) .policy(idPolicyPair.getSecond()) .assetId(assetId) - .providerId(providerUrl.toString()) + .build(); + + var contractRequest = ContractRequest.Builder.newInstance() + .contractOffer(offer) + .counterPartyAddress(providerUrl.toString()) + .providerId(providerId) + .protocol(DATASPACE_PROTOCOL_HTTP) .build(); ContractAgreement agreement; try { - agreement = negotiator.negotiate(providerUrl, offer); + agreement = negotiator.negotiate(contractRequest); } catch (InterruptedException | ExecutionException negotiationException) { LOGGER.error(format("Negotiation failed for provider %s and contractOffer %s", providerUrl, offer.getId()), negotiationException); @@ -153,22 +162,19 @@ public Response getDataset(@QueryParam("providerUrl") URL providerUrl, * Initiate a contract negotiation, acting as a consumer, with a provider * connector. * - * @param providerUrl The provider's url. - * @param contractOffer A contract offer to be negotiated with. + * @param contractRequest The contract request to be sent. * @return An agreementID on success or an error message on error. */ @POST @Path(NEGOTIATE_CONTRACT_PATH) - public Response negotiateContract(@QueryParam("providerUrl") URL providerUrl, - ContractOffer contractOffer) { - Objects.requireNonNull(providerUrl, "Provider URL must not be null"); - Objects.requireNonNull(contractOffer, "ContractOffer must not be null"); + public Response negotiateContract(ContractRequest contractRequest) { + Objects.requireNonNull(contractRequest, "ContractOffer must not be null"); try { - var agreement = negotiator.negotiate(providerUrl, contractOffer); - return Response.ok(agreement).build(); + var agreement = negotiator.negotiate(contractRequest); + return Response.ok(agreement).build(); // TODO contract request instead of contractoffer: do whole change } catch (InterruptedException | ExecutionException negotiationException) { - LOGGER.error(format("Negotiation failed for provider %s and contractOffer %s", providerUrl, - contractOffer.getId()), negotiationException); + LOGGER.error(format("Negotiation failed for provider %s and contractOffer %s", contractRequest.getProviderId(), + contractRequest.getContractOffer().getId()), negotiationException); return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(negotiationException.getMessage()) .build(); } diff --git a/edc-extension4aas/src/main/java/de/fraunhofer/iosb/app/client/contract/PolicyService.java b/edc-extension4aas/src/main/java/de/fraunhofer/iosb/app/client/contract/PolicyService.java index 3f54a491..b7a48a19 100644 --- a/edc-extension4aas/src/main/java/de/fraunhofer/iosb/app/client/contract/PolicyService.java +++ b/edc-extension4aas/src/main/java/de/fraunhofer/iosb/app/client/contract/PolicyService.java @@ -91,7 +91,8 @@ public PolicyService(CatalogService catalogService, TypeTransformerRegistry tran * otherwise occupied, and was interrupted. */ public Dataset getDatasetForAssetId(URL providerUrl, String assetId) throws InterruptedException { - var catalogFuture = catalogService.request(providerUrl.toString(), + var catalogFuture = catalogService.requestCatalog( + providerUrl.toString(), DATASPACE_PROTOCOL_HTTP, QuerySpec.Builder.newInstance() .filter(List.of(criterion(Asset.PROPERTY_ID, "=", assetId))) diff --git a/edc-extension4aas/src/main/java/de/fraunhofer/iosb/app/client/dataTransfer/TransferInitiator.java b/edc-extension4aas/src/main/java/de/fraunhofer/iosb/app/client/dataTransfer/TransferInitiator.java index 2c693a2f..08d84885 100644 --- a/edc-extension4aas/src/main/java/de/fraunhofer/iosb/app/client/dataTransfer/TransferInitiator.java +++ b/edc-extension4aas/src/main/java/de/fraunhofer/iosb/app/client/dataTransfer/TransferInitiator.java @@ -19,7 +19,6 @@ import de.fraunhofer.iosb.app.client.ClientEndpoint; import de.fraunhofer.iosb.app.model.configuration.Configuration; import org.eclipse.edc.connector.transfer.spi.TransferProcessManager; -import org.eclipse.edc.connector.transfer.spi.types.DataRequest; import org.eclipse.edc.connector.transfer.spi.types.TransferRequest; import org.eclipse.edc.spi.EdcException; import org.eclipse.edc.spi.types.domain.DataAddress; @@ -114,21 +113,16 @@ public CompletableFuture initiateTransferProcess(URL providerUrl, String var dataFuture = new CompletableFuture(); observable.register(dataFuture, agreementId); - var dataRequest = DataRequest.Builder.newInstance() + var transferRequest = TransferRequest.Builder.newInstance() .id(UUID.randomUUID().toString()) // this is not relevant, thus can be random .connectorAddress(providerUrl.toString()) // the address of the provider connector .protocol(DATASPACE_PROTOCOL_HTTP) .connectorId("consumer") .assetId(assetId) .dataDestination(dataSinkAddress) - .managedResources(false) // we do not need any provisioning .contractId(agreementId) .build(); - var transferRequest = TransferRequest.Builder.newInstance() - .dataRequest(dataRequest) - .build(); - var transferProcessStatus = transferProcessManager.initiateConsumerRequest(transferRequest); if (transferProcessStatus.failed()) { throw new EdcException(transferProcessStatus.getFailureDetail()); diff --git a/edc-extension4aas/src/main/java/de/fraunhofer/iosb/app/client/negotiation/Negotiator.java b/edc-extension4aas/src/main/java/de/fraunhofer/iosb/app/client/negotiation/Negotiator.java index d45db30f..aad6ab28 100644 --- a/edc-extension4aas/src/main/java/de/fraunhofer/iosb/app/client/negotiation/Negotiator.java +++ b/edc-extension4aas/src/main/java/de/fraunhofer/iosb/app/client/negotiation/Negotiator.java @@ -22,19 +22,15 @@ import org.eclipse.edc.connector.contract.spi.types.agreement.ContractAgreement; import org.eclipse.edc.connector.contract.spi.types.negotiation.ContractNegotiation; import org.eclipse.edc.connector.contract.spi.types.negotiation.ContractRequest; -import org.eclipse.edc.connector.contract.spi.types.negotiation.ContractRequestData; -import org.eclipse.edc.connector.contract.spi.types.offer.ContractOffer; import org.eclipse.edc.spi.EdcException; import org.eclipse.edc.spi.query.QuerySpec; -import java.net.URL; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import static java.lang.String.format; -import static org.eclipse.edc.protocol.dsp.spi.types.HttpMessageProtocol.DATASPACE_PROTOCOL_HTTP; /** * Send contract offer, negotiation status watch @@ -65,8 +61,7 @@ public Negotiator(ConsumerContractNegotiationManager consumerNegotiationManager, /** * Negotiate a contract agreement using the given contract offer if no agreement exists for this constellation. * - * @param providerUrl The provider of the data. - * @param contractOffer The object of negotiation. + * @param contractRequest The contract request to be sent. * @return contractAgreement of the completed negotiation. * @throws ExecutionException Attempted to retrieve the agreementId but the * task aborted by throwing an exception. This @@ -75,28 +70,16 @@ public Negotiator(ConsumerContractNegotiationManager consumerNegotiationManager, * @throws InterruptedException Thread for agreementId was waiting, sleeping, or * otherwise occupied, and was interrupted. */ - public ContractAgreement negotiate(URL providerUrl, ContractOffer contractOffer) + public ContractAgreement negotiate(ContractRequest contractRequest) throws InterruptedException, ExecutionException { - var contractRequestData = ContractRequestData.Builder.newInstance() - .connectorId("anonymous") - .counterPartyAddress(providerUrl.toString()) - .contractOffer(contractOffer) - .protocol(DATASPACE_PROTOCOL_HTTP) - .build(); - - var contractRequest = ContractRequest.Builder.newInstance() - .requestData(contractRequestData) - .build(); - var previousAgreements = contractNegotiationStore.queryAgreements(QuerySpec.max()); var relevantAgreements = previousAgreements - .filter(agreement -> agreement.getAssetId().equals(contractOffer.getAssetId())) - .filter(agreement -> agreement.getProviderId().equals(contractOffer.getProviderId())) + .filter(agreement -> agreement.getAssetId().equals(contractRequest.getContractOffer().getAssetId())) + .filter(agreement -> agreement.getProviderId().equals(contractRequest.getProviderId())) .toList(); - if (relevantAgreements.size() > 0) { // An agreement exists for this asset & provider - return relevantAgreements.get(0); // Pick first agreement, hope contractNegotiationStore removes invalid - // agreements + if (!relevantAgreements.isEmpty()) { + return relevantAgreements.get(0); // assuming contractNegotiationStore removes invalid agreements } var result = consumerNegotiationManager.initiate(contractRequest); diff --git a/edc-extension4aas/src/main/java/de/fraunhofer/iosb/app/controller/ResourceController.java b/edc-extension4aas/src/main/java/de/fraunhofer/iosb/app/controller/ResourceController.java index 3452742d..ce2301ea 100644 --- a/edc-extension4aas/src/main/java/de/fraunhofer/iosb/app/controller/ResourceController.java +++ b/edc-extension4aas/src/main/java/de/fraunhofer/iosb/app/controller/ResourceController.java @@ -62,12 +62,4 @@ public void deleteAssetAndContracts(String assetId) { resourceAgent.deleteAsset(assetId); } - /** - * Removes a contract - * - * @param contractId The contract id - */ - public void deleteContract(String contractId) { - contractHandler.deleteContractDefinition(contractId); - } } diff --git a/edc-extension4aas/src/main/java/de/fraunhofer/iosb/app/edc/ContractHandler.java b/edc-extension4aas/src/main/java/de/fraunhofer/iosb/app/edc/ContractHandler.java index dfa5c641..30e6a2d9 100644 --- a/edc-extension4aas/src/main/java/de/fraunhofer/iosb/app/edc/ContractHandler.java +++ b/edc-extension4aas/src/main/java/de/fraunhofer/iosb/app/edc/ContractHandler.java @@ -28,13 +28,13 @@ import org.eclipse.edc.policy.model.Policy; import org.eclipse.edc.spi.query.Criterion; import org.eclipse.edc.spi.query.QuerySpec; -import org.eclipse.edc.spi.result.StoreResult; import org.eclipse.edc.spi.types.domain.asset.Asset; import java.io.IOException; import java.nio.file.Path; import java.util.List; import java.util.Objects; +import java.util.Optional; import static java.lang.String.format; @@ -62,22 +62,32 @@ public class ContractHandler { private final Logger logger; private final ObjectReader objectReader; + private final Policy defaultPolicy; + + /** + * Creates an instance of the ContractHandler class. + * + * @param contractStore Needed to manage EDC contracts. + * @param policyStore Needed to manage EDC policies. + */ public ContractHandler(ContractDefinitionStore contractStore, PolicyDefinitionStore policyStore) { - Objects.requireNonNull(contractStore); - Objects.requireNonNull(policyStore); + Objects.requireNonNull(contractStore, "ContractDefinitionStore"); + Objects.requireNonNull(policyStore, "PolicyDefinitionStore"); this.contractDefinitionStore = contractStore; this.policyDefinitionStore = policyStore; + + defaultPolicy = initializeDefaultPolicy(); + configuration = Configuration.getInstance(); logger = Logger.getInstance(); - var objectMapper = new ObjectMapper(); - objectReader = objectMapper.readerFor(Policy.class); + objectReader = new ObjectMapper().readerFor(Policy.class); } /** - * Registers the given assetId to the default contract. + * Registers the given assetId to the default contract with the default access and contract policies. * * @param assetId The asset ID - * @return Contract id of contract this assetId was registered to + * @return Contract id of contract this assetId was registered to. */ public String registerAssetToDefaultContract(String assetId) { Objects.requireNonNull(assetId); @@ -97,19 +107,16 @@ public void deleteContractsWithAssetId(String assetId) { .forEach(contract -> contractDefinitionStore.deleteById(contract.getId())); } - /** - * Deletes the contract definition with the given id. Wraps - * {@link org.eclipse.edc.connector.contract.spi.offer.store.ContractDefinitionStore#deleteById(String) - * ContractDefinitionStore.deleteById()} - * - * @param contractId Contract to be deleted - * @return The removed contract definition or null if the contract definition - * was not found - */ - public StoreResult deleteContractDefinition(String contractId) { - return contractDefinitionStore.deleteById(contractId); + + private Policy initializeDefaultPolicy() { + return Policy.Builder.newInstance() + .permission(Permission.Builder.newInstance() + .action(Action.Builder.newInstance().type("USE").build()) + .build()) + .build(); } + private String createDefaultContract(String assetId) { contractNumber++; var accessPolicyId = DEFAULT_ACCESS_POLICY_UID + contractNumber; @@ -119,54 +126,19 @@ private String createDefaultContract(String assetId) { var defaultAccessPolicyPath = configuration.getDefaultAccessPolicyPath(); var defaultContractPolicyPath = configuration.getDefaultContractPolicyPath(); - var usePermissionPolicy = Policy.Builder.newInstance() - .permission(Permission.Builder.newInstance() - .action(Action.Builder.newInstance().type("USE").build()) - //.target(assetId) - .build()) - //.type(PolicyType.CONTRACT) - //.target(assetId) - .build(); + var defaultAccessPolicy = getPolicyDefinitionFromFile(defaultAccessPolicyPath).orElse(defaultPolicy); + var defaultContractPolicy = getPolicyDefinitionFromFile(defaultContractPolicyPath).orElse(defaultPolicy); var defaultAccessPolicyDefinition = PolicyDefinition.Builder.newInstance() .id(accessPolicyId) - .policy(usePermissionPolicy) + .policy(defaultAccessPolicy.withTarget(assetId)) .build(); var defaultContractPolicyDefinition = PolicyDefinition.Builder.newInstance() .id(contractPolicyId) - .policy(usePermissionPolicy) + .policy(defaultContractPolicy.withTarget(assetId)) .build(); - if (Objects.nonNull(defaultAccessPolicyPath)) { - try { - Policy defaultAccessPolicy = objectReader.readValue(Path.of(defaultAccessPolicyPath).toFile()); - defaultAccessPolicyDefinition = PolicyDefinition.Builder.newInstance() - .id(accessPolicyId) - .policy(defaultAccessPolicy.withTarget(assetId)) - .build(); - } catch (IOException ioException) { - logger.error( - format("Could not find a correct access policy at path %s. Using internal default policy.", - defaultAccessPolicyPath), - ioException); - } - } policyDefinitionStore.create(defaultAccessPolicyDefinition); - - if (Objects.nonNull(defaultContractPolicyPath)) { - try { - Policy defaultContractPolicy = objectReader.readValue(Path.of(defaultContractPolicyPath).toFile()); - defaultContractPolicyDefinition = PolicyDefinition.Builder.newInstance() - .id(contractPolicyId) - .policy(defaultContractPolicy.withTarget(assetId)) - .build(); - } catch (IOException ioException) { - logger.error( - format("Could not find a correct contract policy at path %s. Using internal default policy.", - defaultContractPolicyPath), - ioException); - } - } policyDefinitionStore.create(defaultContractPolicyDefinition); var defaultContractDefinition = ContractDefinition.Builder.newInstance() @@ -180,4 +152,21 @@ private String createDefaultContract(String assetId) { return contractDefinitionId; } + + private Optional getPolicyDefinitionFromFile(String filePath) { + if (Objects.isNull(filePath)) { + return Optional.empty(); + } + + try { + Policy filePolicy = objectReader.readValue(Path.of(filePath).toFile()); + return Optional.of(filePolicy); + } catch (IOException ioException) { + logger.error( + format("Could not find a valid policy at path %s. Using internal default policy.", + filePath), + ioException); + return Optional.empty(); + } + } } diff --git a/edc-extension4aas/src/main/java/de/fraunhofer/iosb/app/edc/ResourceHandler.java b/edc-extension4aas/src/main/java/de/fraunhofer/iosb/app/edc/ResourceHandler.java index e0e1f00f..c00da509 100644 --- a/edc-extension4aas/src/main/java/de/fraunhofer/iosb/app/edc/ResourceHandler.java +++ b/edc-extension4aas/src/main/java/de/fraunhofer/iosb/app/edc/ResourceHandler.java @@ -46,8 +46,10 @@ public String createAsset(String sourceUrl, String name, String contentType, Str .id(assetId) .name(name) .contentType(contentType) - .version(version).build(); - assetIndex.create(asset, dataAddress); + .version(version) + .dataAddress(dataAddress) + .build(); + assetIndex.create(asset); return assetId; } diff --git a/edc-extension4aas/src/main/java/de/fraunhofer/iosb/app/model/configuration/Configuration.java b/edc-extension4aas/src/main/java/de/fraunhofer/iosb/app/model/configuration/Configuration.java index 99cd6439..c48f179b 100644 --- a/edc-extension4aas/src/main/java/de/fraunhofer/iosb/app/model/configuration/Configuration.java +++ b/edc-extension4aas/src/main/java/de/fraunhofer/iosb/app/model/configuration/Configuration.java @@ -15,9 +15,7 @@ */ package de.fraunhofer.iosb.app.model.configuration; -import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.databind.annotation.JsonSerialize; import java.net.URL; import java.util.Objects; @@ -26,12 +24,9 @@ * Singleton class. * The configuration of the application. */ -@JsonSerialize -@JsonAutoDetect public class Configuration { private static final String SETTINGS_PREFIX = "edc.aas."; - private static Configuration instance; @JsonProperty(SETTINGS_PREFIX + "remoteAASLocation") @@ -73,6 +68,7 @@ public class Configuration { @JsonProperty(SETTINGS_PREFIX + "client.acceptedPolicyDefinitionsPath") private String acceptedPolicyDefinitionsPath; + public static synchronized Configuration getInstance() { if (Objects.isNull(instance)) { instance = new Configuration(); @@ -80,107 +76,68 @@ public static synchronized Configuration getInstance() { return instance; } + public URL getRemoteAasLocation() { return remoteAasLocation; } - public void setRemoteAasLocation(URL remoteAasLocation) { - this.remoteAasLocation = remoteAasLocation; - } public String getLocalAasModelPath() { return localAasModelPath; } - public void setLocalAasModelPath(String localAasModelPath) { - this.localAasModelPath = localAasModelPath; - } public int getLocalAasServicePort() { return localAasServicePort; } - public void setLocalAasServicePort(int localAasServicePort) { - this.localAasServicePort = localAasServicePort; - } public String getAasServiceConfigPath() { return aasServiceConfigPath; } - public void setAasServiceConfigPath(String aasServiceConfigPath) { - this.aasServiceConfigPath = aasServiceConfigPath; - } public int getSyncPeriod() { return syncPeriod; } - public void setSyncPeriod(int syncPeriod) { - this.syncPeriod = syncPeriod; - } public boolean isExposeSelfDescription() { return exposeSelfDescription; } - public void setExposeSelfDescription(boolean exposeSelfDescription) { - this.exposeSelfDescription = exposeSelfDescription; - } public String getDefaultAccessPolicyPath() { return defaultAccessPolicyPath; } - public void setDefaultAccessPolicyPath(String defaultAccessPolicyPath) { - this.defaultAccessPolicyPath = defaultAccessPolicyPath; - } public String getDefaultContractPolicyPath() { return defaultContractPolicyPath; } - public void setDefaultContractPolicyPath(String defaultContractPolicyPath) { - this.defaultContractPolicyPath = defaultContractPolicyPath; - } public int getWaitForAgreementTimeout() { return waitForAgreementTimeout; } - public void setWaitForAgreementTimeout(int waitForAgreementTimeout) { - this.waitForAgreementTimeout = waitForAgreementTimeout; - } public int getWaitForTransferTimeout() { return waitForTransferTimeout; } - public void setWaitForTransferTimeout(int waitForTransferTimeout) { - this.waitForTransferTimeout = waitForTransferTimeout; - } public int getWaitForCatalogTimeout() { return waitForCatalogTimeout; } - public void setWaitForCatalogTimeout(int waitForCatalogTimeout) { - this.waitForCatalogTimeout = waitForCatalogTimeout; - } public boolean isAcceptAllProviderOffers() { return acceptAllProviderOffers; } - public void setAcceptAllProviderOffers(boolean acceptAllProviderOffers) { - this.acceptAllProviderOffers = acceptAllProviderOffers; - } public String getAcceptedPolicyDefinitionsPath() { return acceptedPolicyDefinitionsPath; } - - public void setAcceptedPolicyDefinitionsPath(String acceptedPolicyDefinitionsPath) { - this.acceptedPolicyDefinitionsPath = acceptedPolicyDefinitionsPath; - } } diff --git a/edc-extension4aas/src/main/java/de/fraunhofer/iosb/app/sync/Synchronizer.java b/edc-extension4aas/src/main/java/de/fraunhofer/iosb/app/sync/Synchronizer.java index 2b503ff0..3e4922fa 100644 --- a/edc-extension4aas/src/main/java/de/fraunhofer/iosb/app/sync/Synchronizer.java +++ b/edc-extension4aas/src/main/java/de/fraunhofer/iosb/app/sync/Synchronizer.java @@ -188,10 +188,7 @@ private void addAssetsContracts(List elements) { } private void removeAssetsContracts(List elements) { - elements.forEach(element -> { - resourceController.deleteAssetAndContracts(element.getIdsAssetId()); - resourceController.deleteContract(element.getIdsContractId()); - }); + elements.forEach(element -> resourceController.deleteAssetAndContracts(element.getIdsAssetId())); } @Override diff --git a/edc-extension4aas/src/test/java/de/fraunhofer/iosb/app/AasExtensionTest.java b/edc-extension4aas/src/test/java/de/fraunhofer/iosb/app/AasExtensionTest.java index 8a506d59..7e8e5076 100644 --- a/edc-extension4aas/src/test/java/de/fraunhofer/iosb/app/AasExtensionTest.java +++ b/edc-extension4aas/src/test/java/de/fraunhofer/iosb/app/AasExtensionTest.java @@ -15,7 +15,6 @@ */ package de.fraunhofer.iosb.app; -import de.fraunhofer.iosb.app.model.configuration.Configuration; import okhttp3.OkHttpClient; import org.eclipse.edc.api.auth.spi.AuthenticationService; import org.eclipse.edc.connector.contract.spi.negotiation.ConsumerContractNegotiationManager; @@ -66,9 +65,6 @@ void setup(ServiceExtensionContext context, ObjectFactory factory) { when(mockConf.getString("ids.webhook.address")).thenReturn("http://localhost:8080"); when(mockConf.getString("web.http.port")).thenReturn("1234"); when(mockConf.getString("web.http.path")).thenReturn("api-path"); - // Singleton testing is fun - Configuration.getInstance().setRemoteAasLocation(null); - Configuration.getInstance().setLocalAasModelPath(null); extension = factory.constructInstance(AasExtension.class); } diff --git a/edc-extension4aas/src/test/java/de/fraunhofer/iosb/app/client/ClientEndpointTest.java b/edc-extension4aas/src/test/java/de/fraunhofer/iosb/app/client/ClientEndpointTest.java index 149e884b..5c02b686 100644 --- a/edc-extension4aas/src/test/java/de/fraunhofer/iosb/app/client/ClientEndpointTest.java +++ b/edc-extension4aas/src/test/java/de/fraunhofer/iosb/app/client/ClientEndpointTest.java @@ -29,6 +29,7 @@ import org.eclipse.edc.connector.contract.spi.negotiation.observe.ContractNegotiationObservable; import org.eclipse.edc.connector.contract.spi.negotiation.store.ContractNegotiationStore; import org.eclipse.edc.connector.contract.spi.types.negotiation.ContractNegotiation; +import org.eclipse.edc.connector.contract.spi.types.negotiation.ContractRequest; import org.eclipse.edc.connector.contract.spi.types.offer.ContractOffer; import org.eclipse.edc.connector.policy.spi.PolicyDefinition; import org.eclipse.edc.connector.spi.catalog.CatalogService; @@ -119,7 +120,7 @@ private CatalogService mockCatalogService() throws IOException { var completableFuture = new CompletableFuture>(); completableFuture.complete(StatusResult.success(new ObjectMapper().writeValueAsBytes(mockCatalog))); - when(catalogService.request(any(), any(), any())).thenReturn(completableFuture); + when(catalogService.requestCatalog(any(), any(), any())).thenReturn(completableFuture); return catalogService; } @@ -145,11 +146,16 @@ public void shutdownMockServer() { @Test public void negotiateContractTest() { - try (var ignored = clientEndpoint.negotiateContract(url, - ContractOffer.Builder.newInstance() - .id(UUID.randomUUID().toString()) - .policy(mockPolicyDefinition.getPolicy()) - .assetId(UUID.randomUUID().toString()) + try (var ignored = clientEndpoint.negotiateContract( + ContractRequest.Builder.newInstance() + .counterPartyAddress(url.toString()) + .contractOffer( + ContractOffer.Builder.newInstance() + .id(UUID.randomUUID().toString()) + .policy(mockPolicyDefinition.getPolicy()) + .assetId(UUID.randomUUID().toString()) + .build()) + .protocol("dataspace-protocol-http") .build())) { fail(); } catch (EdcException expected) { @@ -164,7 +170,7 @@ public void negotiateContractTest() { @Disabled("Until catalog fetching works again") public void negotiateContractAndTransferTest() { // TODO repair after fixing ContractOfferService.class - try (var ignored = clientEndpoint.negotiateContract(url, "test-asset", null)) { + try (var ignored = clientEndpoint.negotiateContract(url, "test-id", "test-asset-id", null)) { fail(); } catch (EdcException expected) { } diff --git a/edc-extension4aas/src/test/java/de/fraunhofer/iosb/app/client/contract/PolicyServiceTest.java b/edc-extension4aas/src/test/java/de/fraunhofer/iosb/app/client/contract/PolicyServiceTest.java index 7162702d..6f8a64dc 100644 --- a/edc-extension4aas/src/test/java/de/fraunhofer/iosb/app/client/contract/PolicyServiceTest.java +++ b/edc-extension4aas/src/test/java/de/fraunhofer/iosb/app/client/contract/PolicyServiceTest.java @@ -66,7 +66,7 @@ void getPolicyForAssetIdTest() throws InterruptedException { assert catalogString != null; mockedFuture.complete(StatusResult.success(catalogString.getBytes(StandardCharsets.UTF_8))); - when(mockCatalogService.request(any(), any(), any())).thenReturn(mockedFuture); + when(mockCatalogService.requestCatalog(any(), any(), any())).thenReturn(mockedFuture); when(mockTransformer.transform(any(), any())).thenReturn(Result.success(Catalog.Builder.newInstance() .dataset(Dataset.Builder.newInstance() @@ -86,7 +86,7 @@ void getPolicyForAssetIdTest() throws InterruptedException { @Test void getContractUnreachableProviderTest() throws MalformedURLException, InterruptedException { var mockedFuture = new CompletableFuture>(); - when(mockCatalogService.request(any(), any(), any())).thenReturn(mockedFuture); + when(mockCatalogService.requestCatalog(any(), any(), any())).thenReturn(mockedFuture); try { policyService.getDatasetForAssetId(new URL("http://fakeUrl:4321/not/working"), "test-asset-id"); diff --git a/edc-extension4aas/src/test/java/de/fraunhofer/iosb/app/client/negotiation/NegotiatorTest.java b/edc-extension4aas/src/test/java/de/fraunhofer/iosb/app/client/negotiation/NegotiatorTest.java index 768dfae6..496caa10 100644 --- a/edc-extension4aas/src/test/java/de/fraunhofer/iosb/app/client/negotiation/NegotiatorTest.java +++ b/edc-extension4aas/src/test/java/de/fraunhofer/iosb/app/client/negotiation/NegotiatorTest.java @@ -21,6 +21,7 @@ import org.eclipse.edc.connector.contract.spi.negotiation.store.ContractNegotiationStore; import org.eclipse.edc.connector.contract.spi.types.agreement.ContractAgreement; import org.eclipse.edc.connector.contract.spi.types.negotiation.ContractNegotiation; +import org.eclipse.edc.connector.contract.spi.types.negotiation.ContractRequest; import org.eclipse.edc.connector.contract.spi.types.offer.ContractOffer; import org.eclipse.edc.policy.model.Action; import org.eclipse.edc.policy.model.Permission; @@ -78,8 +79,13 @@ void testNegotiate() throws MalformedURLException, ExecutionException, Interrupt .policy(mockPolicy) .build(); - var future = Executors.newSingleThreadExecutor().submit(() -> clientNegotiator.negotiate(fakeUrl, - contractOffer)); + var contractRequest = ContractRequest.Builder.newInstance() + .contractOffer(contractOffer) + .counterPartyAddress(fakeUrl.toString()) + .protocol("dataspace-protocol-http") + .build(); + + var future = Executors.newSingleThreadExecutor().submit(() -> clientNegotiator.negotiate(contractRequest)); // Let the negotiator think we need time to process // If not, the "confirmed" signal will be sent too soon, and the negotiator will // never complete diff --git a/example/build.gradle.kts b/example/build.gradle.kts index 3dd3cc0d..4a9f4e03 100644 --- a/example/build.gradle.kts +++ b/example/build.gradle.kts @@ -25,12 +25,15 @@ dependencies { // Identity and access management MOCK -> only for testing implementation("$group:iam-mock:$edcVersion") + + // Enables X-Api-Key auth implementation("$group:auth-tokenbased:$edcVersion") // Read configuration values implementation("$group:configuration-filesystem:$edcVersion") // Data transfer (read from AAS service/write to HTTP endpoint) + implementation("$group:control-plane-api-client:$edcVersion") implementation("$group:data-plane-core:$edcVersion") implementation("$group:data-plane-http:$edcVersion") implementation("$group:data-plane-client:$edcVersion") @@ -38,8 +41,10 @@ dependencies { implementation("$group:data-plane-selector-core:$edcVersion") implementation("$group:data-plane-selector-api:$edcVersion") implementation("$group:transfer-data-plane:$edcVersion") + } + application { mainClass.set("org.eclipse.edc.boot.system.runtime.BaseRuntime") } diff --git a/example/configurations/consumer.properties b/example/configurations/consumer.properties index 8ac1dede..af726333 100644 --- a/example/configurations/consumer.properties +++ b/example/configurations/consumer.properties @@ -23,3 +23,6 @@ edc.web.rest.cors.enabled=true edc.web.rest.cors.origins=* edc.web.rest.cors.headers=x-api-key, content-type edc.web.rest.cors.methods=GET, POST, DELETE, PUT, OPTIONS + +edc.dsp.id=consumer +edc.participant.id=consumer \ No newline at end of file diff --git a/example/configurations/provider.properties b/example/configurations/provider.properties index 95f22c4a..a4e79700 100644 --- a/example/configurations/provider.properties +++ b/example/configurations/provider.properties @@ -6,7 +6,7 @@ edc.aas.localAASServicePort=8080 # Provide a URL of an already running AAS service (such as FA³ST, BaSyx) # edc.aas.remoteAasLocation = http://example.com/aas # Period of synchronizing the EDC assetStore with the connected AAS services (in seconds) -edc.aas.syncPeriod=10 +edc.aas.syncPeriod=30 # Expose self description # Path to a default access policy definition file # edc.aas.defaultAccessPolicyDefinitionPath = ... @@ -16,7 +16,7 @@ edc.aas.syncPeriod=10 # Port and path for custom http services such as SelfDescription web.http.port=8181 web.http.path=/api -# Port and path for requesting an EDC to communicate with another EDC by IDS messages (consumer-provider) +# Port and path for requesting an EDC to communicate with another EDC by DSP messages (consumer-provider) web.http.management.port=8182 web.http.management.path=/management # Port and path for IDS messages (from another EDC) @@ -33,3 +33,6 @@ edc.web.rest.cors.enabled=true edc.web.rest.cors.origins=* edc.web.rest.cors.headers=x-api-key, content-type edc.web.rest.cors.methods=GET, POST, DELETE, PUT, OPTIONS + +edc.dsp.id=provider +edc.participant.id=provider \ No newline at end of file diff --git a/example/dataspaceconnector-configuration.properties b/example/dataspaceconnector-configuration.properties index dc009dd2..86ff082b 100644 --- a/example/dataspaceconnector-configuration.properties +++ b/example/dataspaceconnector-configuration.properties @@ -7,7 +7,7 @@ # AAS Extension specific # Supply AAS model + (port XOR AAS service config) for an AAS service internally started by the extension edc.aas.localAASModelPath=./resources/FestoDemoAAS.json -edc.aas.localAASServicePort=8080 +edc.aas.localAASServicePort=9090 # edc.aas.localAASServiceConfigPath = ./example/resources/exampleConfig.json # Provide a URL of an already running AAS service (such as FA³ST, BaSyx) # edc.aas.remoteAasLocation = http://example.com/aas @@ -27,18 +27,21 @@ edc.aas.client.waitForTransferTimeout=100 edc.aas.client.waitForAgreementTimeout=100 edc.aas.client.acceptAllProviderOffers=true # EDC specific values -web.http.port=8181 +web.http.port=9191 web.http.path=/api # Port and path for requesting an EDC to communicate with another EDC by IDS messages (consumer-provider) -web.http.management.port=8182 +web.http.management.port=9192 web.http.management.path=/management # Port and path for IDS messages (from another EDC) -web.http.protocol.port=8282 +web.http.protocol.port=9292 web.http.protocol.path=/dsp -edc.dsp.callback.address=http://localhost:8282/dsp +edc.dsp.callback.address=http://localhost:9292/dsp # edc.transfer.functions.enabled.protocols = https # Connector hostname, which e.g. is used in referer urls edc.hostname=localhost # Auth key for using internal EDC api (header key: x-api-key) edc.api.auth.key=password edc.jsonld.https.enabled=true + +edc.dsp.id=provider +edc.participant.id=provider \ No newline at end of file diff --git a/example/resources/aas_edc_extension.postman_collection.json b/example/resources/aas_edc_extension.postman_collection.json index 5880e710..2f8ba50e 100644 --- a/example/resources/aas_edc_extension.postman_collection.json +++ b/example/resources/aas_edc_extension.postman_collection.json @@ -1,6 +1,6 @@ { "info": { - "_postman_id": "582d7e09-588e-4635-8aec-eadfb21c0069", + "_postman_id": "11d46791-636f-49a5-8bb9-d040c8285963", "name": "EDC Extension", "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" }, @@ -217,8 +217,7 @@ }, { "key": "assetId", - "value": "{{asset-id}}", - "description": "May be null" + "value": "{{asset-id}}" } ] } @@ -232,7 +231,7 @@ "header": [], "body": { "mode": "raw", - "raw": "{\r\n \"id\": \"{{contract-offer-id}}\",\r\n \"policy\": {\r\n \"permissions\": [\r\n {\r\n \"edctype\": \"dataspaceconnector:permission\",\r\n \"target\": \"{{asset-id}}\",\r\n \"action\": {\r\n \"type\": \"USE\"\r\n }\r\n }\r\n ],\r\n \"target\": \"{{asset-id}}\"\r\n },\r\n \"assetId\": \"{{asset-id}}\",\r\n \"providerId\": \"urn:connector:provider\"\r\n}", + "raw": "{ \r\n \"@context\": {\r\n \"edc\": \"https://w3id.org/edc/v0.0.1/ns/\",\r\n \"odrl\": \"http://www.w3.org/ns/odrl/2/\"\r\n },\r\n \"providerId\": \"provider\",\r\n \"consumerId\": \"consumer\",\r\n \"connectorAddress\": \"{{provider}}\",\r\n \"protocol\": \"dataspace-protocol-http\",\r\n \"counterPartyId\": \"provider\",\r\n \"counterPartyAddress\": \"{{provider-dsp}}\",\r\n \"contractOffer\": {\r\n \"id\": \"DEFAULT_CONTRACT24:-1268910060:3886d894-3955-4b06-83c6-e86fdeb5e65a\",\r\n \"policy\": {\r\n \"permissions\": [\r\n {\r\n \"edctype\": \"dataspaceconnector:permission\",\r\n \"target\": \"{{asset-id}}\",\r\n \"action\": {\r\n \"type\": \"USE\"\r\n }\r\n }\r\n ],\r\n \"target\": \"{{asset-id}}\"\r\n },\r\n \"assetId\": \"{{asset-id}}\"\r\n }\r\n}", "options": { "raw": { "language": "json" @@ -240,7 +239,7 @@ } }, "url": { - "raw": "{{consumer}}/api/automated/negotiateContract?providerUrl={{provider-dsp}}", + "raw": "{{consumer}}/api/automated/negotiateContract", "host": [ "{{consumer}}" ], @@ -248,12 +247,6 @@ "api", "automated", "negotiateContract" - ], - "query": [ - { - "key": "providerUrl", - "value": "{{provider-dsp}}" - } ] } }, @@ -811,6 +804,13 @@ "v2", "contractdefinitions", "request" + ], + "query": [ + { + "key": "", + "value": null, + "disabled": true + } ] } }, @@ -964,12 +964,12 @@ }, { "key": "asset-id", - "value": "-1379397334", + "value": "", "type": "default" }, { "key": "contract-offer-id", - "value": "DEFAULT_CONTRACT2:-1379397334:cf2a9414-b759-4f62-b947-327e59585ab5", + "value": "", "type": "default" }, { diff --git a/gradle.properties b/gradle.properties index b306594c..f7323349 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,6 +1,6 @@ javaVersion=17 group=org.eclipse.edc -edcVersion=0.1.3 +edcVersion=0.3.0 faaastVersion=0.5.0 rsApi=3.1.0 okHttpVersion=4.10.0