Skip to content

Commit

Permalink
feat: STS client SQL store implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
wolf4ood committed Sep 13, 2024
1 parent d5b50ad commit 236dcb5
Show file tree
Hide file tree
Showing 26 changed files with 1,098 additions and 49 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ void token() {
.name("Name")
.secretAlias(clientKeyAlias)
.privateKeyAlias(privateKeyAlias)
.publicKeyReference("publicKeyReference")
.did(did)
.build();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import static org.eclipse.edc.iam.identitytrust.sts.client.configuration.StsClientConfigurationExtension.CLIENT_ID;
import static org.eclipse.edc.iam.identitytrust.sts.client.configuration.StsClientConfigurationExtension.CLIENT_NAME;
import static org.eclipse.edc.iam.identitytrust.sts.client.configuration.StsClientConfigurationExtension.CLIENT_PRIVATE_KEY_ALIAS;
import static org.eclipse.edc.iam.identitytrust.sts.client.configuration.StsClientConfigurationExtension.CLIENT_PUBLIC_KEY_REFERENCE;
import static org.eclipse.edc.iam.identitytrust.sts.client.configuration.StsClientConfigurationExtension.CLIENT_SECRET_ALIAS;
import static org.eclipse.edc.iam.identitytrust.sts.client.configuration.StsClientConfigurationExtension.CONFIG_PREFIX;
import static org.eclipse.edc.iam.identitytrust.sts.client.configuration.StsClientConfigurationExtension.ID;
Expand Down Expand Up @@ -65,6 +66,7 @@ void initialize_withClient(ServiceExtensionContext context, StsClientConfigurati
.privateKeyAlias("pAlias")
.secretAlias("sAlias")
.did("did:example:subject")
.publicKeyReference("publicReference")
.build();
var clientAlias = "client";
var config = ConfigFactory.fromMap(clientConfig(client, clientAlias));
Expand All @@ -74,7 +76,9 @@ void initialize_withClient(ServiceExtensionContext context, StsClientConfigurati
var capture = ArgumentCaptor.forClass(StsClient.class);
verify(clientStore).create(capture.capture());

assertThat(capture.getValue()).usingRecursiveComparison().isEqualTo(client);
assertThat(capture.getValue()).usingRecursiveComparison()
.ignoringFields("createdAt")
.isEqualTo(client);
}

private Map<String, String> clientConfig(StsClient client, String clientAlias) {
Expand All @@ -84,7 +88,8 @@ private Map<String, String> clientConfig(StsClient client, String clientAlias) {
clientAlias + "." + CLIENT_ID, client.getClientId(),
clientAlias + "." + CLIENT_SECRET_ALIAS, client.getSecretAlias(),
clientAlias + "." + CLIENT_DID, client.getDid(),
clientAlias + "." + CLIENT_PRIVATE_KEY_ALIAS, client.getPrivateKeyAlias()
clientAlias + "." + CLIENT_PRIVATE_KEY_ALIAS, client.getPrivateKeyAlias(),
clientAlias + "." + CLIENT_PUBLIC_KEY_REFERENCE, client.getPublicKeyReference()
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,13 @@ dependencies {
implementation(project(":spi:common:keys-spi"))
implementation(project(":extensions:common:iam:identity-trust:identity-trust-sts:identity-trust-sts-embedded"))
implementation(project(":core:common:token-core"))
implementation(project(":core:common:lib:store-lib"))

testImplementation(testFixtures(project(":spi:common:identity-trust-sts-spi")))
testImplementation(project(":core:common:lib:boot-lib"))
testImplementation(project(":core:common:lib:crypto-common-lib"))
testImplementation(project(":core:common:lib:keys-lib"))
testImplementation(project(":core:common:junit"))
testImplementation(project(":core:common:lib:query-lib"))
testImplementation(libs.nimbus.jwt)
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,21 +17,26 @@
import org.eclipse.edc.iam.identitytrust.sts.defaults.store.InMemoryStsClientStore;
import org.eclipse.edc.iam.identitytrust.sts.spi.store.StsClientStore;
import org.eclipse.edc.runtime.metamodel.annotation.Extension;
import org.eclipse.edc.runtime.metamodel.annotation.Inject;
import org.eclipse.edc.runtime.metamodel.annotation.Provider;
import org.eclipse.edc.spi.query.CriterionOperatorRegistry;
import org.eclipse.edc.spi.system.ServiceExtension;

@Extension(StsDefaultStoresExtension.NAME)
public class StsDefaultStoresExtension implements ServiceExtension {

public static final String NAME = "Secure Token Service Default Stores";

@Inject
private CriterionOperatorRegistry criterionOperatorRegistry;

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

@Provider(isDefault = true)
public StsClientStore clientStore() {
return new InMemoryStsClientStore();
return new InMemoryStsClientStore(criterionOperatorRegistry);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,17 @@

import org.eclipse.edc.iam.identitytrust.sts.spi.model.StsClient;
import org.eclipse.edc.iam.identitytrust.sts.spi.store.StsClientStore;
import org.eclipse.edc.spi.query.CriterionOperatorRegistry;
import org.eclipse.edc.spi.query.QueryResolver;
import org.eclipse.edc.spi.query.QuerySpec;
import org.eclipse.edc.spi.result.StoreResult;
import org.eclipse.edc.store.ReflectionBasedQueryResolver;
import org.jetbrains.annotations.NotNull;

import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Stream;

import static java.lang.String.format;

Expand All @@ -29,19 +35,54 @@
*/
public class InMemoryStsClientStore implements StsClientStore {

// we store it by clientId
private final Map<String, StsClient> clients = new ConcurrentHashMap<>();
private final QueryResolver<StsClient> queryResolver;


public InMemoryStsClientStore(CriterionOperatorRegistry criterionOperatorRegistry) {
queryResolver = new ReflectionBasedQueryResolver<>(StsClient.class, criterionOperatorRegistry);
}

@Override
public StoreResult<StsClient> create(StsClient client) {
return Optional.ofNullable(clients.putIfAbsent(client.getClientId(), client))
.map(old -> StoreResult.<StsClient>alreadyExists(format("Client with id %s already exists", client.getClientId())))
.map(old -> StoreResult.<StsClient>alreadyExists(format(CLIENT_EXISTS_TEMPLATE, client.getClientId())))
.orElseGet(() -> StoreResult.success(client));
}

@Override
public StoreResult<StsClient> findByClientId(String id) {
return Optional.ofNullable(clients.get(id))
public StoreResult<Void> update(StsClient stsClient) {
var prev = clients.replace(stsClient.getClientId(), stsClient);
return Optional.ofNullable(prev)
.map(a -> StoreResult.<Void>success())
.orElse(StoreResult.notFound(format(CLIENT_NOT_FOUND_BY_ID_TEMPLATE, stsClient.getId())));
}

@Override
public @NotNull Stream<StsClient> findAll(QuerySpec spec) {
return queryResolver.query(clients.values().stream(), spec);
}

@Override
public StoreResult<StsClient> findById(String id) {
return clients.values().stream()
.filter(client -> client.getId().equals(id))
.findFirst()
.map(StoreResult::success)
.orElseGet(() -> StoreResult.notFound(format(CLIENT_NOT_FOUND_BY_ID_TEMPLATE, id)));
}

@Override
public StoreResult<StsClient> findByClientId(String clientId) {
return Optional.ofNullable(clients.get(clientId))
.map(StoreResult::success)
.orElseGet(() -> StoreResult.notFound(format("Client with id %s not found.", id)));
.orElseGet(() -> StoreResult.notFound(format(CLIENT_NOT_FOUND_BY_CLIENT_ID_TEMPLATE, clientId)));
}

@Override
public StoreResult<StsClient> deleteById(String id) {
return findById(id)
.onSuccess(client -> clients.remove(client.getClientId()));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import org.eclipse.edc.keys.keyparsers.PemParser;
import org.eclipse.edc.keys.spi.KeyParserRegistry;
import org.eclipse.edc.keys.spi.PrivateKeyResolver;
import org.eclipse.edc.query.CriterionOperatorRegistryImpl;
import org.eclipse.edc.security.token.jwt.DefaultJwsSignerProvider;
import org.eclipse.edc.spi.security.Vault;
import org.eclipse.edc.token.JwtGenerationService;
Expand Down Expand Up @@ -56,7 +57,7 @@
@ComponentTest
public class StsClientTokenIssuanceIntegrationTest {

private final InMemoryStsClientStore clientStore = new InMemoryStsClientStore();
private final InMemoryStsClientStore clientStore = new InMemoryStsClientStore(CriterionOperatorRegistryImpl.ofDefaults());
private final Vault vault = new InMemoryVault(mock());
private final KeyParserRegistry keyParserRegistry = new KeyParserRegistryImpl();
private StsClientServiceImpl clientService;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

import org.eclipse.edc.iam.identitytrust.sts.spi.store.StsClientStore;
import org.eclipse.edc.iam.identitytrust.sts.spi.store.fixtures.StsClientStoreTestBase;
import org.eclipse.edc.query.CriterionOperatorRegistryImpl;
import org.junit.jupiter.api.BeforeEach;

public class InMemoryStsClientStoreTest extends StsClientStoreTestBase {
Expand All @@ -24,7 +25,7 @@ public class InMemoryStsClientStoreTest extends StsClientStoreTestBase {

@BeforeEach
void setUp() {
store = new InMemoryStsClientStore();
store = new InMemoryStsClientStore(CriterionOperatorRegistryImpl.ofDefaults());
}

@Override
Expand Down
31 changes: 31 additions & 0 deletions extensions/common/store/sql/sts-client-store-sql/build.gradle.kts
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
*
*/

plugins {
`java-library`
}

dependencies {
api(project(":spi:common:core-spi"))
api(project(":spi:common:transaction-spi"))

implementation(project(":extensions:common:sql:sql-core"))
implementation(project(":extensions:common:sql:sql-bootstrapper"))
implementation(project(":spi:common:identity-trust-sts-spi"))
implementation(project(":spi:common:transaction-datasource-spi"))
testImplementation(project(":core:common:junit"))
testImplementation(testFixtures(project(":extensions:common:sql:sql-core")))
testImplementation(testFixtures(project(":spi:common:identity-trust-sts-spi")))

}
Loading

0 comments on commit 236dcb5

Please sign in to comment.