Skip to content

Commit e82f6aa

Browse files
feat: Alice now uses a standalone STS
1 parent 60b0e71 commit e82f6aa

File tree

23 files changed

+815
-49
lines changed

23 files changed

+815
-49
lines changed

.github/workflows/run-end2end-tests.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ jobs:
6666
./gradlew clean dockerize
6767
- name: "Load Docker Images"
6868
run: |-
69-
kind load docker-image --name mxd data-service-api tx-identityhub tx-catalog-server tx-control-plane
69+
kind load docker-image --name mxd data-service-api tx-identityhub tx-identityhub-sts tx-catalog-server tx-sts
7070
7171
- name: "Terraform init"
7272
working-directory: mxd

mxd-runtimes/gradle/libs.versions.toml

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,14 +51,20 @@ edc-lib-keys = { module = "org.eclipse.edc:keys-lib", version.ref = "edc" }
5151
edc-lib-transform = { module = "org.eclipse.edc:transform-lib", version.ref = "edc" }
5252
edc-lib-jsonld = { module = "org.eclipse.edc:json-ld-lib", version.ref = "edc" }
5353

54-
# identith-hub SPI modules
54+
# identith-hub modules
5555
edc-ih-spi = { module = "org.eclipse.edc:identity-hub-spi", version.ref = "edc" }
56+
edc-ih-account-remote = { module = "org.eclipse.edc:sts-account-service-remote", version.ref = "edc" }
5657

5758
# identity hub BOM modules
5859
bom-ih-withsts = { module = "org.eclipse.edc:identityhub-with-sts-bom", version.ref = "edc" }
60+
bom-ih = { module = "org.eclipse.edc:identityhub-bom", version.ref = "edc" }
5961
bom-ih-sql = { module = "org.eclipse.edc:identityhub-feature-sql-bom", version.ref = "edc" }
6062
bom-ih-sql-sts = { module = "org.eclipse.edc:identityhub-feature-sql-sts-bom", version.ref = "edc" }
6163

64+
# STS modules
65+
edc-sql-sts-store = { module = "org.eclipse.edc:sts-client-store-sql", version.ref = "edc" }
66+
bom-sts = { module = "org.eclipse.edc:sts-feature-bom", version.ref = "edc" }
67+
6268
# Tractus-X Runtime BOMs
6369
edc-tx-controlplane = { module = "org.eclipse.tractusx.edc:edc-controlplane-postgresql-hashicorp-vault", version.ref = "tractusx" }
6470

@@ -76,6 +82,7 @@ testcontainers-postgres = { module = "org.testcontainers:postgresql", version.re
7682

7783
[bundles]
7884
connector = ["edc-boot", "edc-core-connector", "edc-ext-http", "edc-api-observability", "edc-ext-jsonld"]
85+
sql-sts = [ "edc-sql-sts-store", "edc-sql-core", "edc-sql-pool", "edc-sql-transactionlocal", "postgres"]
7986

8087

8188
[plugins]

mxd-runtimes/settings.gradle.kts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,9 @@ dependencyResolutionManagement {
4343
}
4444

4545
include(":tx-identityhub")
46-
include(":tx-control-plane")
46+
include(":tx-identityhub-sts")
4747
include(":tx-catalog-server")
48+
include(":tx-sts")
4849
include(":data-service-api")
4950
include(":jwt-signer")
5051
include(":e2e-test")

mxd-runtimes/tx-control-plane/build.gradle.kts renamed to mxd-runtimes/tx-identityhub-sts/build.gradle.kts

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,18 @@ plugins {
2020

2121
dependencies {
2222

23-
runtimeOnly(libs.edc.tx.controlplane)
24-
implementation(libs.edc.spi.crawler)
25-
implementation(catalogLibs.tx.dcp)
26-
implementation(libs.edc.spi.identitytrust)
23+
// used for the runtime
24+
runtimeOnly(libs.bom.ih.withsts)
25+
runtimeOnly(libs.bom.ih.sql)
26+
runtimeOnly(libs.bom.ih.sql.sts)
27+
runtimeOnly(libs.edc.vault.hashicorp)
2728

29+
// used for custom extensions
30+
implementation(libs.edc.core.connector)
31+
implementation(libs.edc.ih.spi)
32+
33+
testImplementation(libs.edc.lib.crypto)
34+
testImplementation(libs.edc.lib.keys)
2835
testImplementation(libs.edc.junit)
2936
}
3037

mxd-runtimes/tx-control-plane/src/main/docker/Dockerfile renamed to mxd-runtimes/tx-identityhub-sts/src/main/docker/Dockerfile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ RUN adduser \
2020
USER "$APP_USER"
2121
WORKDIR /app
2222

23-
COPY ${JAR} controlplane.jar
23+
COPY ${JAR} identityhub.jar
2424
COPY ${OTEL_JAR} opentelemetry-javaagent.jar
2525
COPY ${ADDITIONAL_FILES} ./
2626

@@ -34,4 +34,4 @@ ENTRYPOINT ["java", \
3434
"-Dotel.exporter.prometheus.port=9090", \
3535
"-Djava.security.egd=file:/dev/urandom", \
3636
"-jar", \
37-
"controlplane.jar"]
37+
"identityhub.jar"]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/*
2+
* Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
3+
*
4+
* This program and the accompanying materials are made available under the
5+
* terms of the Apache License, Version 2.0 which is available at
6+
* https://www.apache.org/licenses/LICENSE-2.0
7+
*
8+
* SPDX-License-Identifier: Apache-2.0
9+
*
10+
* Contributors:
11+
* Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - initial API and implementation
12+
*
13+
*/
14+
15+
package org.eclipse.edc.identityhub.demo;
16+
17+
import org.eclipse.edc.identityhub.spi.ScopeToCriterionTransformer;
18+
import org.eclipse.edc.runtime.metamodel.annotation.Extension;
19+
import org.eclipse.edc.runtime.metamodel.annotation.Provider;
20+
import org.eclipse.edc.spi.system.ServiceExtension;
21+
22+
23+
@Extension("DCP Demo: Core Extension for IdentityHub")
24+
public class IdentityHubExtension implements ServiceExtension {
25+
26+
@Provider
27+
public ScopeToCriterionTransformer createScopeTransformer() {
28+
return new TxScopeToCriterionTransformer();
29+
}
30+
31+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/*
2+
* Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
3+
*
4+
* This program and the accompanying materials are made available under the
5+
* terms of the Apache License, Version 2.0 which is available at
6+
* https://www.apache.org/licenses/LICENSE-2.0
7+
*
8+
* SPDX-License-Identifier: Apache-2.0
9+
*
10+
* Contributors:
11+
* Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - initial API and implementation
12+
*
13+
*/
14+
15+
package org.eclipse.edc.identityhub.demo;
16+
17+
import org.eclipse.edc.identityhub.spi.ScopeToCriterionTransformer;
18+
import org.eclipse.edc.spi.query.Criterion;
19+
import org.eclipse.edc.spi.result.Result;
20+
21+
import java.util.List;
22+
23+
import static org.eclipse.edc.spi.result.Result.failure;
24+
import static org.eclipse.edc.spi.result.Result.success;
25+
26+
/**
27+
* Implementation of {@link ScopeToCriterionTransformer} similar to the upstream one that maps tx scopes
28+
* to {@link Criterion} for querying the credentials (Just for testing)
29+
*/
30+
public class TxScopeToCriterionTransformer implements ScopeToCriterionTransformer {
31+
32+
public static final String TYPE_OPERAND = "verifiableCredential.credential.type";
33+
public static final String ALIAS_LITERAL = "org.eclipse.tractusx.vc.type";
34+
public static final String CONTAINS_OPERATOR = "contains";
35+
private static final String SCOPE_SEPARATOR = ":";
36+
private final List<String> allowedOperations = List.of("read", "*", "all");
37+
38+
@Override
39+
public Result<Criterion> transform(String scope) {
40+
var tokens = tokenize(scope);
41+
if (tokens.failed()) {
42+
return failure("Scope string cannot be converted: %s".formatted(tokens.getFailureDetail()));
43+
}
44+
var credentialType = tokens.getContent()[1];
45+
return success(new Criterion(TYPE_OPERAND, CONTAINS_OPERATOR, credentialType));
46+
}
47+
48+
protected Result<String[]> tokenize(String scope) {
49+
if (scope == null) return failure("Scope was null");
50+
51+
var tokens = scope.split(SCOPE_SEPARATOR);
52+
if (tokens.length != 3) {
53+
return failure("Scope string has invalid format.");
54+
}
55+
if (!ALIAS_LITERAL.equalsIgnoreCase(tokens[0])) {
56+
return failure("Scope alias MUST be %s but was %s".formatted(ALIAS_LITERAL, tokens[0]));
57+
}
58+
if (!allowedOperations.contains(tokens[2])) {
59+
return failure("Invalid scope operation: " + tokens[2]);
60+
}
61+
62+
return success(tokens);
63+
}
64+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
/*
2+
* Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
3+
*
4+
* This program and the accompanying materials are made available under the
5+
* terms of the Apache License, Version 2.0 which is available at
6+
* https://www.apache.org/licenses/LICENSE-2.0
7+
*
8+
* SPDX-License-Identifier: Apache-2.0
9+
*
10+
* Contributors:
11+
* Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - initial API and implementation
12+
*
13+
*/
14+
15+
package org.eclipse.edc.identityhub.seed;
16+
17+
import org.eclipse.edc.identityhub.spi.authentication.ServicePrincipal;
18+
import org.eclipse.edc.identityhub.spi.participantcontext.ParticipantContextService;
19+
import org.eclipse.edc.identityhub.spi.participantcontext.model.KeyDescriptor;
20+
import org.eclipse.edc.identityhub.spi.participantcontext.model.ParticipantManifest;
21+
import org.eclipse.edc.runtime.metamodel.annotation.Inject;
22+
import org.eclipse.edc.runtime.metamodel.annotation.Setting;
23+
import org.eclipse.edc.spi.EdcException;
24+
import org.eclipse.edc.spi.monitor.Monitor;
25+
import org.eclipse.edc.spi.security.Vault;
26+
import org.eclipse.edc.spi.system.ServiceExtension;
27+
import org.eclipse.edc.spi.system.ServiceExtensionContext;
28+
29+
import java.util.List;
30+
import java.util.Map;
31+
32+
import static java.util.Optional.ofNullable;
33+
34+
public class SuperUserSeedExtension implements ServiceExtension {
35+
public static final String NAME = "MVD ParticipantContext Seed Extension";
36+
public static final String DEFAULT_SUPER_USER_PARTICIPANT_ID = "super-user";
37+
38+
@Setting(value = "Explicitly set the initial API key for the Super-User")
39+
public static final String SUPERUSER_APIKEY_PROPERTY = "edc.ih.api.superuser.key";
40+
41+
@Setting(value = "Config value to set the super-user's participant ID.", defaultValue = DEFAULT_SUPER_USER_PARTICIPANT_ID)
42+
public static final String SUPERUSER_PARTICIPANT_ID_PROPERTY = "edc.ih.api.superuser.id";
43+
private String superUserParticipantId;
44+
private String superUserApiKey;
45+
private Monitor monitor;
46+
@Inject
47+
private ParticipantContextService participantContextService;
48+
@Inject
49+
private Vault vault;
50+
51+
@Override
52+
public String name() {
53+
return NAME;
54+
}
55+
56+
@Override
57+
public void initialize(ServiceExtensionContext context) {
58+
superUserParticipantId = context.getSetting(SUPERUSER_PARTICIPANT_ID_PROPERTY, DEFAULT_SUPER_USER_PARTICIPANT_ID);
59+
superUserApiKey = context.getSetting(SUPERUSER_APIKEY_PROPERTY, null);
60+
monitor = context.getMonitor();
61+
}
62+
63+
@Override
64+
public void start() {
65+
// create super-user
66+
if (participantContextService.getParticipantContext(superUserParticipantId).succeeded()) { // already exists
67+
monitor.debug("super-user already exists with ID '%s', will not re-create".formatted(superUserParticipantId));
68+
return;
69+
}
70+
participantContextService.createParticipantContext(ParticipantManifest.Builder.newInstance()
71+
.participantId(superUserParticipantId)
72+
.did("did:web:%s".formatted(superUserParticipantId)) // doesn't matter, not intended for resolution
73+
.active(true)
74+
.key(KeyDescriptor.Builder.newInstance()
75+
.keyGeneratorParams(Map.of("algorithm", "EdDSA", "curve", "Ed25519"))
76+
.keyId("%s-key".formatted(superUserParticipantId))
77+
.privateKeyAlias("%s-alias".formatted(superUserParticipantId))
78+
.build())
79+
.roles(List.of(ServicePrincipal.ROLE_ADMIN))
80+
.build())
81+
.onSuccess(generatedKey -> {
82+
var apiKey = ofNullable(superUserApiKey)
83+
.map(key -> {
84+
if (!key.contains(".")) {
85+
monitor.warning("Super-user key override: this key appears to have an invalid format, you may be unable to access some APIs. It must follow the structure: 'base64(<participantId>).<random-string>'");
86+
}
87+
participantContextService.getParticipantContext(superUserParticipantId)
88+
.onSuccess(pc -> vault.storeSecret(pc.getApiTokenAlias(), key)
89+
.onSuccess(u -> monitor.debug("Super-user key override successful"))
90+
.onFailure(f -> monitor.warning("Error storing API key in vault: %s".formatted(f.getFailureDetail()))))
91+
.onFailure(f -> monitor.warning("Error overriding API key for '%s': %s".formatted(superUserParticipantId, f.getFailureDetail())));
92+
return key;
93+
})
94+
.orElse(generatedKey.get("apiKey").toString());
95+
monitor.info("Created user 'super-user'. Please take note of the API Key: %s".formatted(apiKey));
96+
})
97+
.orElseThrow(f -> new EdcException("Error creating Super-User: " + f.getFailureDetail()));
98+
}
99+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#
2+
# Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
3+
#
4+
# This program and the accompanying materials are made available under the
5+
# terms of the Apache License, Version 2.0 which is available at
6+
# https://www.apache.org/licenses/LICENSE-2.0
7+
#
8+
# SPDX-License-Identifier: Apache-2.0
9+
#
10+
# Contributors:
11+
# Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - initial API and implementation
12+
#
13+
#
14+
15+
org.eclipse.edc.identityhub.demo.IdentityHubExtension
16+
org.eclipse.edc.identityhub.seed.SuperUserSeedExtension

0 commit comments

Comments
 (0)