diff --git a/.github/workflows/e2e-tests.yaml b/.github/workflows/e2e-tests.yaml
index 1656cea..232a701 100644
--- a/.github/workflows/e2e-tests.yaml
+++ b/.github/workflows/e2e-tests.yaml
@@ -94,7 +94,7 @@ jobs:
kubectl wait --namespace edc-v \
--for=condition=ready pod \
--selector=type=edcv-infra \
- --timeout=120s
+ --timeout=300s
- name: "Deploy JAD applications"
run: |-
diff --git a/k8s/apps/dataplane-config.yaml b/k8s/apps/dataplane-config.yaml
index 0d45d43..c9e6b43 100644
--- a/k8s/apps/dataplane-config.yaml
+++ b/k8s/apps/dataplane-config.yaml
@@ -31,7 +31,7 @@ data:
web.http.control.path: "/api/control"
web.http.public.port: "11002"
web.http.public.path: "/api/public"
- web.http.certs.port: "8085"
+ web.http.certs.port: "8186"
web.http.certs.path: "/api/data"
edc.vault.hashicorp.url: "http://vault.edc-v.svc.cluster.local:8200"
diff --git a/k8s/apps/ui-config.yaml b/k8s/apps/ui-config.yaml
new file mode 100644
index 0000000..7cba25f
--- /dev/null
+++ b/k8s/apps/ui-config.yaml
@@ -0,0 +1,58 @@
+#
+# Copyright (c) 2026 Metaform Systems, Inc.
+#
+# 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:
+# Metaform Systems, Inc. - initial API and implementation
+#
+
+---
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: jad-web-ui-config
+ namespace: edc-v
+data:
+ config.json: |
+ {
+ "production": true,
+ "apiUrl": "http://redline.edc-v.svc.cluster.local:8081",
+ "appName": "Aruba's DataSpace",
+ "version": "1.0.0",
+ "features": {
+ "enableMockData": false,
+ "enableAnalytics": true,
+ "enableDebugMode": false,
+ "enableDevMode": true
+ },
+ "auth": {
+ "roles": {
+ "admin": "EDC_ADMIN",
+ "participant": "EDC_USER_PARTICIPANT",
+ "validRoles": ["EDC_ADMIN", "EDC_USER_PARTICIPANT"]
+ },
+ "enableAuth": true,
+ "tokenKey": "auth_token",
+ "keycloak": {
+ "url": "http://keycloak-fe.localhost",
+ "realm": "jad-ui",
+ "clientId": "edc-aruba-provisioning-customers-portal-fe",
+ "initOptions": {
+ "onLoad": "check-sso",
+ "checkLoginIframe": false,
+ "pkceMethod": "S256",
+ "storageKey": "edc-partipant"
+ },
+ "bearerExcludedUrls": ["/assets"]
+ }
+ }
+ }
+
+
+
+# REDLINE_URL: "http://redline.edc-v.svc.cluster.local:8081"
diff --git a/k8s/apps/ui.yaml b/k8s/apps/ui.yaml
new file mode 100644
index 0000000..bff040d
--- /dev/null
+++ b/k8s/apps/ui.yaml
@@ -0,0 +1,92 @@
+#
+# Copyright (c) 2026 Metaform Systems, Inc.
+#
+# 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:
+# Metaform Systems, Inc. - initial API and implementation
+#
+
+
+---
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: jad-web-ui
+ namespace: edc-v
+spec:
+ replicas: 1
+ selector:
+ matchLabels:
+ app: jad-web-ui
+ template:
+ metadata:
+ labels:
+ app: jad-web-ui
+ spec:
+ volumes:
+ - name: config-volume
+ configMap:
+ name: jad-web-ui-config
+ defaultMode: 420
+ containers:
+ - name: jad-web-ui
+ image:
+# ghcr.io/aruba-it-s-p-a/edc-client-participant-fe:3b202e0bb6c88ddef712686e635e25357852377a
+ ghcr.io/aruba-it-s-p-a/edc-public-participant-portal:demo-madrid
+ ports:
+ - containerPort: 80
+ protocol: TCP
+ env:
+ - name: HOST_API
+ value: https://identity.aruba.io
+ resources: {}
+ volumeMounts:
+ - name: config-volume
+ mountPath: /usr/share/nginx/html/customers/assets/config
+ imagePullPolicy: Always
+
+---
+apiVersion: v1
+kind: Service
+metadata:
+ name: jad-web-ui
+ namespace: edc-v
+ labels:
+ app: jad-web-ui
+spec:
+ type: ClusterIP
+ ports:
+ - port: 80
+ targetPort: 80
+ protocol: TCP
+ name: http
+ selector:
+ app: jad-web-ui
+
+---
+apiVersion: gateway.networking.k8s.io/v1
+kind: HTTPRoute
+metadata:
+ name: jad-web-ui
+ namespace: edc-v
+spec:
+ parentRefs:
+ - name: edcv-gateway
+ kind: Gateway
+ sectionName: http
+ hostnames:
+ - ui.localhost
+ rules:
+ - matches:
+ - path:
+ type: PathPrefix
+ value: /
+ backendRefs:
+ - name: jad-web-ui
+ port: 80
+ weight: 1
diff --git a/k8s/base/keycloak-fe.yaml b/k8s/base/keycloak-fe.yaml
new file mode 100644
index 0000000..5e5e10d
--- /dev/null
+++ b/k8s/base/keycloak-fe.yaml
@@ -0,0 +1,222 @@
+#
+# Copyright (c) 2025 Metaform Systems, Inc.
+#
+# 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:
+# Metaform Systems, Inc. - initial API and implementation
+#
+
+---
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: keycloak4frontend
+ namespace: edc-v
+ labels:
+ platform: edcv
+spec:
+ replicas: 1
+ selector:
+ matchLabels:
+ app: keycloak-fe
+ template:
+ metadata:
+ labels:
+ app: keycloak-fe
+ platform: edcv
+ type: edcv-infra
+ spec:
+ containers:
+ - name: keycloak
+ image: quay.io/keycloak/keycloak:latest
+ args:
+ - "start-dev"
+ - "--health-enabled=true"
+ - "--import-realm"
+ ports:
+ - containerPort: 8080
+ name: http
+ - containerPort: 9000
+ name: health
+ env:
+ - name: KEYCLOAK_ADMIN
+ value: "admin"
+ - name: KC_BOOTSTRAP_ADMIN_USERNAME
+ value: "admin"
+ - name: KC_BOOTSTRAP_ADMIN_PASSWORD
+ value: "admin"
+ - name: KC_HTTP_ENABLED
+ value: "true"
+ - name: KC_HOSTNAME
+ value: http://keycloak-fe.localhost
+ - name: KC_HOSTNAME_STRICT
+ value: "true"
+ - name: KC_PROXY
+ value: "edge"
+ - name: KC_HEALTH_ENABLED
+ value: "true"
+ - name: KC_METRICS_ENABLED
+ value: "true"
+ - name: KC_LOG_LEVEL
+ value: INFO
+ - name: KC_DB
+ value: postgres
+ - name: POSTGRES_DB
+ value: keycloak_fe
+ - name: KC_DB_URL
+ value: jdbc:postgresql://postgres.edc-v.svc.cluster.local:5432/keycloak_fe
+ - name: KC_DB_USERNAME
+ value: "kc_fe"
+ - name: KC_DB_PASSWORD
+ value: "kc_fe"
+ volumeMounts:
+ - name: realm-config-ui
+ mountPath: /opt/keycloak/data/import
+ readinessProbe:
+ httpGet:
+ path: /health/ready
+ port: 9000
+ initialDelaySeconds: 5
+ periodSeconds: 10
+ successThreshold: 1
+ failureThreshold: 12
+ livenessProbe:
+ httpGet:
+ path: /health/live
+ port: 9000
+ initialDelaySeconds: 5
+ periodSeconds: 10
+ successThreshold: 1
+ failureThreshold: 12
+ volumes:
+ - name: realm-config-ui
+ configMap:
+ name: keycloak-realm-ui
+---
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: keycloak-realm-ui
+ namespace: edc-v
+ labels:
+ tier: infrastructure
+data:
+ ## redirectUri and webOrigins "*" are required for public clients, otherwise we'll run into redirect and CORS issues
+ jad-ui-realm.json: |
+ {
+ "realm": "jad-ui",
+ "enabled": true,
+ "displayName": "Keycloak Realm for authenticating frontend (UI) users",
+ "displayNameHtml": "
Keycloak Realm for authenticating frontend (UI) users
",
+ "clients": [
+ {
+ "clientId": "edc-aruba-provisioning-customers-portal-fe",
+ "enabled": true,
+ "clientAuthenticatorType": "client-secret",
+ "redirectUris": [
+ "http://localhost:4200/*",
+ "*"
+ ],
+ "webOrigins": [
+ "http://localhost:4200",
+ "*"
+ ],
+ "protocol": "openid-connect",
+ "publicClient": true,
+ "standardFlowEnabled": true,
+ "implicitFlowEnabled": false,
+ "directAccessGrantsEnabled": true,
+ "serviceAccountsEnabled": false,
+ "attributes": {
+ "pkce.code.challenge.method": "S256"
+ }
+ }
+ ],
+ "roles": {
+ "realm": [
+ {
+ "name": "EDC_ADMIN",
+ "description": "Administrator role for EDC portal"
+ },
+ {
+ "name": "EDC_USER_PARTICIPANT",
+ "description": "Participant role for EDC users"
+ }
+ ]
+ },
+ "users": [
+ {
+ "username": "admin",
+ "enabled": true,
+ "email": "admin@example.com",
+ "firstName": "Admin",
+ "lastName": "User",
+ "credentials": [
+ {
+ "type": "password",
+ "value": "admin123",
+ "temporary": false
+ }
+ ],
+ "realmRoles": ["EDC_ADMIN"]
+ },
+ {
+ "username": "user",
+ "enabled": true,
+ "email": "user@testcompany.it",
+ "firstName": "Test",
+ "lastName": "User",
+ "credentials": [
+ {
+ "type": "password",
+ "value": "user123",
+ "temporary": false
+ }
+ ],
+ "realmRoles": ["EDC_USER_PARTICIPANT"]
+ }
+ ]
+ }
+
+---
+apiVersion: v1
+kind: Service
+metadata:
+ name: keycloak-fe
+ namespace: edc-v
+ labels:
+ tier: infrastructure
+spec:
+ selector:
+ app: keycloak-fe
+ ports:
+ - port: 8080
+ targetPort: 8080
+ name: http
+
+---
+apiVersion: gateway.networking.k8s.io/v1
+kind: HTTPRoute
+metadata:
+ name: keycloak-fe
+ namespace: edc-v
+spec:
+ parentRefs:
+ - name: edcv-gateway
+ kind: Gateway
+ sectionName: http
+ hostnames:
+ - keycloak-fe.localhost
+ rules:
+ - matches:
+ - path:
+ type: PathPrefix
+ value: /
+ backendRefs:
+ - name: keycloak-fe
+ port: 8080
\ No newline at end of file
diff --git a/k8s/base/keycloak.yaml b/k8s/base/keycloak.yaml
index 9830d68..093e38f 100644
--- a/k8s/base/keycloak.yaml
+++ b/k8s/base/keycloak.yaml
@@ -83,17 +83,17 @@ spec:
path: /health/ready
port: 9000
initialDelaySeconds: 3
- periodSeconds: 5
+ periodSeconds: 10
successThreshold: 1
- failureThreshold: 5
+ failureThreshold: 12
livenessProbe:
httpGet:
path: /health/live
port: 9000
initialDelaySeconds: 3
- periodSeconds: 5
+ periodSeconds: 10
successThreshold: 1
- failureThreshold: 5
+ failureThreshold: 12
volumes:
- name: realm-config
configMap:
@@ -287,6 +287,9 @@ spec:
- port: 8080
targetPort: 8080
name: http
+ - port: 9000
+ targetPort: 9000
+ name: health
---
apiVersion: gateway.networking.k8s.io/v1
diff --git a/k8s/base/postgres.yaml b/k8s/base/postgres.yaml
index 3b6a719..5e36ee6 100644
--- a/k8s/base/postgres.yaml
+++ b/k8s/base/postgres.yaml
@@ -95,6 +95,12 @@ data:
\c keycloak
GRANT ALL ON SCHEMA public TO kc;
+ CREATE DATABASE keycloak_fe;
+ CREATE USER kc_fe WITH PASSWORD 'kc_fe';
+ GRANT ALL PRIVILEGES ON DATABASE keycloak_fe TO kc_fe;
+ \c keycloak_fe
+ GRANT ALL ON SCHEMA public TO kc_fe;
+
CREATE DATABASE cfm;
CREATE USER cfm WITH PASSWORD 'cfm';
GRANT ALL PRIVILEGES ON DATABASE cfm TO cfm;
diff --git a/tests/end2end/src/test/java/org/eclipse/edc/jad/tests/DataTransferEndToEndTest.java b/tests/end2end/src/test/java/org/eclipse/edc/jad/tests/DataTransferEndToEndTest.java
index b89dc7e..f996e5d 100644
--- a/tests/end2end/src/test/java/org/eclipse/edc/jad/tests/DataTransferEndToEndTest.java
+++ b/tests/end2end/src/test/java/org/eclipse/edc/jad/tests/DataTransferEndToEndTest.java
@@ -27,6 +27,7 @@
import org.junit.jupiter.api.Test;
import java.io.IOException;
+import java.time.Instant;
import java.util.List;
import java.util.Map;
@@ -55,6 +56,8 @@ public class DataTransferEndToEndTest {
private static final ConsoleMonitor MONITOR = new ConsoleMonitor(ConsoleMonitor.Level.DEBUG, true);
private static ClientCredentials providerCredentials;
private static ClientCredentials consumerCredentials;
+ private static String consumerContextId;
+ private static String providerContextId;
static String loadResourceFile(String resourceName) {
@@ -79,6 +82,8 @@ static void prepare() {
}
));
+ var slug = Instant.now().getEpochSecond();
+
var adminToken = createKeycloakToken("admin", "edc-v-admin-secret", "issuer-admin-api:write", "identity-api:write", "management-api:write", "identity-api:read");
createCelExpression(adminToken);
@@ -87,12 +92,16 @@ static void prepare() {
// onboard consumer
MONITOR.info("Onboarding consumer");
- var po = new ParticipantOnboarding("consumer", "did:web:identityhub.edc-v.svc.cluster.local%3A7083:consumer", VAULT_TOKEN, MONITOR.withPrefix("Consumer"));
+ var consumerName = "consumer-" + slug;
+ consumerContextId = "did:web:identityhub.edc-v.svc.cluster.local%3A7083:" + consumerName;
+ var po = new ParticipantOnboarding(consumerName, consumerContextId, VAULT_TOKEN, MONITOR.withPrefix("Consumer " + slug));
consumerCredentials = po.execute(cellId);
// onboard provider
MONITOR.info("Onboarding provider");
- var providerPo = new ParticipantOnboarding("provider", "did:web:identityhub.edc-v.svc.cluster.local%3A7083:provider", VAULT_TOKEN, MONITOR.withPrefix("Provider"));
+ var providerName = "provider-" + slug;
+ providerContextId = "did:web:identityhub.edc-v.svc.cluster.local%3A7083:" + providerName;
+ var providerPo = new ParticipantOnboarding(providerName, providerContextId, VAULT_TOKEN, MONITOR.withPrefix("Provider " + slug));
providerCredentials = providerPo.execute(cellId);
}
@@ -154,10 +163,10 @@ void testTodoDataTransfer() {
.auth().oauth2(getAccessToken(consumerCredentials.clientId(), consumerCredentials.clientSecret(), "management-api:write").accessToken())
.body("""
{
- "providerId":"did:web:identityhub.edc-v.svc.cluster.local%%3A7083:provider",
+ "providerId":"%s",
"policyId": "%s"
}
- """.formatted(offerId))
+ """.formatted(providerContextId, offerId))
.contentType("application/json")
.post("/api/mgmt/v1alpha/participants/%s/data".formatted(consumerCredentials.clientId()))
.then()
@@ -192,10 +201,10 @@ void testCertDataTransfer() {
.auth().oauth2(getAccessToken(consumerCredentials.clientId(), consumerCredentials.clientSecret(), "management-api:write").accessToken())
.body("""
{
- "providerId":"did:web:identityhub.edc-v.svc.cluster.local%%3A7083:provider",
+ "providerId":"%s",
"policyId": "%s"
}
- """.formatted(offerId))
+ """.formatted(providerContextId, offerId))
.contentType("application/json")
.post("/api/mgmt/v1alpha/participants/%s/transfer".formatted(consumerCredentials.clientId()))
.then()
@@ -226,9 +235,9 @@ private CatalogResponse fetchCatalog(ClientCredentials consumerCredentials) {
.contentType("application/json")
.body("""
{
- "counterPartyDid": "did:web:identityhub.edc-v.svc.cluster.local%3A7083:provider"
+ "counterPartyDid": "%s"
}
- """)
+ """.formatted(providerContextId))
.post("/api/mgmt/v1alpha/participants/%s/catalog".formatted(consumerCredentials.clientId()))
.then()
.statusCode(200)