From 108f34c5497078a20ae083c608d9b029ceaaac8a Mon Sep 17 00:00:00 2001 From: Ronja Quensel Date: Wed, 8 Jul 2026 14:30:07 +0200 Subject: [PATCH] feat: add auth profile for dataplane --- .../java/org/eclipse/dataplane/Dataplane.java | 9 +++++- .../registration/AuthorizationProfile.java | 2 ++ .../DataPlaneRegistrationMessage.java | 4 +-- docs/getting-started.md | 3 +- .../org/eclipse/dataplane/DataplaneTest.java | 30 +++++++++++++++++++ 5 files changed, 44 insertions(+), 4 deletions(-) diff --git a/dataplane-sdk-core/src/main/java/org/eclipse/dataplane/Dataplane.java b/dataplane-sdk-core/src/main/java/org/eclipse/dataplane/Dataplane.java index 7459083..68c8eb1 100644 --- a/dataplane-sdk-core/src/main/java/org/eclipse/dataplane/Dataplane.java +++ b/dataplane-sdk-core/src/main/java/org/eclipse/dataplane/Dataplane.java @@ -31,6 +31,7 @@ import org.eclipse.dataplane.domain.dataflow.DataFlowSuspendMessage; import org.eclipse.dataplane.domain.dataflow.DataFlowTerminateMessage; import org.eclipse.dataplane.domain.registration.Authorization; +import org.eclipse.dataplane.domain.registration.AuthorizationProfile; import org.eclipse.dataplane.domain.registration.ControlPlaneRegistrationMessage; import org.eclipse.dataplane.domain.registration.DataPlaneRegistrationMessage; import org.eclipse.dataplane.logic.OnCompleted; @@ -75,6 +76,7 @@ public class Dataplane { private ControlPlaneStore controlPlaneStore = new InMemoryControlPlaneStore(objectMapper); private String id; private URI endpoint; + private AuthorizationProfile authorizationProfile; private final Set profiles = new HashSet<>(); private final Set labels = new HashSet<>(); @@ -317,7 +319,7 @@ public Result extractControlplaneId(String authorizationHeader) { public Result registerOn(String controlPlaneEndpoint) { - var message = new DataPlaneRegistrationMessage(id, endpoint, profiles, labels); + var message = new DataPlaneRegistrationMessage(id, endpoint, profiles, labels, authorizationProfile); return toJson(message) .map(body -> HttpRequest.newBuilder() @@ -445,6 +447,11 @@ public Builder endpoint(URI endpoint) { return this; } + public Builder authorizationProfile(AuthorizationProfile authorizationProfile) { + dataplane.authorizationProfile = authorizationProfile; + return this; + } + public Builder profile(String profile) { dataplane.profiles.add(profile); return this; diff --git a/dataplane-sdk-core/src/main/java/org/eclipse/dataplane/domain/registration/AuthorizationProfile.java b/dataplane-sdk-core/src/main/java/org/eclipse/dataplane/domain/registration/AuthorizationProfile.java index 30eeeda..8d3d75c 100644 --- a/dataplane-sdk-core/src/main/java/org/eclipse/dataplane/domain/registration/AuthorizationProfile.java +++ b/dataplane-sdk-core/src/main/java/org/eclipse/dataplane/domain/registration/AuthorizationProfile.java @@ -16,6 +16,7 @@ import com.fasterxml.jackson.annotation.JsonAnyGetter; import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonIgnore; import org.eclipse.dataplane.port.exception.IllegalAttributeTypeException; import java.util.HashMap; @@ -34,6 +35,7 @@ public AuthorizationProfile(String type) { attributes.put("type", type); } + @JsonIgnore public String getType() { return attributes.get("type").toString(); } diff --git a/dataplane-sdk-core/src/main/java/org/eclipse/dataplane/domain/registration/DataPlaneRegistrationMessage.java b/dataplane-sdk-core/src/main/java/org/eclipse/dataplane/domain/registration/DataPlaneRegistrationMessage.java index f5d8a20..d71e591 100644 --- a/dataplane-sdk-core/src/main/java/org/eclipse/dataplane/domain/registration/DataPlaneRegistrationMessage.java +++ b/dataplane-sdk-core/src/main/java/org/eclipse/dataplane/domain/registration/DataPlaneRegistrationMessage.java @@ -21,7 +21,7 @@ public record DataPlaneRegistrationMessage( String dataplaneId, URI endpoint, Set profiles, - Set labels -// TODO: authorization + Set labels, + AuthorizationProfile authorization ) { } diff --git a/docs/getting-started.md b/docs/getting-started.md index 1d38c80..b6c6c5b 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -57,7 +57,8 @@ Additionally, the `Dataplane.Builder` class provides methods for the following p - `endpoint`: the URL under which the Dataplane API is reachable, will be your application's base URL and path plus `/v1/dataflows` - `transferType`: a [transfer type](https://github.com/eclipse-dataplane-signaling/dataplane-signaling/blob/main/specifications/signaling.md#data-transfer-types) supported by the dataplane (multiple transfer types can be added) - `label`: a label for the dataplane instance which can be used by control planes to filter for specific dataplanes (multiple labels can be added) -- `authorization`: defines the authorization used between control and dataplane, for more information see [Authorizations](#authorizations) +- `authorization`: defines a supported authorization for communication with the control plane, for more information see [Authorizations](#authorizations) +- `authorizationProfile`: defines the authorization profile used by this dataplane, i.e. how a control plane should authenticate when talking to this dataplane *There is one additional builder method called `stores()`, which will be detailed later in this guide. When not setting any stores specifically, both `DataFlow` and `ControlPlane` information will be stored in-memory.* diff --git a/e2e-tests/src/test/java/org/eclipse/dataplane/DataplaneTest.java b/e2e-tests/src/test/java/org/eclipse/dataplane/DataplaneTest.java index c28fd67..8a0077a 100644 --- a/e2e-tests/src/test/java/org/eclipse/dataplane/DataplaneTest.java +++ b/e2e-tests/src/test/java/org/eclipse/dataplane/DataplaneTest.java @@ -18,6 +18,7 @@ import com.github.tomakehurst.wiremock.WireMockServer; import org.eclipse.dataplane.domain.Result; import org.eclipse.dataplane.domain.dataflow.DataFlowPrepareMessage; +import org.eclipse.dataplane.domain.registration.AuthorizationProfile; import org.eclipse.dataplane.domain.registration.ControlPlaneRegistrationMessage; import org.eclipse.dataplane.port.exception.DataFlowNotifyControlPlaneFailed; import org.eclipse.dataplane.port.exception.DataplaneNotRegistered; @@ -35,6 +36,7 @@ import static com.github.tomakehurst.wiremock.client.WireMock.and; import static com.github.tomakehurst.wiremock.client.WireMock.anyUrl; import static com.github.tomakehurst.wiremock.client.WireMock.equalTo; +import static com.github.tomakehurst.wiremock.client.WireMock.equalToJson; import static com.github.tomakehurst.wiremock.client.WireMock.matchingJsonPath; import static com.github.tomakehurst.wiremock.client.WireMock.post; import static com.github.tomakehurst.wiremock.client.WireMock.postRequestedFor; @@ -177,6 +179,34 @@ void shouldRegisterOnTheControlPlane() { ); } + @Test + void shouldRegisterOnTheControlPlane_withAuthProfile() { + controlPlane.stubFor(put(anyUrl()).willReturn(aResponse().withStatus(200))); + + var authProfile = new AuthorizationProfile("test") + .withAttribute("key", "value"); + + var dataplane = Dataplane.newInstance() + .id("dataplane-id") + .endpoint(URI.create("http://localhost/dataplane")) + .authorizationProfile(authProfile) + .profile("SupportedTransferType-PUSH") + .label("label-one").label("label-two") + .build(); + + var result = dataplane.registerOn(controlPlane.baseUrl()); + + assertThat(result.succeeded()).isTrue(); + controlPlane.verify(putRequestedFor(urlPathEqualTo("/dataplanes")) + .withRequestBody(and( + matchingJsonPath("endpoint", equalTo("http://localhost/dataplane")), + matchingJsonPath("authorization", equalToJson("{\"type\":\"test\",\"key\":\"value\"}")), + matchingJsonPath("profiles[0]", equalTo("SupportedTransferType-PUSH")), + matchingJsonPath("labels.size()", equalTo("2")) + )) + ); + } + @Test void shouldFail_whenStatusIsNot200() { controlPlane.stubFor(post(anyUrl()).willReturn(aResponse().withStatus(409)));