From c777edd42a7a89158c23ea41b8c2a06d093b4e39 Mon Sep 17 00:00:00 2001 From: Paul Latzelsperger <43503240+paullatzelsperger@users.noreply.github.com> Date: Tue, 15 Oct 2024 15:00:24 +0200 Subject: [PATCH] feat(ci): use E2E tests for BOM smoke tests (#4550) * feat(ci): use E2E tests for BOM Smoke tests * pr remarks --- .github/workflows/verify.yaml | 16 +- .../controlplane-dcp-bom/example.properties | 7 - .../example.properties | 5 - .../bom/dataplane-base-bom/example.properties | 6 - dist/bom/sts-feature-bom/example.properties | 1 - settings.gradle.kts | 1 + system-tests/bom-tests/build.gradle.kts | 31 ++++ .../eclipse/edc/test/bom/BomSmokeTests.java | 164 ++++++++++++++++++ .../bom-tests/src/test/resources/cert.pem | 13 ++ .../src/test/resources/jwks_response.json | 20 +++ 10 files changed, 231 insertions(+), 33 deletions(-) delete mode 100644 dist/bom/controlplane-dcp-bom/example.properties delete mode 100644 dist/bom/controlplane-oauth2-bom/example.properties delete mode 100644 dist/bom/dataplane-base-bom/example.properties delete mode 100644 dist/bom/sts-feature-bom/example.properties create mode 100644 system-tests/bom-tests/build.gradle.kts create mode 100644 system-tests/bom-tests/src/test/java/org/eclipse/edc/test/bom/BomSmokeTests.java create mode 100644 system-tests/bom-tests/src/test/resources/cert.pem create mode 100644 system-tests/bom-tests/src/test/resources/jwks_response.json diff --git a/.github/workflows/verify.yaml b/.github/workflows/verify.yaml index 13a4408b6df..49e5e652af7 100644 --- a/.github/workflows/verify.yaml +++ b/.github/workflows/verify.yaml @@ -3,9 +3,9 @@ name: Run Tests on: workflow_dispatch: push: - branches: [main, release/*, bugfix/*] + branches: [ main, release/*, bugfix/* ] pull_request: - branches: [main, release/*, bugfix/*] + branches: [ main, release/*, bugfix/* ] paths-ignore: - "**.md" - "docs/**" @@ -91,15 +91,3 @@ jobs: uses: eclipse-edc/.github/.github/workflows/verify-openapi.yml@main secrets: inherit - Verify-EDC-BOM: - strategy: - fail-fast: false - - # we can't test the "controlplane-oauth2-com" because it only starts successfully if the public key is already in the vault - matrix: - bom-directory: - ["dist/bom/controlplane-dcp-bom", "dist/bom/sts-feature-bom"] - uses: eclipse-edc/.github/.github/workflows/verify-bom.yml@main - with: - module-dir: ${{ matrix.bom-directory }} - properties-file: example.properties diff --git a/dist/bom/controlplane-dcp-bom/example.properties b/dist/bom/controlplane-dcp-bom/example.properties deleted file mode 100644 index 2311c0ef6f1..00000000000 --- a/dist/bom/controlplane-dcp-bom/example.properties +++ /dev/null @@ -1,7 +0,0 @@ -edc.iam.sts.oauth.token.url=https://sts.com/token -edc.iam.sts.oauth.client.id=test-client -edc.iam.sts.oauth.client.secret.alias=test-alias -web.http.port=8080 -web.http.path=/api -web.http.management.port=8081 -web.http.management.path=/api/management \ No newline at end of file diff --git a/dist/bom/controlplane-oauth2-bom/example.properties b/dist/bom/controlplane-oauth2-bom/example.properties deleted file mode 100644 index a319f1ac513..00000000000 --- a/dist/bom/controlplane-oauth2-bom/example.properties +++ /dev/null @@ -1,5 +0,0 @@ -edc.oauth.token.url=https://oauth2.com/token -# this will require the public key alias to be present in the vault -edc.oauth.certificate.alias=test-alias -edc.oauth.private.key.alias=private-test-alias -edc.oauth.client.id=test-client \ No newline at end of file diff --git a/dist/bom/dataplane-base-bom/example.properties b/dist/bom/dataplane-base-bom/example.properties deleted file mode 100644 index 75facad1235..00000000000 --- a/dist/bom/dataplane-base-bom/example.properties +++ /dev/null @@ -1,6 +0,0 @@ -edc.transfer.proxy.token.verifier.publickey.alias=test-alias -edc.transfer.proxy.token.signer.privatekey.alias=private-alias -edc.dpf.selector.url=http://test.com/selector -web.http.control.port=9091 -web.http.control.path=/api/control -web.http.port=9090 \ No newline at end of file diff --git a/dist/bom/sts-feature-bom/example.properties b/dist/bom/sts-feature-bom/example.properties deleted file mode 100644 index e153d883a44..00000000000 --- a/dist/bom/sts-feature-bom/example.properties +++ /dev/null @@ -1 +0,0 @@ -edc.api.accounts.key=password \ No newline at end of file diff --git a/settings.gradle.kts b/settings.gradle.kts index 9c17d4fc8de..4948a783224 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -285,6 +285,7 @@ include(":system-tests:sts-api:sts-api-test-runner") include(":system-tests:sts-api:sts-api-test-runtime") include(":system-tests:telemetry:telemetry-test-runner") include(":system-tests:telemetry:telemetry-test-runtime") +include(":system-tests:bom-tests") // BOM modules ---------------------------------------------------------------- include(":dist:bom:controlplane-base-bom") diff --git a/system-tests/bom-tests/build.gradle.kts b/system-tests/bom-tests/build.gradle.kts new file mode 100644 index 00000000000..85d8068b72f --- /dev/null +++ b/system-tests/bom-tests/build.gradle.kts @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + * + * Contributors: + * Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - initial API and implementation + * + */ + +plugins { + java +} + +dependencies { + testImplementation(project(":core:common:junit")) + testImplementation(project(":core:common:lib:boot-lib")) + testImplementation(libs.restAssured) + testImplementation(libs.assertj) + testImplementation(libs.awaitility) + testImplementation(libs.mockserver.netty) + testImplementation(libs.mockserver.client) +} + +edcBuild { + publish.set(false) +} diff --git a/system-tests/bom-tests/src/test/java/org/eclipse/edc/test/bom/BomSmokeTests.java b/system-tests/bom-tests/src/test/java/org/eclipse/edc/test/bom/BomSmokeTests.java new file mode 100644 index 00000000000..5231e68f86b --- /dev/null +++ b/system-tests/bom-tests/src/test/java/org/eclipse/edc/test/bom/BomSmokeTests.java @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + * + * Contributors: + * Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - initial API and implementation + * + */ + +package org.eclipse.edc.test.bom; + +import org.eclipse.edc.boot.vault.InMemoryVault; +import org.eclipse.edc.junit.annotations.EndToEndTest; +import org.eclipse.edc.junit.extensions.EmbeddedRuntime; +import org.eclipse.edc.junit.extensions.RuntimeExtension; +import org.eclipse.edc.junit.extensions.RuntimePerMethodExtension; +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.RegisterExtension; +import org.mockserver.integration.ClientAndServer; + +import java.util.Map; + +import static io.restassured.RestAssured.given; +import static org.awaitility.Awaitility.await; +import static org.eclipse.edc.junit.testfixtures.TestUtils.getResourceFileContentAsString; +import static org.eclipse.edc.util.io.Ports.getFreePort; +import static org.hamcrest.Matchers.equalTo; +import static org.mockito.Mockito.mock; +import static org.mockserver.model.HttpRequest.request; +import static org.mockserver.model.HttpResponse.response; +import static org.mockserver.stop.Stop.stopQuietly; + +public class BomSmokeTests { + abstract static class SmokeTest { + public static final String DEFAULT_PORT = "8080"; + public static final String DEFAULT_PATH = "/api"; + + @Test + void assertRuntimeReady() { + await().untilAsserted(() -> given() + .baseUri("http://localhost:" + DEFAULT_PORT + DEFAULT_PATH + "/check/startup") + .get() + .then() + .statusCode(200) + .log().ifValidationFails() + .body("isSystemHealthy", equalTo(true))); + + } + } + + @Nested + @EndToEndTest + class ControlPlaneDcp extends SmokeTest { + + @RegisterExtension + protected RuntimeExtension runtime = + new RuntimePerMethodExtension(new EmbeddedRuntime("control-plane-dcp-bom", + Map.of( + "edc.iam.sts.oauth.token.url", "https://sts.com/token", + "edc.iam.sts.oauth.client.id", "test-client", + "edc.iam.sts.oauth.client.secret.alias", "test-alias", + "web.http.port", DEFAULT_PORT, + "web.http.path", DEFAULT_PATH, + "web.http.management.port", "8081", + "web.http.management.path", "/api/management"), + ":dist:bom:controlplane-dcp-bom" + )); + } + + @Nested + @EndToEndTest + class ControlPlaneOauth2 extends SmokeTest { + + @RegisterExtension + protected static RuntimeExtension runtime = + new RuntimePerMethodExtension(new EmbeddedRuntime("control-plane-oauth2-bom", + Map.of( + "edc.oauth.token.url", "https://oauth2.com/token", + "edc.oauth.certificate.alias", "test-alias", + "edc.oauth.private.key.alias", "private-test-alias", + "web.http.management.port", "8081", + "web.http.management.path", "/api/management", + "web.http.port", DEFAULT_PORT, + "web.http.path", DEFAULT_PATH, + "edc.oauth.provider.jwks.url", "http://localhost:9999/jwks", + "edc.oauth.client.id", "test-client"), + ":dist:bom:controlplane-oauth2-bom" + )); + private static ClientAndServer jwksServer; + + @BeforeAll + static void setup() { + var v = new InMemoryVault(mock()); + v.storeSecret("test-alias", getResourceFileContentAsString("cert.pem")); + runtime.registerServiceMock(Vault.class, v); + + // mock the JWKS server, respond with some arbitrary JWKS + jwksServer = ClientAndServer.startClientAndServer(9999); + jwksServer.when(request().withPath("/jwks").withMethod("GET")) + .respond(response().withStatusCode(200).withBody(getResourceFileContentAsString("jwks_response.json"))); + } + + @AfterAll + static void cleanup() { + stopQuietly(jwksServer); + } + } + + @Nested + @EndToEndTest + public class DataPlaneBase extends SmokeTest { + + private static ClientAndServer server; + @RegisterExtension + protected RuntimeExtension runtime = + new RuntimePerMethodExtension(new EmbeddedRuntime("data-plane-base-bom", + Map.of( + "edc.transfer.proxy.token.verifier.publickey.alias", "test-alias", + "edc.transfer.proxy.token.signer.privatekey.alias", "private-alias", + "edc.dpf.selector.url", "http://localhost:%s/selector".formatted(server.getPort()), + "web.http.control.port", "8081", + "web.http.control.path", "/api/control", + "web.http.port", DEFAULT_PORT, + "web.http.path", DEFAULT_PATH), + ":dist:bom:dataplane-base-bom" + )); + + @BeforeAll + static void setup() { + server = ClientAndServer.startClientAndServer(getFreePort()); + server.when(request().withPath("/selector")) + .respond(response().withStatusCode(200)); + } + + @AfterAll + static void afterAll() { + stopQuietly(server); + } + } + + @Nested + @EndToEndTest + class StsFeature extends SmokeTest { + + @RegisterExtension + protected RuntimeExtension runtime = + new RuntimePerMethodExtension(new EmbeddedRuntime("data-plane-base-bom", + Map.of( + "web.http.port", DEFAULT_PORT, + "web.http.path", DEFAULT_PATH, + "edc.api.accounts.key", "password"), + ":dist:bom:sts-feature-bom" + )); + } +} diff --git a/system-tests/bom-tests/src/test/resources/cert.pem b/system-tests/bom-tests/src/test/resources/cert.pem new file mode 100644 index 00000000000..a1a70cc3eb1 --- /dev/null +++ b/system-tests/bom-tests/src/test/resources/cert.pem @@ -0,0 +1,13 @@ +-----BEGIN CERTIFICATE----- +MIIB7DCCAVWgAwIBAgIGAYHYExlWMA0GCSqGSIb3DQEBCwUAMA8xDTALBgNVBAMM +BFRlc3QwHhcNMjIwNzA3MDk1MjE5WhcNMzIwNzA0MDk1MjE5WjAPMQ0wCwYDVQQD +DARUZXN0MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDHggAW6QF9E2N2y37U +xcacS+LFZwyVIFJkd/Zbe4JF0N+qqPGgRO8kMYiXb12geuJ+lxobLQkOlsnztkfX +htVLkYoruSthMQORC/fZDhP1eV5KpR0LVACoQmLJBTbKE2tOJh5HODxvzhiV+Bi5 +DAWOhmkA1dYo1UFg8ORt/YzOvQIDAQABo1MwUTAdBgNVHQ4EFgQUwxs2XndsvlwH +4JqFpqMXF9mEDVAwHwYDVR0jBBgwFoAUwxs2XndsvlwH4JqFpqMXF9mEDVAwDwYD +VR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOBgQCajJWQ7x7TEZvCRXWr3J43 +WFoOZBjhKwDtNySoeF/mJvxEcWzeCfxvqO/zQ16+vMj/+1kW7+eex8dSYBfRtb83 +MjOtKQYd4PU5uH4QqFFyJ3oH72ZItTAikfuRcrV0Gu7lsLSkLjglUFAREr8aI0QC +0SDLUMXw7nNsSJ/s2yIiVw== +-----END CERTIFICATE----- \ No newline at end of file diff --git a/system-tests/bom-tests/src/test/resources/jwks_response.json b/system-tests/bom-tests/src/test/resources/jwks_response.json new file mode 100644 index 00000000000..95abe9db3df --- /dev/null +++ b/system-tests/bom-tests/src/test/resources/jwks_response.json @@ -0,0 +1,20 @@ +{ + "keys": [ + { + "kty": "RSA", + "kid": "1438289820780", + "use": "sig", + "alg": "RS256", + "n": "idWPro_QiAFOdMsJD163lcDIPogOwXogRo3Pct2MMyeE2GAGqV20Sc8QUbuLDfPl-7Hi9IfFOz--JY6QL5l92eV-GJXkTmidUEooZxIZSp3ghRxLCqlyHeF5LuuM5LPRFDeF4YWFQT_D2eNo_w95g6qYSeOwOwGIfaHa2RMPcQAiM6LX4ot-Z7Po9z0_3ztFa02m3xejEFr2rLRqhFl3FZJaNnwTUk6an6XYsunxMk3Ya3lRaKJReeXeFtfTpShgtPiAl7lIfLJH9h26h2OAlww531DpxHSm1gKXn6bjB0NTC55vJKft4wXoc_0xKZhnWmjQE8d9xE8e1Z3Ll1LYbw", + "e": "AQAB" + }, + { + "kty": "RSA", + "kid": "1438289856256", + "use": "sig", + "alg": "RS256", + "n": "zo5cKcbFECeiH8eGx2D-DsFSpjSKbTVlXD6uL5JAy9rYIv7eYEP6vrKeX-x1z70yEdvgk9xbf9alc8siDfAz3rLCknqlqL7XGVAQL0ZP63UceDmD60LHOzMrx4eR6p49B3rxFfjvX2SWSV3-1H6XNyLk_ALbG6bGCFGuWBQzPJB4LMKCrOFq-6jtRKOKWBXYgkYkaYs5dG-3e2ULbq-y2RdgxYh464y_-MuxDQfvUgP787XKfcXP_XjJZvyuOEANjVyJYZSOyhHUlSGJapQ8ztHdF-swsnf7YkePJ2eR9fynWV2ZoMaXOdidgZtGTa4R1Z4BgH2C0hKJiqRy9fB7Gw", + "e": "AQAB" + } + ] +} \ No newline at end of file