From cb57f7fdf477421bb09945ce894056532a75310e Mon Sep 17 00:00:00 2001 From: ndr_brt Date: Wed, 26 Jun 2024 18:03:20 +0200 Subject: [PATCH] feat: make pub/priv aliases mandatory at startup (#4304) * feat: make pub/priv alias mandatory at startup * test cleanup * get rid of the backend service --- .../asset/AssetEventDispatchTest.java | 2 + .../ContractDefinitionEventDispatchTest.java | 2 + .../ContractNegotiationEventDispatchTest.java | 2 + .../PolicyDefinitionEventDispatchTest.java | 2 + .../TransferProcessEventDispatchTest.java | 2 + .../DataPlaneDefaultIamServicesExtension.java | 28 +-- .../jsonld/serde/SerdeIntegrationTest.java | 4 +- ...nsferProcessHttpClientIntegrationTest.java | 4 +- .../DataPlaneSelectorApiV2ControllerTest.java | 4 +- .../DataPlaneSelectorApiV3ControllerTest.java | 4 +- .../http/DataPlaneHttpExtensionTest.java | 20 +- .../http/DataPlaneHttpIntegrationTests.java | 20 +- settings.gradle.kts | 1 - .../e2e/DataPlaneSelectorEndToEndTest.java | 4 +- ...taplaneSelectorControlApiEndToEndTest.java | 4 +- system-tests/e2e-transfer-test/README.md | 1 - .../backend-service/build.gradle.kts | 30 --- ...ckendServiceHttpProvisionerController.java | 95 -------- .../test/e2e/BackendServiceTestExtension.java | 50 ----- .../e2e/ConsumerBackendServiceController.java | 93 -------- .../edc/test/e2e/Oauth2TokenController.java | 78 ------- .../e2e/ProviderBackendApiController.java | 65 ------ ...rg.eclipse.edc.spi.system.ServiceExtension | 1 - .../control-plane/build.gradle.kts | 1 - .../e2e-transfer-test/runner/build.gradle.kts | 2 +- .../org/eclipse/edc/test/e2e/Runtimes.java | 4 - .../test/e2e/TransferEndToEndParticipant.java | 46 ++-- .../test/e2e/TransferEndToEndTestBase.java | 34 ++- .../test/e2e/TransferPullEndToEndTest.java | 208 +++++++++--------- .../test/e2e/TransferPushEndToEndTest.java | 137 +++++------- .../e2e/TransferStreamingEndToEndTest.java | 16 +- 31 files changed, 276 insertions(+), 688 deletions(-) delete mode 100644 system-tests/e2e-transfer-test/backend-service/build.gradle.kts delete mode 100644 system-tests/e2e-transfer-test/backend-service/src/main/java/org/eclipse/edc/test/e2e/BackendServiceHttpProvisionerController.java delete mode 100644 system-tests/e2e-transfer-test/backend-service/src/main/java/org/eclipse/edc/test/e2e/BackendServiceTestExtension.java delete mode 100644 system-tests/e2e-transfer-test/backend-service/src/main/java/org/eclipse/edc/test/e2e/ConsumerBackendServiceController.java delete mode 100644 system-tests/e2e-transfer-test/backend-service/src/main/java/org/eclipse/edc/test/e2e/Oauth2TokenController.java delete mode 100644 system-tests/e2e-transfer-test/backend-service/src/main/java/org/eclipse/edc/test/e2e/ProviderBackendApiController.java delete mode 100644 system-tests/e2e-transfer-test/backend-service/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension diff --git a/core/control-plane/control-plane-aggregate-services/src/test/java/org/eclipse/edc/connector/controlplane/services/asset/AssetEventDispatchTest.java b/core/control-plane/control-plane-aggregate-services/src/test/java/org/eclipse/edc/connector/controlplane/services/asset/AssetEventDispatchTest.java index ca98f4936d4..6d5b1704fcf 100644 --- a/core/control-plane/control-plane-aggregate-services/src/test/java/org/eclipse/edc/connector/controlplane/services/asset/AssetEventDispatchTest.java +++ b/core/control-plane/control-plane-aggregate-services/src/test/java/org/eclipse/edc/connector/controlplane/services/asset/AssetEventDispatchTest.java @@ -21,6 +21,7 @@ import org.eclipse.edc.connector.controlplane.services.spi.asset.AssetService; import org.eclipse.edc.connector.dataplane.selector.spi.client.DataPlaneClientFactory; import org.eclipse.edc.connector.dataplane.selector.spi.store.DataPlaneInstanceStore; +import org.eclipse.edc.junit.annotations.ComponentTest; import org.eclipse.edc.junit.extensions.EdcExtension; import org.eclipse.edc.spi.event.EventRouter; import org.eclipse.edc.spi.event.EventSubscriber; @@ -42,6 +43,7 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; +@ComponentTest @ExtendWith(EdcExtension.class) public class AssetEventDispatchTest { diff --git a/core/control-plane/control-plane-aggregate-services/src/test/java/org/eclipse/edc/connector/controlplane/services/contractdefinition/ContractDefinitionEventDispatchTest.java b/core/control-plane/control-plane-aggregate-services/src/test/java/org/eclipse/edc/connector/controlplane/services/contractdefinition/ContractDefinitionEventDispatchTest.java index ae61957385b..420cfda428c 100644 --- a/core/control-plane/control-plane-aggregate-services/src/test/java/org/eclipse/edc/connector/controlplane/services/contractdefinition/ContractDefinitionEventDispatchTest.java +++ b/core/control-plane/control-plane-aggregate-services/src/test/java/org/eclipse/edc/connector/controlplane/services/contractdefinition/ContractDefinitionEventDispatchTest.java @@ -21,6 +21,7 @@ import org.eclipse.edc.connector.controlplane.services.spi.contractdefinition.ContractDefinitionService; import org.eclipse.edc.connector.dataplane.selector.spi.client.DataPlaneClientFactory; import org.eclipse.edc.connector.dataplane.selector.spi.store.DataPlaneInstanceStore; +import org.eclipse.edc.junit.annotations.ComponentTest; import org.eclipse.edc.junit.extensions.EdcExtension; import org.eclipse.edc.spi.event.EventRouter; import org.eclipse.edc.spi.event.EventSubscriber; @@ -40,6 +41,7 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; +@ComponentTest @ExtendWith(EdcExtension.class) public class ContractDefinitionEventDispatchTest { diff --git a/core/control-plane/control-plane-aggregate-services/src/test/java/org/eclipse/edc/connector/controlplane/services/contractnegotiation/ContractNegotiationEventDispatchTest.java b/core/control-plane/control-plane-aggregate-services/src/test/java/org/eclipse/edc/connector/controlplane/services/contractnegotiation/ContractNegotiationEventDispatchTest.java index 66a5eb5a7df..613dd7d8a02 100644 --- a/core/control-plane/control-plane-aggregate-services/src/test/java/org/eclipse/edc/connector/controlplane/services/contractnegotiation/ContractNegotiationEventDispatchTest.java +++ b/core/control-plane/control-plane-aggregate-services/src/test/java/org/eclipse/edc/connector/controlplane/services/contractnegotiation/ContractNegotiationEventDispatchTest.java @@ -30,6 +30,7 @@ import org.eclipse.edc.connector.controlplane.services.spi.contractnegotiation.ContractNegotiationProtocolService; import org.eclipse.edc.connector.dataplane.selector.spi.client.DataPlaneClientFactory; import org.eclipse.edc.connector.dataplane.selector.spi.store.DataPlaneInstanceStore; +import org.eclipse.edc.junit.annotations.ComponentTest; import org.eclipse.edc.junit.extensions.EdcExtension; import org.eclipse.edc.policy.model.Policy; import org.eclipse.edc.spi.agent.ParticipantAgentService; @@ -66,6 +67,7 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +@ComponentTest @ExtendWith(EdcExtension.class) class ContractNegotiationEventDispatchTest { private static final String CONSUMER = "consumer"; diff --git a/core/control-plane/control-plane-aggregate-services/src/test/java/org/eclipse/edc/connector/controlplane/services/policydefinition/PolicyDefinitionEventDispatchTest.java b/core/control-plane/control-plane-aggregate-services/src/test/java/org/eclipse/edc/connector/controlplane/services/policydefinition/PolicyDefinitionEventDispatchTest.java index a8759aa4122..1754bdf157c 100644 --- a/core/control-plane/control-plane-aggregate-services/src/test/java/org/eclipse/edc/connector/controlplane/services/policydefinition/PolicyDefinitionEventDispatchTest.java +++ b/core/control-plane/control-plane-aggregate-services/src/test/java/org/eclipse/edc/connector/controlplane/services/policydefinition/PolicyDefinitionEventDispatchTest.java @@ -22,6 +22,7 @@ import org.eclipse.edc.connector.controlplane.services.spi.policydefinition.PolicyDefinitionService; import org.eclipse.edc.connector.dataplane.selector.spi.client.DataPlaneClientFactory; import org.eclipse.edc.connector.dataplane.selector.spi.store.DataPlaneInstanceStore; +import org.eclipse.edc.junit.annotations.ComponentTest; import org.eclipse.edc.junit.extensions.EdcExtension; import org.eclipse.edc.policy.model.Policy; import org.eclipse.edc.spi.event.EventRouter; @@ -41,6 +42,7 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; +@ComponentTest @ExtendWith(EdcExtension.class) public class PolicyDefinitionEventDispatchTest { diff --git a/core/control-plane/control-plane-aggregate-services/src/test/java/org/eclipse/edc/connector/controlplane/services/transferprocess/TransferProcessEventDispatchTest.java b/core/control-plane/control-plane-aggregate-services/src/test/java/org/eclipse/edc/connector/controlplane/services/transferprocess/TransferProcessEventDispatchTest.java index 1dc6e4e689e..cb2ad5db752 100644 --- a/core/control-plane/control-plane-aggregate-services/src/test/java/org/eclipse/edc/connector/controlplane/services/transferprocess/TransferProcessEventDispatchTest.java +++ b/core/control-plane/control-plane-aggregate-services/src/test/java/org/eclipse/edc/connector/controlplane/services/transferprocess/TransferProcessEventDispatchTest.java @@ -36,6 +36,7 @@ import org.eclipse.edc.connector.controlplane.transfer.spi.types.protocol.TransferStartMessage; import org.eclipse.edc.connector.core.event.EventExecutorServiceContainer; import org.eclipse.edc.connector.dataplane.selector.spi.client.DataPlaneClientFactory; +import org.eclipse.edc.junit.annotations.ComponentTest; import org.eclipse.edc.junit.extensions.RuntimeExtension; import org.eclipse.edc.junit.extensions.RuntimePerClassExtension; import org.eclipse.edc.policy.model.Policy; @@ -79,6 +80,7 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +@ComponentTest public class TransferProcessEventDispatchTest { public static final Duration TIMEOUT = Duration.ofSeconds(30); diff --git a/core/data-plane/data-plane-core/src/main/java/org/eclipse/edc/connector/dataplane/framework/DataPlaneDefaultIamServicesExtension.java b/core/data-plane/data-plane-core/src/main/java/org/eclipse/edc/connector/dataplane/framework/DataPlaneDefaultIamServicesExtension.java index 30bc6de3f20..c0d59fec35d 100644 --- a/core/data-plane/data-plane-core/src/main/java/org/eclipse/edc/connector/dataplane/framework/DataPlaneDefaultIamServicesExtension.java +++ b/core/data-plane/data-plane-core/src/main/java/org/eclipse/edc/connector/dataplane/framework/DataPlaneDefaultIamServicesExtension.java @@ -24,6 +24,7 @@ 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.monitor.Monitor; import org.eclipse.edc.spi.result.Result; import org.eclipse.edc.spi.system.ServiceExtension; import org.eclipse.edc.spi.system.ServiceExtensionContext; @@ -59,7 +60,6 @@ public String name() { return NAME; } - @Provider(isDefault = true) public DataPlaneAccessControlService defaultAccessControlService(ServiceExtensionContext context) { context.getMonitor().debug("DataPlane Access Control: default implementation is used, will always return Result.success()"); @@ -68,24 +68,24 @@ public DataPlaneAccessControlService defaultAccessControlService(ServiceExtensio @Provider(isDefault = true) public DataPlaneAccessTokenService defaultAccessTokenService(ServiceExtensionContext context) { + var tokenVerifierPublicKeyAlias = context.getConfig().getString(TOKEN_VERIFIER_PUBLIC_KEY_ALIAS); + var tokenSignerPrivateKeyAlias = context.getConfig().getString(TOKEN_SIGNER_PRIVATE_KEY_ALIAS); + var monitor = context.getMonitor().withPrefix("DataPlane IAM"); return new DefaultDataPlaneAccessTokenServiceImpl(new JwtGenerationService(), - accessTokenDataStore, context.getMonitor().withPrefix("DataPlane IAM"), - getPrivateKeySupplier(context), publicKeyIdSupplier(context), tokenValidationService, localPublicKeyService); + accessTokenDataStore, monitor, getPrivateKeySupplier(tokenSignerPrivateKeyAlias, monitor), + publicKeyIdSupplier(tokenVerifierPublicKeyAlias), tokenValidationService, localPublicKeyService); } - private Supplier publicKeyIdSupplier(ServiceExtensionContext context) { - return () -> context.getConfig().getString(TOKEN_VERIFIER_PUBLIC_KEY_ALIAS); + private Supplier publicKeyIdSupplier(String tokenVerifierPublicKeyAlias) { + return () -> tokenVerifierPublicKeyAlias; } @NotNull - private Supplier getPrivateKeySupplier(ServiceExtensionContext context) { - return () -> { - var alias = context.getConfig().getString(TOKEN_SIGNER_PRIVATE_KEY_ALIAS); - return privateKeyResolver.resolvePrivateKey(alias) - .orElse(f -> { - context.getMonitor().warning("Cannot resolve private key: " + f.getFailureDetail()); - return null; - }); - }; + private Supplier getPrivateKeySupplier(String tokenSignerPrivateKeyAlias, Monitor monitor) { + return () -> privateKeyResolver.resolvePrivateKey(tokenSignerPrivateKeyAlias) + .orElse(f -> { + monitor.warning("Cannot resolve private key: " + f.getFailureDetail()); + return null; + }); } } diff --git a/extensions/common/api/management-api-json-ld-context/src/test/java/org/eclipse/edc/connector/api/management/jsonld/serde/SerdeIntegrationTest.java b/extensions/common/api/management-api-json-ld-context/src/test/java/org/eclipse/edc/connector/api/management/jsonld/serde/SerdeIntegrationTest.java index 43a994c8d9b..a187248bde6 100644 --- a/extensions/common/api/management-api-json-ld-context/src/test/java/org/eclipse/edc/connector/api/management/jsonld/serde/SerdeIntegrationTest.java +++ b/extensions/common/api/management-api-json-ld-context/src/test/java/org/eclipse/edc/connector/api/management/jsonld/serde/SerdeIntegrationTest.java @@ -35,7 +35,7 @@ import org.eclipse.edc.connector.spi.service.SecretService; import org.eclipse.edc.edr.spi.store.EndpointDataReferenceStore; import org.eclipse.edc.jsonld.spi.JsonLd; -import org.eclipse.edc.junit.annotations.EndToEndTest; +import org.eclipse.edc.junit.annotations.ComponentTest; import org.eclipse.edc.junit.extensions.RuntimeExtension; import org.eclipse.edc.junit.extensions.RuntimePerClassExtension; import org.eclipse.edc.policy.model.AndConstraint; @@ -86,7 +86,7 @@ import static org.eclipse.edc.util.io.Ports.getFreePort; import static org.mockito.Mockito.mock; -@EndToEndTest +@ComponentTest public class SerdeIntegrationTest { @RegisterExtension diff --git a/extensions/control-plane/api/control-plane-api-client/src/test/java/org/eclipse/edc/connector/controlplane/api/client/transferprocess/TransferProcessHttpClientIntegrationTest.java b/extensions/control-plane/api/control-plane-api-client/src/test/java/org/eclipse/edc/connector/controlplane/api/client/transferprocess/TransferProcessHttpClientIntegrationTest.java index bfa48caf4a9..652df4e958f 100644 --- a/extensions/control-plane/api/control-plane-api-client/src/test/java/org/eclipse/edc/connector/controlplane/api/client/transferprocess/TransferProcessHttpClientIntegrationTest.java +++ b/extensions/control-plane/api/control-plane-api-client/src/test/java/org/eclipse/edc/connector/controlplane/api/client/transferprocess/TransferProcessHttpClientIntegrationTest.java @@ -81,7 +81,9 @@ void setUp(RuntimeExtension extension) { "web.http.control.port", String.valueOf(port), "web.http.control.path", "/control", "edc.core.retry.retries.max", "0", - "edc.dataplane.send.retry.limit", "0" + "edc.dataplane.send.retry.limit", "0", + "edc.transfer.proxy.token.verifier.publickey.alias", "alias", + "edc.transfer.proxy.token.signer.privatekey.alias", "alias" )); extension.registerSystemExtension(ServiceExtension.class, new TransferServiceMockExtension(service)); diff --git a/extensions/data-plane-selector/data-plane-selector-api/src/test/java/org/eclipse/edc/connector/dataplane/selector/api/v2/DataPlaneSelectorApiV2ControllerTest.java b/extensions/data-plane-selector/data-plane-selector-api/src/test/java/org/eclipse/edc/connector/dataplane/selector/api/v2/DataPlaneSelectorApiV2ControllerTest.java index 0d4c4e966fb..1bc8466c3aa 100644 --- a/extensions/data-plane-selector/data-plane-selector-api/src/test/java/org/eclipse/edc/connector/dataplane/selector/api/v2/DataPlaneSelectorApiV2ControllerTest.java +++ b/extensions/data-plane-selector/data-plane-selector-api/src/test/java/org/eclipse/edc/connector/dataplane/selector/api/v2/DataPlaneSelectorApiV2ControllerTest.java @@ -24,7 +24,7 @@ import org.eclipse.edc.connector.dataplane.selector.spi.store.DataPlaneInstanceStore; import org.eclipse.edc.connector.dataplane.selector.spi.strategy.SelectionStrategy; import org.eclipse.edc.connector.dataplane.selector.spi.strategy.SelectionStrategyRegistry; -import org.eclipse.edc.junit.annotations.ComponentTest; +import org.eclipse.edc.junit.annotations.ApiTest; import org.eclipse.edc.junit.extensions.EdcExtension; import org.eclipse.edc.spi.types.domain.DataAddress; import org.junit.jupiter.api.BeforeEach; @@ -49,7 +49,7 @@ import static org.eclipse.edc.util.io.Ports.getFreePort; import static org.hamcrest.Matchers.equalTo; -@ComponentTest +@ApiTest @ExtendWith(EdcExtension.class) public class DataPlaneSelectorApiV2ControllerTest { diff --git a/extensions/data-plane-selector/data-plane-selector-api/src/test/java/org/eclipse/edc/connector/dataplane/selector/api/v3/DataPlaneSelectorApiV3ControllerTest.java b/extensions/data-plane-selector/data-plane-selector-api/src/test/java/org/eclipse/edc/connector/dataplane/selector/api/v3/DataPlaneSelectorApiV3ControllerTest.java index f31f68038ae..f430ce80320 100644 --- a/extensions/data-plane-selector/data-plane-selector-api/src/test/java/org/eclipse/edc/connector/dataplane/selector/api/v3/DataPlaneSelectorApiV3ControllerTest.java +++ b/extensions/data-plane-selector/data-plane-selector-api/src/test/java/org/eclipse/edc/connector/dataplane/selector/api/v3/DataPlaneSelectorApiV3ControllerTest.java @@ -17,7 +17,7 @@ import io.restassured.specification.RequestSpecification; import jakarta.json.JsonArray; import org.eclipse.edc.connector.dataplane.selector.spi.store.DataPlaneInstanceStore; -import org.eclipse.edc.junit.annotations.ComponentTest; +import org.eclipse.edc.junit.annotations.ApiTest; import org.eclipse.edc.junit.extensions.EdcExtension; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -32,7 +32,7 @@ import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.ID; import static org.eclipse.edc.util.io.Ports.getFreePort; -@ComponentTest +@ApiTest @ExtendWith(EdcExtension.class) public class DataPlaneSelectorApiV3ControllerTest { diff --git a/extensions/data-plane/data-plane-http/src/test/java/org/eclipse/edc/connector/dataplane/http/DataPlaneHttpExtensionTest.java b/extensions/data-plane/data-plane-http/src/test/java/org/eclipse/edc/connector/dataplane/http/DataPlaneHttpExtensionTest.java index d603bdcfed2..25a39c7804f 100644 --- a/extensions/data-plane/data-plane-http/src/test/java/org/eclipse/edc/connector/dataplane/http/DataPlaneHttpExtensionTest.java +++ b/extensions/data-plane/data-plane-http/src/test/java/org/eclipse/edc/connector/dataplane/http/DataPlaneHttpExtensionTest.java @@ -19,15 +19,18 @@ import org.eclipse.edc.connector.dataplane.http.spi.HttpRequestParamsProvider; import org.eclipse.edc.connector.dataplane.spi.pipeline.PipelineService; import org.eclipse.edc.connector.dataplane.spi.pipeline.StreamResult; -import org.eclipse.edc.junit.extensions.EdcExtension; +import org.eclipse.edc.junit.annotations.ComponentTest; +import org.eclipse.edc.junit.extensions.RuntimeExtension; +import org.eclipse.edc.junit.extensions.RuntimePerClassExtension; import org.eclipse.edc.spi.types.domain.transfer.DataFlowStartMessage; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.api.extension.RegisterExtension; import org.mockserver.integration.ClientAndServer; import org.mockserver.model.HttpResponse; +import java.util.Map; import java.util.UUID; import static java.util.Collections.emptyMap; @@ -39,7 +42,7 @@ import static org.mockserver.model.HttpRequest.request; import static org.mockserver.stop.Stop.stopQuietly; -@ExtendWith(EdcExtension.class) +@ComponentTest public class DataPlaneHttpExtensionTest { private static ClientAndServer sourceServer; @@ -47,9 +50,16 @@ public class DataPlaneHttpExtensionTest { private static final int SOURCE_PORT = getFreePort(); private static final int DESTINATION_PORT = getFreePort(); + @RegisterExtension + private static final RuntimeExtension RUNTIME = new RuntimePerClassExtension() + .setConfiguration(Map.of( + "edc.transfer.proxy.token.verifier.publickey.alias", "alias", + "edc.transfer.proxy.token.signer.privatekey.alias", "alias" + )) + .registerServiceMock(TransferProcessApiClient.class, mock()); + @BeforeAll - public static void setUp(EdcExtension extension) { - extension.registerServiceMock(TransferProcessApiClient.class, mock()); + public static void setUp() { sourceServer = startClientAndServer(SOURCE_PORT); destinationServer = startClientAndServer(DESTINATION_PORT); } diff --git a/extensions/data-plane/data-plane-integration-tests/src/test/java/org/eclipse/edc/connector/dataplane/http/DataPlaneHttpIntegrationTests.java b/extensions/data-plane/data-plane-integration-tests/src/test/java/org/eclipse/edc/connector/dataplane/http/DataPlaneHttpIntegrationTests.java index 1153b937a00..230974c4052 100644 --- a/extensions/data-plane/data-plane-integration-tests/src/test/java/org/eclipse/edc/connector/dataplane/http/DataPlaneHttpIntegrationTests.java +++ b/extensions/data-plane/data-plane-integration-tests/src/test/java/org/eclipse/edc/connector/dataplane/http/DataPlaneHttpIntegrationTests.java @@ -23,7 +23,9 @@ import org.eclipse.edc.connector.dataplane.spi.DataFlowStates; import org.eclipse.edc.connector.dataplane.spi.schema.DataFlowRequestSchema; import org.eclipse.edc.junit.annotations.ComponentTest; -import org.eclipse.edc.junit.extensions.EdcRuntimeExtension; +import org.eclipse.edc.junit.extensions.EmbeddedRuntime; +import org.eclipse.edc.junit.extensions.RuntimeExtension; +import org.eclipse.edc.junit.extensions.RuntimePerClassExtension; import org.eclipse.edc.spi.types.TypeManager; import org.eclipse.edc.spi.types.domain.transfer.DataFlowStartMessage; import org.junit.jupiter.api.AfterAll; @@ -104,15 +106,17 @@ public class DataPlaneHttpIntegrationTests { private static ClientAndServer validationApiMockServer; private final Duration timeout = Duration.ofSeconds(30); - @RegisterExtension - static EdcRuntimeExtension dataPlane = new EdcRuntimeExtension( + private static final EmbeddedRuntime RUNTIME = new EmbeddedRuntime( "data-plane-server", Map.of( "web.http.public.port", valueOf(PUBLIC_API_PORT), "web.http.public.path", PUBLIC_PATH, "web.http.control.port", valueOf(CONTROL_API_PORT), "web.http.control.path", CONTROL_PATH, - "edc.dataplane.token.validation.endpoint", VALIDATION_API_HOST + "edc.dataplane.token.validation.endpoint", VALIDATION_API_HOST, + "edc.transfer.proxy.token.verifier.publickey.alias", "alias", + "edc.transfer.proxy.token.signer.privatekey.alias", "alias", + "edc.core.retry.retries.max", "0" ), ":extensions:common:metrics:micrometer-core", ":core:data-plane:data-plane-core", @@ -149,6 +153,10 @@ public void resetMockServer() { @Nested class Pull { + + @RegisterExtension + static RuntimeExtension dataPlane = new RuntimePerClassExtension(RUNTIME); + @Test void transfer_pull_withSourceQueryParamsAndPath_success(TypeManager typeManager) { // prepare data source and validation servers @@ -227,6 +235,10 @@ void shouldProxyMethodAndBody_whenSet(TypeManager typeManager) { @Nested class Push { + + @RegisterExtension + static RuntimeExtension dataPlane = new RuntimePerClassExtension(RUNTIME); + @Test void transfer_toHttpSink_success(TypeManager typeManager) { var body = UUID.randomUUID().toString(); diff --git a/settings.gradle.kts b/settings.gradle.kts index 270831b2d0d..9494afdfe26 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -267,7 +267,6 @@ include(":spi:policy-monitor:policy-monitor-spi") include(":tests:junit-base") // modules for system tests ------------------------------------------------------------------------ -include(":system-tests:e2e-transfer-test:backend-service") include(":system-tests:e2e-transfer-test:control-plane") include(":system-tests:e2e-transfer-test:data-plane") include(":system-tests:e2e-transfer-test:runner") diff --git a/system-tests/e2e-dataplane-tests/tests/src/test/java/org/eclipse/edc/test/e2e/DataPlaneSelectorEndToEndTest.java b/system-tests/e2e-dataplane-tests/tests/src/test/java/org/eclipse/edc/test/e2e/DataPlaneSelectorEndToEndTest.java index 6d86bfe36e5..86aafdcc2d5 100644 --- a/system-tests/e2e-dataplane-tests/tests/src/test/java/org/eclipse/edc/test/e2e/DataPlaneSelectorEndToEndTest.java +++ b/system-tests/e2e-dataplane-tests/tests/src/test/java/org/eclipse/edc/test/e2e/DataPlaneSelectorEndToEndTest.java @@ -71,7 +71,9 @@ public class DataPlaneSelectorEndToEndTest { "web.http.port", String.valueOf(getFreePort()), "web.http.path", "/api", "web.http.control.port", String.valueOf(dataPlaneControlPort), - "web.http.control.path", "/control" + "web.http.control.path", "/control", + "edc.transfer.proxy.token.verifier.publickey.alias", "alias", + "edc.transfer.proxy.token.signer.privatekey.alias", "alias" ), ":core:data-plane:data-plane-core", ":extensions:data-plane:data-plane-http", diff --git a/system-tests/e2e-dataplane-tests/tests/src/test/java/org/eclipse/edc/test/e2e/DataplaneSelectorControlApiEndToEndTest.java b/system-tests/e2e-dataplane-tests/tests/src/test/java/org/eclipse/edc/test/e2e/DataplaneSelectorControlApiEndToEndTest.java index 8cae2eac227..bd5de15b382 100644 --- a/system-tests/e2e-dataplane-tests/tests/src/test/java/org/eclipse/edc/test/e2e/DataplaneSelectorControlApiEndToEndTest.java +++ b/system-tests/e2e-dataplane-tests/tests/src/test/java/org/eclipse/edc/test/e2e/DataplaneSelectorControlApiEndToEndTest.java @@ -60,7 +60,9 @@ public class DataplaneSelectorControlApiEndToEndTest { "web.http.path", "/api", "web.http.control.port", String.valueOf(getFreePort()), "web.http.control.path", "/control", - "edc.dpf.selector.url", String.format("http://localhost:%d/control/v1/dataplanes", controlPlaneControlPort) + "edc.dpf.selector.url", String.format("http://localhost:%d/control/v1/dataplanes", controlPlaneControlPort), + "edc.transfer.proxy.token.verifier.publickey.alias", "alias", + "edc.transfer.proxy.token.signer.privatekey.alias", "alias" ), ":system-tests:e2e-dataplane-tests:runtimes:data-plane", ":extensions:data-plane:data-plane-self-registration", diff --git a/system-tests/e2e-transfer-test/README.md b/system-tests/e2e-transfer-test/README.md index 852db88351b..d746c2af136 100644 --- a/system-tests/e2e-transfer-test/README.md +++ b/system-tests/e2e-transfer-test/README.md @@ -4,7 +4,6 @@ This tests verifies some complete scenarios of contract negotiation and data tra ## Modules detail -* [backend-service](./backend-service): it represents an external application that interacts with the EDC. * [control-plane](./control-plane): it's responsible for handling the contract negotiation phase using in-memory persistence * [data-plane](./data-plane): it handles the data transfer phase acting as a proxy * [runner](./runner): it contains the test implementation diff --git a/system-tests/e2e-transfer-test/backend-service/build.gradle.kts b/system-tests/e2e-transfer-test/backend-service/build.gradle.kts deleted file mode 100644 index 54c4027dc24..00000000000 --- a/system-tests/e2e-transfer-test/backend-service/build.gradle.kts +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (c) 2022 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` -} - -dependencies { - implementation(project(":spi:common:http-spi")) - implementation(project(":extensions:common:http")) - implementation(project(":core:common:boot")) - - implementation(libs.nimbus.jwt) - implementation(libs.jakarta.rsApi) -} - -edcBuild { - publish.set(false) -} diff --git a/system-tests/e2e-transfer-test/backend-service/src/main/java/org/eclipse/edc/test/e2e/BackendServiceHttpProvisionerController.java b/system-tests/e2e-transfer-test/backend-service/src/main/java/org/eclipse/edc/test/e2e/BackendServiceHttpProvisionerController.java deleted file mode 100644 index 2db76a45086..00000000000 --- a/system-tests/e2e-transfer-test/backend-service/src/main/java/org/eclipse/edc/test/e2e/BackendServiceHttpProvisionerController.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (c) 2022 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.edc.test.e2e; - -import jakarta.ws.rs.Consumes; -import jakarta.ws.rs.POST; -import jakarta.ws.rs.Path; -import jakarta.ws.rs.core.MediaType; -import okhttp3.Request; -import okhttp3.RequestBody; -import org.eclipse.edc.http.spi.EdcHttpClient; -import org.eclipse.edc.spi.monitor.Monitor; -import org.eclipse.edc.spi.types.TypeManager; - -import java.util.Map; -import java.util.concurrent.Executors; - -import static java.lang.String.format; -import static java.util.concurrent.TimeUnit.SECONDS; -import static okhttp3.MediaType.get; -import static org.eclipse.edc.spi.constants.CoreConstants.EDC_NAMESPACE; - -@Path("/provision") -public class BackendServiceHttpProvisionerController { - - private final Monitor monitor; - private final EdcHttpClient httpClient; - private final TypeManager typeManager; - private final int exposedHttpPort; - - public BackendServiceHttpProvisionerController(Monitor monitor, EdcHttpClient httpClient, TypeManager typeManager, int exposedHttpPort) { - this.monitor = monitor; - this.httpClient = httpClient; - this.typeManager = typeManager; - this.exposedHttpPort = exposedHttpPort; - } - - @POST - @Consumes(MediaType.APPLICATION_JSON) - public void provision(Map request) { - var baseUrl = request.get("callbackAddress"); - var transferProcessId = request.get("transferProcessId"); - var completeUrl = format("%s/%s/provision", baseUrl, transferProcessId); - monitor.info(format("Provision request received. Will now call the callback address %s to fake the provisioning", completeUrl)); - var requestBody = Map.of( - "edctype", "dataspaceconnector:provisioner-callback-request", - "resourceDefinitionId", request.get("resourceDefinitionId"), - "assetId", request.get("assetId"), - "resourceName", "aName", - // this is the data address of the content served by this backend service - "contentDataAddress", Map.of( - "properties", Map.of( - EDC_NAMESPACE + "type", "HttpData", - EDC_NAMESPACE + "baseUrl", format("http://localhost:%d/api/provider/data", exposedHttpPort) - ) - ), - "apiKeyJwt", "unused", - "hasToken", false - ); - - Executors.newScheduledThreadPool(1).schedule(() -> callbackRequest(completeUrl, requestBody), 5, SECONDS); - } - - private void callbackRequest(String completeUrl, Map requestBody) { - var callbackRequest = new Request.Builder() - .url(completeUrl) - .post(RequestBody.create(typeManager.writeValueAsString(requestBody), get("application/json"))) - .build(); - - try (var response = httpClient.execute(callbackRequest)) { - var body = response.body(); - var string = body.string(); - if (response.isSuccessful()) { - monitor.info("Provisioning callback responded correctly: " + string); - - } else { - monitor.warning(format("Provisioning callback responded with error: %s %s", response.code(), string)); - } - } catch (Exception e) { - monitor.severe(format("Error in calling the provisioning callback at %s", completeUrl), e); - } - } -} diff --git a/system-tests/e2e-transfer-test/backend-service/src/main/java/org/eclipse/edc/test/e2e/BackendServiceTestExtension.java b/system-tests/e2e-transfer-test/backend-service/src/main/java/org/eclipse/edc/test/e2e/BackendServiceTestExtension.java deleted file mode 100644 index 315b1c302ae..00000000000 --- a/system-tests/e2e-transfer-test/backend-service/src/main/java/org/eclipse/edc/test/e2e/BackendServiceTestExtension.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2022 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.edc.test.e2e; - -import org.eclipse.edc.http.spi.EdcHttpClient; -import org.eclipse.edc.runtime.metamodel.annotation.Inject; -import org.eclipse.edc.spi.system.ServiceExtension; -import org.eclipse.edc.spi.system.ServiceExtensionContext; -import org.eclipse.edc.spi.types.TypeManager; -import org.eclipse.edc.web.jersey.mapper.EdcApiExceptionMapper; -import org.eclipse.edc.web.spi.WebService; - -public class BackendServiceTestExtension implements ServiceExtension { - - @Inject - private WebService webService; - - @Inject - private EdcHttpClient httpClient; - - @Inject - private TypeManager typeManager; - - @Override - public String name() { - return "[TEST] Backend service"; - } - - @Override - public void initialize(ServiceExtensionContext context) { - var exposedHttpPort = context.getConfig().getInteger("web.http.port"); - webService.registerResource(new ProviderBackendApiController()); - webService.registerResource(new ConsumerBackendServiceController(context.getMonitor())); - webService.registerResource(new BackendServiceHttpProvisionerController(context.getMonitor(), httpClient, typeManager, exposedHttpPort)); - webService.registerResource(new Oauth2TokenController(context.getMonitor())); - webService.registerResource(new EdcApiExceptionMapper()); - } -} diff --git a/system-tests/e2e-transfer-test/backend-service/src/main/java/org/eclipse/edc/test/e2e/ConsumerBackendServiceController.java b/system-tests/e2e-transfer-test/backend-service/src/main/java/org/eclipse/edc/test/e2e/ConsumerBackendServiceController.java deleted file mode 100644 index 08e1aa99c11..00000000000 --- a/system-tests/e2e-transfer-test/backend-service/src/main/java/org/eclipse/edc/test/e2e/ConsumerBackendServiceController.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (c) 2022 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.edc.test.e2e; - -import jakarta.ws.rs.Consumes; -import jakarta.ws.rs.GET; -import jakarta.ws.rs.POST; -import jakarta.ws.rs.Path; -import jakarta.ws.rs.PathParam; -import jakarta.ws.rs.Produces; -import jakarta.ws.rs.core.MediaType; -import org.eclipse.edc.spi.monitor.Monitor; -import org.eclipse.edc.spi.types.domain.edr.EndpointDataReference; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.NoSuchElementException; -import java.util.Optional; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.atomic.AtomicReference; - -@Path("/consumer") -public class ConsumerBackendServiceController { - - private final Monitor monitor; - private final AtomicReference data = new AtomicReference<>(); - private final Map> dataReference = new ConcurrentHashMap<>(); - - public ConsumerBackendServiceController(Monitor monitor) { - this.monitor = monitor; - } - - @Path("/dataReference") - @POST - @Consumes({ MediaType.APPLICATION_JSON }) - public void pushDataReference(EndpointDataReference edr) { - monitor.debug("Received new endpoint data reference with url " + edr.getEndpoint()); - dataReference.compute(edr.getId(), (k, edrs) -> { - if (edrs == null) { - var list = new ArrayList(); - list.add(edr); - return list; - } else { - edrs.add(edr); - return edrs; - } - }); - } - - @Path("/dataReference/{id}") - @GET - @Produces({ MediaType.APPLICATION_JSON }) - public EndpointDataReference getDataReference(@PathParam("id") String id) { - return Optional.ofNullable(dataReference.get(id)) - .flatMap(edrs -> edrs.stream().findFirst()) - .orElseThrow(NoSuchElementException::new); - } - - @Path("/dataReference/{id}/all") - @GET - @Produces({ MediaType.APPLICATION_JSON }) - public List getAllDataReferences(@PathParam("id") String id) { - return Optional.ofNullable(dataReference.get(id)) - .orElseThrow(NoSuchElementException::new); - } - - @Path("/store") - @POST - public void pushData(String body) { - data.set(body); - } - - @Path("/data") - @GET - @Produces(MediaType.APPLICATION_JSON) - public String getData() { - return data.get(); - } - -} diff --git a/system-tests/e2e-transfer-test/backend-service/src/main/java/org/eclipse/edc/test/e2e/Oauth2TokenController.java b/system-tests/e2e-transfer-test/backend-service/src/main/java/org/eclipse/edc/test/e2e/Oauth2TokenController.java deleted file mode 100644 index 18053bd5f91..00000000000 --- a/system-tests/e2e-transfer-test/backend-service/src/main/java/org/eclipse/edc/test/e2e/Oauth2TokenController.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (c) 2022 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.edc.test.e2e; - -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.gen.RSAKeyGenerator; -import com.nimbusds.jwt.JWTClaimsSet; -import com.nimbusds.jwt.SignedJWT; -import jakarta.ws.rs.FormParam; -import jakarta.ws.rs.POST; -import jakarta.ws.rs.Path; -import org.eclipse.edc.spi.monitor.Monitor; -import org.eclipse.edc.web.spi.exception.InvalidRequestException; - -import java.util.Map; -import java.util.UUID; - -import static java.lang.String.format; - -@Path("/oauth2") -public class Oauth2TokenController { - - private static final String EXPECTED_CLIENT_ID = "clientId"; - private static final String EXPECTED_CLIENT_SECRET = "supersecret"; - private final Monitor monitor; - - public Oauth2TokenController(Monitor monitor) { - this.monitor = monitor; - } - - @POST - @Path("/token") - public Map getToken(@FormParam("client_id") String clientId, @FormParam("client_secret") String clientSecret) { - monitor.info("Oauth2 token requested"); - if (!EXPECTED_CLIENT_ID.equals(clientId) || !EXPECTED_CLIENT_SECRET.equals(clientSecret)) { - var message = format("Cannot validate token request, parameters are not valid: client_id %s - client_secret %s", clientId, clientSecret); - monitor.severe(message); - throw new InvalidRequestException(message); - } - - return Map.of("access_token", createToken()); - } - - private String createToken() { - try { - var key = new RSAKeyGenerator(2048) - .keyUse(KeyUse.SIGNATURE) - .keyID(UUID.randomUUID().toString()) - .generate(); - - var claims = new JWTClaimsSet.Builder().build(); - var header = new JWSHeader.Builder(JWSAlgorithm.RS256).keyID(UUID.randomUUID().toString()).build(); - - var jwt = new SignedJWT(header, claims); - jwt.sign(new RSASSASigner(key.toPrivateKey())); - return jwt.serialize(); - } catch (JOSEException e) { - throw new RuntimeException(e); - } - } - -} diff --git a/system-tests/e2e-transfer-test/backend-service/src/main/java/org/eclipse/edc/test/e2e/ProviderBackendApiController.java b/system-tests/e2e-transfer-test/backend-service/src/main/java/org/eclipse/edc/test/e2e/ProviderBackendApiController.java deleted file mode 100644 index d99535d21b4..00000000000 --- a/system-tests/e2e-transfer-test/backend-service/src/main/java/org/eclipse/edc/test/e2e/ProviderBackendApiController.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2022 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.edc.test.e2e; - -import com.nimbusds.jwt.SignedJWT; -import jakarta.ws.rs.DefaultValue; -import jakarta.ws.rs.GET; -import jakarta.ws.rs.HeaderParam; -import jakarta.ws.rs.Path; -import jakarta.ws.rs.Produces; -import jakarta.ws.rs.QueryParam; -import jakarta.ws.rs.core.MediaType; -import org.eclipse.edc.web.spi.exception.NotAuthorizedException; - -import java.text.ParseException; -import java.util.Map; - -@Path("/provider") -public class ProviderBackendApiController { - - @Path("/data") - @GET - @Produces(MediaType.APPLICATION_JSON) - public Map getData(@DefaultValue("some information") @QueryParam("message") String message) { - return Map.of("message", message); - } - - @Path("/oauth2data") - @GET - @Produces(MediaType.APPLICATION_JSON) - public Map getOauth2Data(@DefaultValue("some information") @QueryParam("message") String message, @HeaderParam("Authorization") String authorization) { - if (authorization == null || !isAuthorized(authorization)) { - throw new NotAuthorizedException("The authorization token is not valid: " + authorization); - } else { - return Map.of("message", message); - } - } - - private boolean isAuthorized(String authorization) { - if (!authorization.startsWith("Bearer ")) { - return false; - } - - var token = authorization.replace("Bearer ", ""); - - try { - SignedJWT.parse(token); - return true; - } catch (ParseException e) { - return false; - } - } -} diff --git a/system-tests/e2e-transfer-test/backend-service/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension b/system-tests/e2e-transfer-test/backend-service/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension deleted file mode 100644 index 336190bc8a1..00000000000 --- a/system-tests/e2e-transfer-test/backend-service/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension +++ /dev/null @@ -1 +0,0 @@ -org.eclipse.edc.test.e2e.BackendServiceTestExtension diff --git a/system-tests/e2e-transfer-test/control-plane/build.gradle.kts b/system-tests/e2e-transfer-test/control-plane/build.gradle.kts index d31d264eeb5..f37f54d0e11 100644 --- a/system-tests/e2e-transfer-test/control-plane/build.gradle.kts +++ b/system-tests/e2e-transfer-test/control-plane/build.gradle.kts @@ -39,7 +39,6 @@ dependencies { implementation(project(":extensions:data-plane-selector:data-plane-selector-control-api")) implementation(project(":extensions:control-plane:provision:provision-http")) - implementation(project(":extensions:control-plane:transfer:transfer-pull-http-receiver")) implementation(project(":extensions:control-plane:transfer:transfer-pull-http-dynamic-receiver")) implementation(project(":core:policy-monitor:policy-monitor-core")) diff --git a/system-tests/e2e-transfer-test/runner/build.gradle.kts b/system-tests/e2e-transfer-test/runner/build.gradle.kts index c56df048952..8c4e175f05a 100644 --- a/system-tests/e2e-transfer-test/runner/build.gradle.kts +++ b/system-tests/e2e-transfer-test/runner/build.gradle.kts @@ -24,6 +24,7 @@ dependencies { testImplementation(project(":spi:common:web-spi")) testImplementation(project(":core:common:connector-core")) testImplementation(project(":core:common:junit")) + testImplementation(testFixtures(project(":core:common:lib:http-lib"))) testImplementation(testFixtures(project(":extensions:common:sql:sql-core"))) testImplementation(testFixtures(project(":extensions:control-plane:api:management-api:management-api-test-fixtures"))) testImplementation(project(":extensions:common:json-ld")) @@ -39,7 +40,6 @@ dependencies { testImplementation(libs.testcontainers.junit) testImplementation(libs.testcontainers.kafka) - testCompileOnly(project(":system-tests:e2e-transfer-test:backend-service")) testCompileOnly(project(":system-tests:e2e-transfer-test:control-plane")) testCompileOnly(project(":system-tests:e2e-transfer-test:data-plane")) } diff --git a/system-tests/e2e-transfer-test/runner/src/test/java/org/eclipse/edc/test/e2e/Runtimes.java b/system-tests/e2e-transfer-test/runner/src/test/java/org/eclipse/edc/test/e2e/Runtimes.java index d01b8c8de0e..f7071f480a2 100644 --- a/system-tests/e2e-transfer-test/runner/src/test/java/org/eclipse/edc/test/e2e/Runtimes.java +++ b/system-tests/e2e-transfer-test/runner/src/test/java/org/eclipse/edc/test/e2e/Runtimes.java @@ -27,10 +27,6 @@ */ public enum Runtimes { - BACKEND_SERVICE( - ":system-tests:e2e-transfer-test:backend-service" - ), - IN_MEMORY_CONTROL_PLANE( ":system-tests:e2e-transfer-test:control-plane", ":extensions:data-plane:data-plane-signaling:data-plane-signaling-client" diff --git a/system-tests/e2e-transfer-test/runner/src/test/java/org/eclipse/edc/test/e2e/TransferEndToEndParticipant.java b/system-tests/e2e-transfer-test/runner/src/test/java/org/eclipse/edc/test/e2e/TransferEndToEndParticipant.java index 15f9f926837..f8e8717362e 100644 --- a/system-tests/e2e-transfer-test/runner/src/test/java/org/eclipse/edc/test/e2e/TransferEndToEndParticipant.java +++ b/system-tests/e2e-transfer-test/runner/src/test/java/org/eclipse/edc/test/e2e/TransferEndToEndParticipant.java @@ -16,10 +16,9 @@ import io.restassured.common.mapper.TypeRef; import jakarta.json.Json; -import jakarta.json.JsonObject; +import org.assertj.core.api.ThrowingConsumer; import org.eclipse.edc.connector.controlplane.test.system.utils.Participant; import org.eclipse.edc.spi.types.domain.DataAddress; -import org.hamcrest.Matcher; import org.jetbrains.annotations.NotNull; import java.net.URI; @@ -33,6 +32,7 @@ import static jakarta.json.Json.createArrayBuilder; import static jakarta.json.Json.createObjectBuilder; import static java.io.File.separator; +import static org.assertj.core.api.Assertions.assertThat; import static org.eclipse.edc.boot.BootServicesExtension.PARTICIPANT_ID; import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.CONTEXT; import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.ID; @@ -48,25 +48,14 @@ public class TransferEndToEndParticipant extends Participant { private final URI dataPlaneDefault = URI.create("http://localhost:" + getFreePort()); private final URI dataPlaneControl = URI.create("http://localhost:" + getFreePort() + "/control"); private final URI dataPlanePublic = URI.create("http://localhost:" + getFreePort() + "/public"); - private final URI backendService = URI.create("http://localhost:" + getFreePort()); + private final int httpProvisionerPort = getFreePort(); protected TransferEndToEndParticipant() { super(); } - /** - * Get private properties to configure a dynamic http receiver for EDR. - * - * @return the receiver properties. - */ - public JsonObject dynamicReceiverPrivateProperties() { - return Json.createObjectBuilder() - .add("receiverHttpEndpoint", backendService + "/api/consumer/dataReference") - .build(); - } - - public URI backendService() { - return backendService; + public int getHttpProvisionerPort() { + return httpProvisionerPort; } /** @@ -125,9 +114,6 @@ public Map controlPlaneConfiguration() { put("edc.vault", resourceAbsolutePath(getName() + "-vault.properties")); put("edc.keystore", resourceAbsolutePath("certs/cert.pfx")); put("edc.keystore.password", "123456"); - put("edc.receiver.http.endpoint", backendService + "/api/consumer/dataReference"); - put("edc.transfer.proxy.token.signer.privatekey.alias", "1"); - put("edc.transfer.proxy.token.verifier.publickey.alias", "public-key"); put("edc.transfer.proxy.endpoint", dataPlanePublic.toString()); put("edc.transfer.send.retry.limit", "1"); put("edc.transfer.send.retry.base-delay.ms", "100"); @@ -137,7 +123,7 @@ public Map controlPlaneConfiguration() { put("edc.negotiation.provider.send.retry.base-delay.ms", "100"); put("provisioner.http.entries.default.provisioner.type", "provider"); - put("provisioner.http.entries.default.endpoint", backendService + "/api/provision"); + put("provisioner.http.entries.default.endpoint", "http://localhost:%d/provision".formatted(httpProvisionerPort)); put("provisioner.http.entries.default.data.address.type", "HttpProvision"); } }; @@ -163,7 +149,7 @@ public Map dataPlaneConfiguration() { put("edc.keystore.password", "123456"); put("edc.dataplane.api.public.baseurl", dataPlanePublic + "/v2/"); put("edc.dataplane.token.validation.endpoint", controlPlaneControl + "/token"); - put("edc.transfer.proxy.token.signer.privatekey.alias", "1"); + put("edc.transfer.proxy.token.signer.privatekey.alias", "private-key"); put("edc.transfer.proxy.token.verifier.publickey.alias", "public-key"); put("edc.dataplane.http.sink.partition.size", "1"); put("edc.dpf.selector.url", controlPlaneControl + "/v1/dataplanes"); @@ -183,14 +169,6 @@ public Map dataPlanePostgresConfiguration() { return baseConfiguration; } - public Map backendServiceConfiguration() { - return new HashMap<>() { - { - put("web.http.port", String.valueOf(backendService.getPort())); - } - }; - } - /** * Get the EDR from the EDR cache by transfer process id. * @@ -221,10 +199,10 @@ public DataAddress getEdr(String transferProcessId) { * * @param edr endpoint data reference * @param queryParams query parameters - * @param bodyMatcher matcher for response body + * @param bodyAssertion assertion to be verified on the body */ - public void pullData(DataAddress edr, Map queryParams, Matcher bodyMatcher) { - given() + public void pullData(DataAddress edr, Map queryParams, ThrowingConsumer bodyAssertion) { + var data = given() .baseUri(edr.getStringProperty("endpoint")) .header("Authorization", edr.getStringProperty("authorization")) .queryParams(queryParams) @@ -233,7 +211,9 @@ public void pullData(DataAddress edr, Map queryParams, Matcher dataAddressProperties) { PROVIDER.createAsset(assetId, Map.of("description", "description"), dataAddressProperties); - var accessPolicyId = PROVIDER.createPolicyDefinition(noConstraintPolicy()); var contractPolicyId = PROVIDER.createPolicyDefinition(contractPolicy); - PROVIDER.createContractDefinition(assetId, UUID.randomUUID().toString(), accessPolicyId, contractPolicyId); + PROVIDER.createContractDefinition(assetId, UUID.randomUUID().toString(), noConstraintPolicyId, contractPolicyId); + } + + protected void createResourcesOnProvider(String assetId, Map dataAddressProperties) { + PROVIDER.createAsset(assetId, Map.of("description", "description"), dataAddressProperties); + PROVIDER.createContractDefinition(assetId, UUID.randomUUID().toString(), noConstraintPolicyId, noConstraintPolicyId); } protected void awaitTransferToBeInState(String transferProcessId, TransferProcessStates state) { diff --git a/system-tests/e2e-transfer-test/runner/src/test/java/org/eclipse/edc/test/e2e/TransferPullEndToEndTest.java b/system-tests/e2e-transfer-test/runner/src/test/java/org/eclipse/edc/test/e2e/TransferPullEndToEndTest.java index c3485ab0c3f..dcfce9270bf 100644 --- a/system-tests/e2e-transfer-test/runner/src/test/java/org/eclipse/edc/test/e2e/TransferPullEndToEndTest.java +++ b/system-tests/e2e-transfer-test/runner/src/test/java/org/eclipse/edc/test/e2e/TransferPullEndToEndTest.java @@ -22,21 +22,26 @@ import jakarta.json.Json; import jakarta.json.JsonArrayBuilder; import jakarta.json.JsonObject; +import okhttp3.Request; +import okhttp3.RequestBody; import org.eclipse.edc.connector.controlplane.test.system.utils.PolicyFixtures; import org.eclipse.edc.connector.controlplane.transfer.spi.event.TransferProcessStarted; import org.eclipse.edc.junit.annotations.EndToEndTest; import org.eclipse.edc.junit.annotations.PostgresqlIntegrationTest; import org.eclipse.edc.junit.extensions.RuntimeExtension; import org.eclipse.edc.junit.extensions.RuntimePerClassExtension; +import org.eclipse.edc.spi.EdcException; import org.eclipse.edc.spi.event.EventEnvelope; +import org.eclipse.edc.spi.security.Vault; import org.jetbrains.annotations.NotNull; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.BeforeAllCallback; import org.junit.jupiter.api.extension.RegisterExtension; import org.mockserver.integration.ClientAndServer; +import org.mockserver.mock.action.ExpectationResponseCallback; import org.mockserver.model.HttpRequest; import org.mockserver.model.HttpResponse; import org.mockserver.model.HttpStatusCode; @@ -48,21 +53,23 @@ import java.util.Set; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.Executors; import static java.time.Duration.ofDays; +import static java.util.concurrent.TimeUnit.SECONDS; +import static okhttp3.MediaType.get; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.awaitility.Awaitility.await; import static org.eclipse.edc.connector.controlplane.test.system.utils.PolicyFixtures.inForceDatePolicy; -import static org.eclipse.edc.connector.controlplane.test.system.utils.PolicyFixtures.noConstraintPolicy; import static org.eclipse.edc.connector.controlplane.transfer.spi.types.TransferProcessStates.STARTED; import static org.eclipse.edc.connector.controlplane.transfer.spi.types.TransferProcessStates.SUSPENDED; import static org.eclipse.edc.connector.controlplane.transfer.spi.types.TransferProcessStates.TERMINATED; +import static org.eclipse.edc.http.client.testfixtures.HttpTestUtils.testHttpClient; import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.TYPE; import static org.eclipse.edc.spi.constants.CoreConstants.EDC_NAMESPACE; import static org.eclipse.edc.sql.testfixtures.PostgresqlEndToEndInstance.createDatabase; import static org.eclipse.edc.util.io.Ports.getFreePort; -import static org.hamcrest.CoreMatchers.equalTo; import static org.mockserver.integration.ClientAndServer.startClientAndServer; import static org.mockserver.model.HttpRequest.request; import static org.mockserver.model.HttpResponse.response; @@ -72,33 +79,33 @@ class TransferPullEndToEndTest { abstract static class Tests extends TransferEndToEndTestBase { + private static final ObjectMapper MAPPER = new ObjectMapper(); - private static final String CALLBACK_PATH = "hooks"; - private static final int CALLBACK_PORT = getFreePort(); - private static ClientAndServer callbacksEndpoint; + private static ClientAndServer providerDataSource; - @BeforeEach - void beforeEach() { - callbacksEndpoint = startClientAndServer(CALLBACK_PORT); + @BeforeAll + static void beforeAll() { + providerDataSource = startClientAndServer(getFreePort()); } - @AfterEach - void tearDown() { - stopQuietly(callbacksEndpoint); + @AfterAll + static void afterAll() { + stopQuietly(providerDataSource); } @Test void httpPull_dataTransfer_withCallbacks() { - seedVaults(); + providerDataSource.when(HttpRequest.request()).respond(HttpResponse.response().withBody("data")); + var callbacksEndpoint = startClientAndServer(getFreePort()); var assetId = UUID.randomUUID().toString(); - createResourcesOnProvider(assetId, noConstraintPolicy(), httpDataAddressProperties()); - var dynamicReceiverProps = CONSUMER.dynamicReceiverPrivateProperties(); + createResourcesOnProvider(assetId, httpSourceDataAddress()); + var callbackUrl = String.format("http://localhost:%d/hooks", callbacksEndpoint.getLocalPort()); var callbacks = Json.createArrayBuilder() - .add(createCallback(callbackUrl(), true, Set.of("transfer.process.started"))) + .add(createCallback(callbackUrl, true, Set.of("transfer.process.started"))) .build(); - var request = request().withPath("/" + CALLBACK_PATH) + var request = request().withPath("/hooks") .withMethod(HttpMethod.POST.name()); var events = new ConcurrentHashMap(); @@ -106,7 +113,6 @@ void httpPull_dataTransfer_withCallbacks() { callbacksEndpoint.when(request).respond(req -> this.cacheEdr(req, events)); var transferProcessId = CONSUMER.requestAssetFrom(assetId, PROVIDER) - .withPrivateProperties(dynamicReceiverProps) .withTransferType("HttpData-PULL") .withCallbacks(callbacks) .execute(); @@ -117,47 +123,47 @@ void httpPull_dataTransfer_withCallbacks() { var event = events.get(transferProcessId); var msg = UUID.randomUUID().toString(); - await().atMost(timeout).untilAsserted(() -> CONSUMER.pullData(event.getDataAddress(), Map.of("message", msg), equalTo(msg))); + await().atMost(timeout).untilAsserted(() -> CONSUMER.pullData(event.getDataAddress(), Map.of("message", msg), body -> assertThat(body).isEqualTo("data"))); + + providerDataSource.verify(HttpRequest.request("/source").withMethod("GET")); + stopQuietly(callbacksEndpoint); } @Test void httpPull_dataTransfer_withEdrCache() { - seedVaults(); + providerDataSource.when(HttpRequest.request()).respond(HttpResponse.response().withBody("data")); var assetId = UUID.randomUUID().toString(); - createResourcesOnProvider(assetId, PolicyFixtures.contractExpiresIn("10s"), httpDataAddressProperties()); - var dynamicReceiverProps = CONSUMER.dynamicReceiverPrivateProperties(); + var sourceDataAddress = httpSourceDataAddress(); + createResourcesOnProvider(assetId, PolicyFixtures.contractExpiresIn("10s"), sourceDataAddress); var transferProcessId = CONSUMER.requestAssetFrom(assetId, PROVIDER) - .withPrivateProperties(dynamicReceiverProps) .withTransferType("HttpData-PULL") .execute(); - await().atMost(timeout).untilAsserted(() -> { - var state = CONSUMER.getTransferProcessState(transferProcessId); - assertThat(state).isEqualTo(STARTED.name()); - }); + awaitTransferToBeInState(transferProcessId, STARTED); var edr = await().atMost(timeout).until(() -> CONSUMER.getEdr(transferProcessId), Objects::nonNull); // Do the transfer var msg = UUID.randomUUID().toString(); - await().atMost(timeout).untilAsserted(() -> CONSUMER.pullData(edr, Map.of("message", msg), equalTo(msg))); + await().atMost(timeout).untilAsserted(() -> CONSUMER.pullData(edr, Map.of("message", msg), body -> assertThat(body).isEqualTo("data"))); // checks that the EDR is gone once the contract expires await().atMost(timeout).untilAsserted(() -> assertThatThrownBy(() -> CONSUMER.getEdr(transferProcessId))); // checks that transfer fails - await().atMost(timeout).untilAsserted(() -> assertThatThrownBy(() -> CONSUMER.pullData(edr, Map.of("message", msg), equalTo(msg)))); + await().atMost(timeout).untilAsserted(() -> assertThatThrownBy(() -> CONSUMER.pullData(edr, Map.of("message", msg), body -> assertThat(body).isEqualTo("data")))); + + providerDataSource.verify(HttpRequest.request("/source").withMethod("GET")); } @Test void suspendAndResume_httpPull_dataTransfer_withEdrCache() { - seedVaults(); + providerDataSource.when(HttpRequest.request()).respond(HttpResponse.response().withBody("data")); var assetId = UUID.randomUUID().toString(); - createResourcesOnProvider(assetId, noConstraintPolicy(), httpDataAddressProperties()); + createResourcesOnProvider(assetId, httpSourceDataAddress()); var transferProcessId = CONSUMER.requestAssetFrom(assetId, PROVIDER) - .withPrivateProperties(CONSUMER.dynamicReceiverPrivateProperties()) .withTransferType("HttpData-PULL") .execute(); @@ -166,7 +172,7 @@ void suspendAndResume_httpPull_dataTransfer_withEdrCache() { var edr = await().atMost(timeout).until(() -> CONSUMER.getEdr(transferProcessId), Objects::nonNull); var msg = UUID.randomUUID().toString(); - await().atMost(timeout).untilAsserted(() -> CONSUMER.pullData(edr, Map.of("message", msg), equalTo(msg))); + await().atMost(timeout).untilAsserted(() -> CONSUMER.pullData(edr, Map.of("message", msg), body -> assertThat(body).isEqualTo("data"))); CONSUMER.suspendTransfer(transferProcessId, "supension"); @@ -175,7 +181,7 @@ void suspendAndResume_httpPull_dataTransfer_withEdrCache() { // checks that the EDR is gone once the transfer has been suspended await().atMost(timeout).untilAsserted(() -> assertThatThrownBy(() -> CONSUMER.getEdr(transferProcessId))); // checks that transfer fails - await().atMost(timeout).untilAsserted(() -> assertThatThrownBy(() -> CONSUMER.pullData(edr, Map.of("message", msg), equalTo(msg)))); + await().atMost(timeout).untilAsserted(() -> assertThatThrownBy(() -> CONSUMER.pullData(edr, Map.of("message", msg), body -> assertThat(body).isEqualTo("data")))); CONSUMER.resumeTransfer(transferProcessId); @@ -183,73 +189,69 @@ void suspendAndResume_httpPull_dataTransfer_withEdrCache() { awaitTransferToBeInState(transferProcessId, STARTED); var secondEdr = await().atMost(timeout).until(() -> CONSUMER.getEdr(transferProcessId), Objects::nonNull); var secondMessage = UUID.randomUUID().toString(); - await().atMost(timeout).untilAsserted(() -> CONSUMER.pullData(secondEdr, Map.of("message", secondMessage), equalTo(secondMessage))); + await().atMost(timeout).untilAsserted(() -> CONSUMER.pullData(secondEdr, Map.of("message", secondMessage), body -> assertThat(body).isEqualTo("data"))); + providerDataSource.verify(HttpRequest.request("/source").withMethod("GET")); } @Test void pullFromHttp_httpProvision() { - seedVaults(); + providerDataSource.when(HttpRequest.request()).respond(HttpResponse.response().withBody("data")); + var provisionServer = startClientAndServer(PROVIDER.getHttpProvisionerPort()); + provisionServer.when(HttpRequest.request()).respond(new HttpProvisionerCallback()); + var assetId = UUID.randomUUID().toString(); - createResourcesOnProvider(assetId, noConstraintPolicy(), Map.of( + createResourcesOnProvider(assetId, Map.of( "name", "transfer-test", - "baseUrl", PROVIDER.backendService() + "/api/provider/data", + "baseUrl", "http://localhost:" + provisionServer.getPort() + "/provision", "type", "HttpProvision", "proxyQueryParams", "true" )); var transferProcessId = CONSUMER.requestAssetFrom(assetId, PROVIDER) - .withPrivateProperties(CONSUMER.dynamicReceiverPrivateProperties()) .withTransferType("HttpData-PULL") .execute(); awaitTransferToBeInState(transferProcessId, STARTED); await().atMost(timeout).untilAsserted(() -> { - var state = CONSUMER.getTransferProcessState(transferProcessId); - assertThat(state).isEqualTo(STARTED.name()); - var edr = await().atMost(timeout).until(() -> CONSUMER.getEdr(transferProcessId), Objects::nonNull); - CONSUMER.pullData(edr, Map.of("message", "some information"), equalTo("some information")); + CONSUMER.pullData(edr, Map.of("message", "some information"), body -> assertThat(body).isEqualTo("data")); }); + + provisionServer.verify(HttpRequest.request("/provision")); + + stopQuietly(provisionServer); } @Test void shouldTerminateTransfer_whenContractExpires_fixedInForcePeriod() { - seedVaults(); var assetId = UUID.randomUUID().toString(); var now = Instant.now(); - // contract was valid from t-10d to t-5d, so "now" it is expired var contractPolicy = inForceDatePolicy("gteq", now.minus(ofDays(10)), "lteq", now.minus(ofDays(5))); - createResourcesOnProvider(assetId, contractPolicy, httpDataAddressProperties()); + createResourcesOnProvider(assetId, contractPolicy, httpSourceDataAddress()); var transferProcessId = CONSUMER.requestAssetFrom(assetId, PROVIDER) .withTransferType("HttpData-PULL") .execute(); - await().atMost(timeout).untilAsserted(() -> { - var state = CONSUMER.getTransferProcessState(transferProcessId); - assertThat(state).isEqualTo(TERMINATED.name()); - }); + awaitTransferToBeInState(transferProcessId, TERMINATED); } @Test void shouldTerminateTransfer_whenContractExpires_durationInForcePeriod() { - seedVaults(); var assetId = UUID.randomUUID().toString(); var now = Instant.now(); // contract was valid from t-10d to t-5d, so "now" it is expired var contractPolicy = inForceDatePolicy("gteq", now.minus(ofDays(10)), "lteq", "contractAgreement+1s"); - createResourcesOnProvider(assetId, contractPolicy, httpDataAddressProperties()); + createResourcesOnProvider(assetId, contractPolicy, httpSourceDataAddress()); var transferProcessId = CONSUMER.requestAssetFrom(assetId, PROVIDER) .withTransferType("HttpData-PULL") .execute(); - await().atMost(timeout).untilAsserted(() -> { - var state = CONSUMER.getTransferProcessState(transferProcessId); - assertThat(state).isEqualTo(TERMINATED.name()); - }); + + awaitTransferToBeInState(transferProcessId, TERMINATED); } public JsonObject createCallback(String url, boolean transactional, Set events) { @@ -264,15 +266,12 @@ public JsonObject createCallback(String url, boolean transactional, Set .build(); } - protected abstract void seedVaults(); - - @NotNull - private Map httpDataAddressProperties() { + private static @NotNull Map httpSourceDataAddress() { return Map.of( - "name", "transfer-test", - "baseUrl", PROVIDER.backendService() + "/api/provider/data", - "type", "HttpData", - "proxyQueryParams", "true" + EDC_NAMESPACE + "name", "transfer-test", + EDC_NAMESPACE + "baseUrl", "http://localhost:" + providerDataSource.getPort() + "/source", + EDC_NAMESPACE + "type", "HttpData", + EDC_NAMESPACE + "proxyQueryParams", "true" ); } @@ -290,13 +289,43 @@ private HttpResponse cacheEdr(HttpRequest request, Map { + try { + var request = new Request.Builder() + .url("%s/%s/provision".formatted(requestBody.get("callbackAddress"), requestBody.get("transferProcessId"))) + .post(RequestBody.create(MAPPER.writeValueAsString(callbackRequestBody), get("application/json"))) + .build(); + + testHttpClient().execute(request).close(); + } catch (Exception e) { + throw new EdcException(e); + } + }, 1, SECONDS); + + return response(); + } } - } @Nested @@ -307,10 +336,6 @@ class InMemory extends Tests { static final RuntimeExtension CONSUMER_CONTROL_PLANE = new RuntimePerClassExtension( Runtimes.IN_MEMORY_CONTROL_PLANE.create("consumer-control-plane", CONSUMER.controlPlaneConfiguration())); - @RegisterExtension - static final RuntimeExtension CONSUMER_BACKEND_SERVICE = new RuntimePerClassExtension( - Runtimes.BACKEND_SERVICE.create("consumer-backend-service", CONSUMER.backendServiceConfiguration())); - @RegisterExtension static final RuntimeExtension PROVIDER_CONTROL_PLANE = new RuntimePerClassExtension( Runtimes.IN_MEMORY_CONTROL_PLANE.create("provider-control-plane", PROVIDER.controlPlaneConfiguration())); @@ -319,15 +344,9 @@ class InMemory extends Tests { static final RuntimeExtension PROVIDER_DATA_PLANE = new RuntimePerClassExtension( Runtimes.IN_MEMORY_DATA_PLANE.create("provider-data-plane", PROVIDER.dataPlaneConfiguration())); - @RegisterExtension - static final RuntimeExtension PROVIDER_BACKEND_SERVICE = new RuntimePerClassExtension( - Runtimes.BACKEND_SERVICE.create("provider-backend-service", PROVIDER.backendServiceConfiguration())); - @Override - protected void seedVaults() { - seedVault(CONSUMER_CONTROL_PLANE); - seedVault(PROVIDER_CONTROL_PLANE); - seedVault(PROVIDER_DATA_PLANE); + protected Vault getDataplaneVault() { + return PROVIDER_DATA_PLANE.getService(Vault.class); } } @@ -339,22 +358,13 @@ class EmbeddedDataPlane extends Tests { static final RuntimeExtension CONSUMER_CONTROL_PLANE = new RuntimePerClassExtension( Runtimes.IN_MEMORY_CONTROL_PLANE_EMBEDDED_DATA_PLANE.create("consumer-control-plane", CONSUMER.controlPlaneEmbeddedDataPlaneConfiguration())); - @RegisterExtension - static final RuntimeExtension CONSUMER_BACKEND_SERVICE = new RuntimePerClassExtension( - Runtimes.BACKEND_SERVICE.create("consumer-backend-service", CONSUMER.backendServiceConfiguration())); - @RegisterExtension static final RuntimeExtension PROVIDER_CONTROL_PLANE = new RuntimePerClassExtension( Runtimes.IN_MEMORY_CONTROL_PLANE_EMBEDDED_DATA_PLANE.create("provider-control-plane", PROVIDER.controlPlaneEmbeddedDataPlaneConfiguration())); - @RegisterExtension - static final RuntimeExtension PROVIDER_BACKEND_SERVICE = new RuntimePerClassExtension( - Runtimes.BACKEND_SERVICE.create("provider-backend-service", PROVIDER.backendServiceConfiguration())); - @Override - protected void seedVaults() { - seedVault(CONSUMER_CONTROL_PLANE); - seedVault(PROVIDER_CONTROL_PLANE); + protected Vault getDataplaneVault() { + return PROVIDER_CONTROL_PLANE.getService(Vault.class); } } @@ -372,10 +382,6 @@ class Postgres extends Tests { static final RuntimeExtension CONSUMER_CONTROL_PLANE = new RuntimePerClassExtension( Runtimes.POSTGRES_CONTROL_PLANE.create("consumer-control-plane", CONSUMER.controlPlanePostgresConfiguration())); - @RegisterExtension - static final RuntimeExtension CONSUMER_BACKEND_SERVICE = new RuntimePerClassExtension( - Runtimes.BACKEND_SERVICE.create("consumer-backend-service", CONSUMER.backendServiceConfiguration())); - @RegisterExtension static final RuntimeExtension PROVIDER_CONTROL_PLANE = new RuntimePerClassExtension( Runtimes.POSTGRES_CONTROL_PLANE.create("provider-control-plane", PROVIDER.controlPlanePostgresConfiguration())); @@ -384,15 +390,9 @@ class Postgres extends Tests { static final RuntimeExtension PROVIDER_DATA_PLANE = new RuntimePerClassExtension( Runtimes.POSTGRES_DATA_PLANE.create("provider-data-plane", PROVIDER.dataPlanePostgresConfiguration())); - @RegisterExtension - static final RuntimeExtension PROVIDER_BACKEND_SERVICE = new RuntimePerClassExtension( - Runtimes.BACKEND_SERVICE.create("provider-backend-service", PROVIDER.backendServiceConfiguration())); - @Override - protected void seedVaults() { - seedVault(CONSUMER_CONTROL_PLANE); - seedVault(PROVIDER_CONTROL_PLANE); - seedVault(PROVIDER_DATA_PLANE); + protected Vault getDataplaneVault() { + return PROVIDER_DATA_PLANE.getService(Vault.class); } } diff --git a/system-tests/e2e-transfer-test/runner/src/test/java/org/eclipse/edc/test/e2e/TransferPushEndToEndTest.java b/system-tests/e2e-transfer-test/runner/src/test/java/org/eclipse/edc/test/e2e/TransferPushEndToEndTest.java index 09e6cc0d1c4..83ea8d958f4 100644 --- a/system-tests/e2e-transfer-test/runner/src/test/java/org/eclipse/edc/test/e2e/TransferPushEndToEndTest.java +++ b/system-tests/e2e-transfer-test/runner/src/test/java/org/eclipse/edc/test/e2e/TransferPushEndToEndTest.java @@ -19,83 +19,103 @@ import org.eclipse.edc.junit.annotations.PostgresqlIntegrationTest; import org.eclipse.edc.junit.extensions.RuntimeExtension; import org.eclipse.edc.junit.extensions.RuntimePerClassExtension; -import org.jetbrains.annotations.NotNull; +import org.eclipse.edc.spi.security.Vault; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.BeforeAllCallback; import org.junit.jupiter.api.extension.RegisterExtension; +import org.mockserver.integration.ClientAndServer; +import org.mockserver.model.BinaryBody; +import org.mockserver.model.HttpRequest; +import org.mockserver.model.HttpResponse; import java.util.Map; import java.util.UUID; -import static io.restassured.RestAssured.given; import static jakarta.json.Json.createObjectBuilder; -import static org.eclipse.edc.connector.controlplane.test.system.utils.PolicyFixtures.noConstraintPolicy; import static org.eclipse.edc.connector.controlplane.transfer.spi.types.TransferProcessStates.COMPLETED; import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.TYPE; import static org.eclipse.edc.spi.constants.CoreConstants.EDC_NAMESPACE; import static org.eclipse.edc.sql.testfixtures.PostgresqlEndToEndInstance.createDatabase; -import static org.hamcrest.Matchers.anyOf; -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.notNullValue; +import static org.eclipse.edc.util.io.Ports.getFreePort; +import static org.mockserver.integration.ClientAndServer.startClientAndServer; +import static org.mockserver.model.JsonBody.json; +import static org.mockserver.stop.Stop.stopQuietly; class TransferPushEndToEndTest { abstract static class Tests extends TransferEndToEndTestBase { + private static ClientAndServer providerDataSource; + private static ClientAndServer consumerDataDestination; + + @BeforeAll + static void setUp() { + providerDataSource = startClientAndServer(getFreePort()); + consumerDataDestination = startClientAndServer(getFreePort()); + consumerDataDestination.when(HttpRequest.request()).respond(HttpResponse.response()); + } + + @AfterAll + static void afterAll() { + stopQuietly(providerDataSource); + stopQuietly(consumerDataDestination); + } + @Test void httpPushDataTransfer() { - seedVaults(); + providerDataSource.when(HttpRequest.request()).respond(HttpResponse.response().withBody("data")); var assetId = UUID.randomUUID().toString(); - createResourcesOnProvider(assetId, noConstraintPolicy(), httpDataAddressProperties()); - var destination = httpDataAddress(CONSUMER.backendService() + "/api/consumer/store"); + var dataAddressProperties = Map.of( + "name", "transfer-test", + "baseUrl", "http://localhost:" + providerDataSource.getPort() + "/source", + "type", "HttpData", + "proxyQueryParams", "true" + ); + createResourcesOnProvider(assetId, dataAddressProperties); var transferProcessId = CONSUMER.requestAssetFrom(assetId, PROVIDER) - .withDestination(destination).withTransferType("HttpData-PUSH").execute(); + .withDestination(httpDataAddress("http://localhost:" + consumerDataDestination.getPort() + "/destination")) + .withTransferType("HttpData-PUSH").execute(); awaitTransferToBeInState(transferProcessId, COMPLETED); - given() - .baseUri(CONSUMER.backendService().toString()) - .when() - .get("/api/consumer/data") - .then() - .statusCode(anyOf(is(200), is(204))) - .body(is(notNullValue())); + providerDataSource.verify(HttpRequest.request("/source").withMethod("GET")); + consumerDataDestination.verify(HttpRequest.request("/destination").withBody(BinaryBody.binary("data".getBytes()))); } @Test void httpToHttp_oauth2Provisioning() { - seedVaults(); + var oauth2server = startClientAndServer(getFreePort()); + oauth2server.when(HttpRequest.request()).respond(HttpResponse.response().withBody(json(Map.of("access_token", "token")))); + providerDataSource.when(HttpRequest.request()).respond(HttpResponse.response().withBody("data")); + getDataplaneVault().storeSecret("provision-oauth-secret", "supersecret"); var assetId = UUID.randomUUID().toString(); var sourceDataAddressProperties = Map.of( "type", "HttpData", - "baseUrl", PROVIDER.backendService() + "/api/provider/oauth2data", + "baseUrl", "http://localhost:" + providerDataSource.getPort() + "/source", "oauth2:clientId", "clientId", "oauth2:clientSecretKey", "provision-oauth-secret", - "oauth2:tokenUrl", PROVIDER.backendService() + "/api/oauth2/token" + "oauth2:tokenUrl", "http://localhost:" + oauth2server.getPort() + "/token" ); - createResourcesOnProvider(assetId, noConstraintPolicy(), sourceDataAddressProperties); - var destination = httpDataAddress(CONSUMER.backendService() + "/api/consumer/store"); + createResourcesOnProvider(assetId, sourceDataAddressProperties); var transferProcessId = CONSUMER.requestAssetFrom(assetId, PROVIDER) - .withDestination(destination).withTransferType("HttpData-PUSH").execute(); + .withDestination(httpDataAddress("http://localhost:" + consumerDataDestination.getPort() + "/destination")) + .withTransferType("HttpData-PUSH").execute(); awaitTransferToBeInState(transferProcessId, COMPLETED); - given() - .baseUri(CONSUMER.backendService().toString()) - .when() - .get("/api/consumer/data") - .then() - .statusCode(anyOf(is(200), is(204))) - .body(is(notNullValue())); + oauth2server.verify(HttpRequest.request("/token").withBody("grant_type=client_credentials&client_secret=supersecret&client_id=clientId")); + providerDataSource.verify(HttpRequest.request("/source").withMethod("GET").withHeader("Authorization", "Bearer token")); + consumerDataDestination.verify(HttpRequest.request("/destination").withBody(BinaryBody.binary("data".getBytes()))); + stopQuietly(oauth2server); } - protected abstract void seedVaults(); - private JsonObject httpDataAddress(String baseUrl) { return createObjectBuilder() .add(TYPE, EDC_NAMESPACE + "DataAddress") @@ -103,16 +123,6 @@ private JsonObject httpDataAddress(String baseUrl) { .add(EDC_NAMESPACE + "baseUrl", baseUrl) .build(); } - - @NotNull - private Map httpDataAddressProperties() { - return Map.of( - "name", "transfer-test", - "baseUrl", PROVIDER.backendService() + "/api/provider/data", - "type", "HttpData", - "proxyQueryParams", "true" - ); - } } @Nested @@ -123,10 +133,6 @@ class InMemory extends Tests { static final RuntimeExtension CONSUMER_CONTROL_PLANE = new RuntimePerClassExtension( Runtimes.IN_MEMORY_CONTROL_PLANE.create("consumer-control-plane", CONSUMER.controlPlaneConfiguration())); - @RegisterExtension - static final RuntimeExtension CONSUMER_BACKEND_SERVICE = new RuntimePerClassExtension( - Runtimes.BACKEND_SERVICE.create("consumer-backend-service", CONSUMER.backendServiceConfiguration())); - @RegisterExtension static final RuntimeExtension PROVIDER_CONTROL_PLANE = new RuntimePerClassExtension( Runtimes.IN_MEMORY_CONTROL_PLANE.create("provider-control-plane", PROVIDER.controlPlaneConfiguration())); @@ -135,15 +141,9 @@ class InMemory extends Tests { static final RuntimeExtension PROVIDER_DATA_PLANE = new RuntimePerClassExtension( Runtimes.IN_MEMORY_DATA_PLANE.create("provider-data-plane", PROVIDER.dataPlaneConfiguration())); - @RegisterExtension - static final RuntimeExtension PROVIDER_BACKEND_SERVICE = new RuntimePerClassExtension( - Runtimes.BACKEND_SERVICE.create("provider-backend-service", PROVIDER.backendServiceConfiguration())); - @Override - protected void seedVaults() { - seedVault(CONSUMER_CONTROL_PLANE); - seedVault(PROVIDER_CONTROL_PLANE); - seedVault(PROVIDER_DATA_PLANE); + protected Vault getDataplaneVault() { + return PROVIDER_DATA_PLANE.getService(Vault.class); } } @@ -153,24 +153,15 @@ class EmbeddedDataPlane extends Tests { @RegisterExtension static final RuntimeExtension CONSUMER_CONTROL_PLANE = new RuntimePerClassExtension( - Runtimes.IN_MEMORY_CONTROL_PLANE_EMBEDDED_DATA_PLANE.create("consumer-control-plane", CONSUMER.controlPlaneConfiguration())); - - @RegisterExtension - static final RuntimeExtension CONSUMER_BACKEND_SERVICE = new RuntimePerClassExtension( - Runtimes.BACKEND_SERVICE.create("consumer-backend-service", CONSUMER.backendServiceConfiguration())); + Runtimes.IN_MEMORY_CONTROL_PLANE.create("consumer-control-plane", CONSUMER.controlPlaneConfiguration())); @RegisterExtension static final RuntimeExtension PROVIDER_CONTROL_PLANE = new RuntimePerClassExtension( Runtimes.IN_MEMORY_CONTROL_PLANE_EMBEDDED_DATA_PLANE.create("provider-control-plane", PROVIDER.controlPlaneEmbeddedDataPlaneConfiguration())); - @RegisterExtension - static final RuntimeExtension PROVIDER_BACKEND_SERVICE = new RuntimePerClassExtension( - Runtimes.BACKEND_SERVICE.create("provider-backend-service", PROVIDER.backendServiceConfiguration())); - @Override - protected void seedVaults() { - seedVault(CONSUMER_CONTROL_PLANE); - seedVault(PROVIDER_CONTROL_PLANE); + protected Vault getDataplaneVault() { + return PROVIDER_CONTROL_PLANE.getService(Vault.class); } } @@ -188,10 +179,6 @@ class Postgres extends Tests { static final RuntimeExtension CONSUMER_CONTROL_PLANE = new RuntimePerClassExtension( Runtimes.POSTGRES_CONTROL_PLANE.create("consumer-control-plane", CONSUMER.controlPlanePostgresConfiguration())); - @RegisterExtension - static final RuntimeExtension CONSUMER_BACKEND_SERVICE = new RuntimePerClassExtension( - Runtimes.BACKEND_SERVICE.create("consumer-backend-service", CONSUMER.backendServiceConfiguration())); - @RegisterExtension static final RuntimeExtension PROVIDER_CONTROL_PLANE = new RuntimePerClassExtension( Runtimes.POSTGRES_CONTROL_PLANE.create("provider-control-plane", PROVIDER.controlPlanePostgresConfiguration())); @@ -200,15 +187,9 @@ class Postgres extends Tests { static final RuntimeExtension PROVIDER_DATA_PLANE = new RuntimePerClassExtension( Runtimes.POSTGRES_DATA_PLANE.create("provider-data-plane", PROVIDER.dataPlanePostgresConfiguration())); - @RegisterExtension - static final RuntimeExtension PROVIDER_BACKEND_SERVICE = new RuntimePerClassExtension( - Runtimes.BACKEND_SERVICE.create("provider-backend-service", PROVIDER.backendServiceConfiguration())); - @Override - protected void seedVaults() { - seedVault(CONSUMER_CONTROL_PLANE); - seedVault(PROVIDER_CONTROL_PLANE); - seedVault(PROVIDER_DATA_PLANE); + protected Vault getDataplaneVault() { + return PROVIDER_DATA_PLANE.getService(Vault.class); } } diff --git a/system-tests/e2e-transfer-test/runner/src/test/java/org/eclipse/edc/test/e2e/TransferStreamingEndToEndTest.java b/system-tests/e2e-transfer-test/runner/src/test/java/org/eclipse/edc/test/e2e/TransferStreamingEndToEndTest.java index cbf453df81d..47eaf4184a0 100644 --- a/system-tests/e2e-transfer-test/runner/src/test/java/org/eclipse/edc/test/e2e/TransferStreamingEndToEndTest.java +++ b/system-tests/e2e-transfer-test/runner/src/test/java/org/eclipse/edc/test/e2e/TransferStreamingEndToEndTest.java @@ -29,6 +29,7 @@ import org.eclipse.edc.junit.annotations.EndToEndTest; import org.eclipse.edc.junit.extensions.RuntimeExtension; import org.eclipse.edc.junit.extensions.RuntimePerClassExtension; +import org.eclipse.edc.spi.security.Vault; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; @@ -53,7 +54,6 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.awaitility.Awaitility.await; import static org.eclipse.edc.connector.controlplane.test.system.utils.PolicyFixtures.contractExpiresIn; -import static org.eclipse.edc.connector.controlplane.test.system.utils.PolicyFixtures.noConstraintPolicy; import static org.eclipse.edc.connector.controlplane.transfer.spi.types.TransferProcessStates.STARTED; import static org.eclipse.edc.connector.controlplane.transfer.spi.types.TransferProcessStates.SUSPENDED; import static org.eclipse.edc.connector.controlplane.transfer.spi.types.TransferProcessStates.TERMINATED; @@ -77,10 +77,6 @@ class InMemory extends Tests { static final RuntimeExtension CONSUMER_CONTROL_PLANE = new RuntimePerClassExtension( Runtimes.IN_MEMORY_CONTROL_PLANE.create("consumer-control-plane", CONSUMER.controlPlaneConfiguration())); - @RegisterExtension - static final RuntimeExtension CONSUMER_BACKEND_SERVICE = new RuntimePerClassExtension( - Runtimes.BACKEND_SERVICE.create("consumer-backend-service", CONSUMER.backendServiceConfiguration())); - @RegisterExtension static final RuntimeExtension PROVIDER_CONTROL_PLANE = new RuntimePerClassExtension( Runtimes.IN_MEMORY_CONTROL_PLANE.create("provider-control-plane", PROVIDER.controlPlaneConfiguration())); @@ -89,10 +85,10 @@ class InMemory extends Tests { static final RuntimeExtension PROVIDER_DATA_PLANE = new RuntimePerClassExtension( Runtimes.IN_MEMORY_DATA_PLANE.create("provider-data-plane", PROVIDER.dataPlaneConfiguration())); - @RegisterExtension - static final RuntimeExtension PROVIDER_BACKEND_SERVICE = new RuntimePerClassExtension( - Runtimes.BACKEND_SERVICE.create("provider-backend-service", PROVIDER.backendServiceConfiguration())); - + @Override + protected Vault getDataplaneVault() { + return PROVIDER_DATA_PLANE.getService(Vault.class); + } } @Testcontainers @@ -172,7 +168,7 @@ void shouldSuspendAndResumeTransfer() { consumer.subscribe(List.of(SINK_TOPIC)); var assetId = UUID.randomUUID().toString(); - createResourcesOnProvider(assetId, noConstraintPolicy(), kafkaSourceProperty()); + createResourcesOnProvider(assetId, kafkaSourceProperty()); var transferProcessId = CONSUMER.requestAssetFrom(assetId, PROVIDER) .withDestination(kafkaSink()).withTransferType("Kafka-PUSH").execute();