Skip to content

Commit

Permalink
feat: Alice now uses a standalone STS
Browse files Browse the repository at this point in the history
  • Loading branch information
paullatzelsperger committed Oct 17, 2024
1 parent 60b0e71 commit e82f6aa
Show file tree
Hide file tree
Showing 23 changed files with 815 additions and 49 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/run-end2end-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ jobs:
./gradlew clean dockerize
- name: "Load Docker Images"
run: |-
kind load docker-image --name mxd data-service-api tx-identityhub tx-catalog-server tx-control-plane
kind load docker-image --name mxd data-service-api tx-identityhub tx-identityhub-sts tx-catalog-server tx-sts
- name: "Terraform init"
working-directory: mxd
Expand Down
9 changes: 8 additions & 1 deletion mxd-runtimes/gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -51,14 +51,20 @@ edc-lib-keys = { module = "org.eclipse.edc:keys-lib", version.ref = "edc" }
edc-lib-transform = { module = "org.eclipse.edc:transform-lib", version.ref = "edc" }
edc-lib-jsonld = { module = "org.eclipse.edc:json-ld-lib", version.ref = "edc" }

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

# identity hub BOM modules
bom-ih-withsts = { module = "org.eclipse.edc:identityhub-with-sts-bom", version.ref = "edc" }
bom-ih = { module = "org.eclipse.edc:identityhub-bom", version.ref = "edc" }
bom-ih-sql = { module = "org.eclipse.edc:identityhub-feature-sql-bom", version.ref = "edc" }
bom-ih-sql-sts = { module = "org.eclipse.edc:identityhub-feature-sql-sts-bom", version.ref = "edc" }

# STS modules
edc-sql-sts-store = { module = "org.eclipse.edc:sts-client-store-sql", version.ref = "edc" }
bom-sts = { module = "org.eclipse.edc:sts-feature-bom", version.ref = "edc" }

# Tractus-X Runtime BOMs
edc-tx-controlplane = { module = "org.eclipse.tractusx.edc:edc-controlplane-postgresql-hashicorp-vault", version.ref = "tractusx" }

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

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


[plugins]
Expand Down
3 changes: 2 additions & 1 deletion mxd-runtimes/settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,9 @@ dependencyResolutionManagement {
}

include(":tx-identityhub")
include(":tx-control-plane")
include(":tx-identityhub-sts")
include(":tx-catalog-server")
include(":tx-sts")
include(":data-service-api")
include(":jwt-signer")
include(":e2e-test")
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,18 @@ plugins {

dependencies {

runtimeOnly(libs.edc.tx.controlplane)
implementation(libs.edc.spi.crawler)
implementation(catalogLibs.tx.dcp)
implementation(libs.edc.spi.identitytrust)
// used for the runtime
runtimeOnly(libs.bom.ih.withsts)
runtimeOnly(libs.bom.ih.sql)
runtimeOnly(libs.bom.ih.sql.sts)
runtimeOnly(libs.edc.vault.hashicorp)

// used for custom extensions
implementation(libs.edc.core.connector)
implementation(libs.edc.ih.spi)

testImplementation(libs.edc.lib.crypto)
testImplementation(libs.edc.lib.keys)
testImplementation(libs.edc.junit)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ RUN adduser \
USER "$APP_USER"
WORKDIR /app

COPY ${JAR} controlplane.jar
COPY ${JAR} identityhub.jar
COPY ${OTEL_JAR} opentelemetry-javaagent.jar
COPY ${ADDITIONAL_FILES} ./

Expand All @@ -34,4 +34,4 @@ ENTRYPOINT ["java", \
"-Dotel.exporter.prometheus.port=9090", \
"-Djava.security.egd=file:/dev/urandom", \
"-jar", \
"controlplane.jar"]
"identityhub.jar"]
Original file line number Diff line number Diff line change
@@ -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
*
*/

package org.eclipse.edc.identityhub.demo;

import org.eclipse.edc.identityhub.spi.ScopeToCriterionTransformer;
import org.eclipse.edc.runtime.metamodel.annotation.Extension;
import org.eclipse.edc.runtime.metamodel.annotation.Provider;
import org.eclipse.edc.spi.system.ServiceExtension;


@Extension("DCP Demo: Core Extension for IdentityHub")
public class IdentityHubExtension implements ServiceExtension {

@Provider
public ScopeToCriterionTransformer createScopeTransformer() {
return new TxScopeToCriterionTransformer();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/*
* 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.identityhub.demo;

import org.eclipse.edc.identityhub.spi.ScopeToCriterionTransformer;
import org.eclipse.edc.spi.query.Criterion;
import org.eclipse.edc.spi.result.Result;

import java.util.List;

import static org.eclipse.edc.spi.result.Result.failure;
import static org.eclipse.edc.spi.result.Result.success;

/**
* Implementation of {@link ScopeToCriterionTransformer} similar to the upstream one that maps tx scopes
* to {@link Criterion} for querying the credentials (Just for testing)
*/
public class TxScopeToCriterionTransformer implements ScopeToCriterionTransformer {

public static final String TYPE_OPERAND = "verifiableCredential.credential.type";
public static final String ALIAS_LITERAL = "org.eclipse.tractusx.vc.type";
public static final String CONTAINS_OPERATOR = "contains";
private static final String SCOPE_SEPARATOR = ":";
private final List<String> allowedOperations = List.of("read", "*", "all");

@Override
public Result<Criterion> transform(String scope) {
var tokens = tokenize(scope);
if (tokens.failed()) {
return failure("Scope string cannot be converted: %s".formatted(tokens.getFailureDetail()));
}
var credentialType = tokens.getContent()[1];
return success(new Criterion(TYPE_OPERAND, CONTAINS_OPERATOR, credentialType));
}

protected Result<String[]> tokenize(String scope) {
if (scope == null) return failure("Scope was null");

var tokens = scope.split(SCOPE_SEPARATOR);
if (tokens.length != 3) {
return failure("Scope string has invalid format.");
}
if (!ALIAS_LITERAL.equalsIgnoreCase(tokens[0])) {
return failure("Scope alias MUST be %s but was %s".formatted(ALIAS_LITERAL, tokens[0]));
}
if (!allowedOperations.contains(tokens[2])) {
return failure("Invalid scope operation: " + tokens[2]);
}

return success(tokens);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
/*
* 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.identityhub.seed;

import org.eclipse.edc.identityhub.spi.authentication.ServicePrincipal;
import org.eclipse.edc.identityhub.spi.participantcontext.ParticipantContextService;
import org.eclipse.edc.identityhub.spi.participantcontext.model.KeyDescriptor;
import org.eclipse.edc.identityhub.spi.participantcontext.model.ParticipantManifest;
import org.eclipse.edc.runtime.metamodel.annotation.Inject;
import org.eclipse.edc.runtime.metamodel.annotation.Setting;
import org.eclipse.edc.spi.EdcException;
import org.eclipse.edc.spi.monitor.Monitor;
import org.eclipse.edc.spi.security.Vault;
import org.eclipse.edc.spi.system.ServiceExtension;
import org.eclipse.edc.spi.system.ServiceExtensionContext;

import java.util.List;
import java.util.Map;

import static java.util.Optional.ofNullable;

public class SuperUserSeedExtension implements ServiceExtension {
public static final String NAME = "MVD ParticipantContext Seed Extension";
public static final String DEFAULT_SUPER_USER_PARTICIPANT_ID = "super-user";

@Setting(value = "Explicitly set the initial API key for the Super-User")
public static final String SUPERUSER_APIKEY_PROPERTY = "edc.ih.api.superuser.key";

@Setting(value = "Config value to set the super-user's participant ID.", defaultValue = DEFAULT_SUPER_USER_PARTICIPANT_ID)
public static final String SUPERUSER_PARTICIPANT_ID_PROPERTY = "edc.ih.api.superuser.id";
private String superUserParticipantId;
private String superUserApiKey;
private Monitor monitor;
@Inject
private ParticipantContextService participantContextService;
@Inject
private Vault vault;

@Override
public String name() {
return NAME;
}

@Override
public void initialize(ServiceExtensionContext context) {
superUserParticipantId = context.getSetting(SUPERUSER_PARTICIPANT_ID_PROPERTY, DEFAULT_SUPER_USER_PARTICIPANT_ID);
superUserApiKey = context.getSetting(SUPERUSER_APIKEY_PROPERTY, null);
monitor = context.getMonitor();
}

@Override
public void start() {
// create super-user
if (participantContextService.getParticipantContext(superUserParticipantId).succeeded()) { // already exists
monitor.debug("super-user already exists with ID '%s', will not re-create".formatted(superUserParticipantId));
return;
}
participantContextService.createParticipantContext(ParticipantManifest.Builder.newInstance()
.participantId(superUserParticipantId)
.did("did:web:%s".formatted(superUserParticipantId)) // doesn't matter, not intended for resolution
.active(true)
.key(KeyDescriptor.Builder.newInstance()
.keyGeneratorParams(Map.of("algorithm", "EdDSA", "curve", "Ed25519"))
.keyId("%s-key".formatted(superUserParticipantId))
.privateKeyAlias("%s-alias".formatted(superUserParticipantId))
.build())
.roles(List.of(ServicePrincipal.ROLE_ADMIN))
.build())
.onSuccess(generatedKey -> {
var apiKey = ofNullable(superUserApiKey)
.map(key -> {
if (!key.contains(".")) {
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>'");
}
participantContextService.getParticipantContext(superUserParticipantId)
.onSuccess(pc -> vault.storeSecret(pc.getApiTokenAlias(), key)
.onSuccess(u -> monitor.debug("Super-user key override successful"))
.onFailure(f -> monitor.warning("Error storing API key in vault: %s".formatted(f.getFailureDetail()))))
.onFailure(f -> monitor.warning("Error overriding API key for '%s': %s".formatted(superUserParticipantId, f.getFailureDetail())));
return key;
})
.orElse(generatedKey.get("apiKey").toString());
monitor.info("Created user 'super-user'. Please take note of the API Key: %s".formatted(apiKey));
})
.orElseThrow(f -> new EdcException("Error creating Super-User: " + f.getFailureDetail()));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#
# 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
#
#

org.eclipse.edc.identityhub.demo.IdentityHubExtension
org.eclipse.edc.identityhub.seed.SuperUserSeedExtension
Loading

0 comments on commit e82f6aa

Please sign in to comment.