-
Notifications
You must be signed in to change notification settings - Fork 245
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
25 changed files
with
1,279 additions
and
0 deletions.
There are no files selected for viewing
46 changes: 46 additions & 0 deletions
46
core/common/jwt-core/src/main/java/org/eclipse/edc/jwt/LazyTokenGenerationService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
/* | ||
* Copyright (c) 2023 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.jwt; | ||
|
||
import org.eclipse.edc.jwt.spi.JwtDecorator; | ||
import org.eclipse.edc.jwt.spi.TokenGenerationService; | ||
import org.eclipse.edc.spi.iam.TokenRepresentation; | ||
import org.eclipse.edc.spi.result.Result; | ||
import org.eclipse.edc.spi.security.PrivateKeyResolver; | ||
import org.jetbrains.annotations.NotNull; | ||
|
||
import java.security.PrivateKey; | ||
import java.util.Objects; | ||
|
||
/** | ||
* Token generator that wraps {@link TokenGenerationServiceImpl} and does not cache the private | ||
* key, but instead it resolves it at token generation time. | ||
*/ | ||
public class LazyTokenGenerationService implements TokenGenerationService { | ||
|
||
private final PrivateKeyResolver privateKeyResolver; | ||
private final String keyAlias; | ||
|
||
public LazyTokenGenerationService(PrivateKeyResolver privateKeyResolver, String keyAlias) { | ||
this.privateKeyResolver = Objects.requireNonNull(privateKeyResolver); | ||
this.keyAlias = Objects.requireNonNull(keyAlias); | ||
} | ||
|
||
@Override | ||
public Result<TokenRepresentation> generate(@NotNull JwtDecorator... decorators) { | ||
var key = privateKeyResolver.resolvePrivateKey(keyAlias, PrivateKey.class); | ||
return new TokenGenerationServiceImpl(key).generate(decorators); | ||
} | ||
} |
16 changes: 16 additions & 0 deletions
16
extensions/common/iam/identity-trust/identity-trust-sts-core/build.gradle.kts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
plugins { | ||
`java-library` | ||
`maven-publish` | ||
} | ||
|
||
dependencies { | ||
api(project(":spi:common:transaction-spi")) | ||
api(project(":spi:common:identity-trust-spi")) | ||
api(project(":spi:common:identity-trust-sts-spi")) | ||
implementation(project(":extensions:common:iam:identity-trust:identity-trust-sts-embedded")) | ||
implementation(project(":core:common:jwt-core")) | ||
|
||
testImplementation(testFixtures(project(":spi:common:identity-trust-sts-spi"))) | ||
testImplementation(project(":core:common:junit")) | ||
testImplementation(libs.nimbus.jwt) | ||
} |
79 changes: 79 additions & 0 deletions
79
...src/main/java/org/eclipse/edc/iam/identitytrust/sts/core/StsDefaultServicesExtension.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
/* | ||
* Copyright (c) 2023 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.iam.identitytrust.sts.core; | ||
|
||
import org.eclipse.edc.iam.identitytrust.sts.core.defaults.service.StsClientServiceImpl; | ||
import org.eclipse.edc.iam.identitytrust.sts.core.defaults.service.StsClientTokenGeneratorServiceImpl; | ||
import org.eclipse.edc.iam.identitytrust.sts.service.StsClientService; | ||
import org.eclipse.edc.iam.identitytrust.sts.service.StsClientTokenGeneratorService; | ||
import org.eclipse.edc.iam.identitytrust.sts.store.StsClientStore; | ||
import org.eclipse.edc.jwt.LazyTokenGenerationService; | ||
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.runtime.metamodel.annotation.Setting; | ||
import org.eclipse.edc.spi.security.PrivateKeyResolver; | ||
import org.eclipse.edc.spi.security.Vault; | ||
import org.eclipse.edc.spi.system.ServiceExtension; | ||
import org.eclipse.edc.spi.system.ServiceExtensionContext; | ||
import org.eclipse.edc.transaction.spi.TransactionContext; | ||
|
||
import java.time.Clock; | ||
import java.util.concurrent.TimeUnit; | ||
|
||
@Extension(StsDefaultServicesExtension.NAME) | ||
public class StsDefaultServicesExtension implements ServiceExtension { | ||
|
||
public static final String NAME = "Secure Token Service Default Services"; | ||
|
||
@Setting(value = "Self-issued ID Token expiration in minutes. By default is 5 minutes", defaultValue = "" + StsDefaultServicesExtension.DEFAULT_STS_TOKEN_EXPIRATION_MIN) | ||
private static final String STS_TOKEN_EXPIRATION = "edc.iam.sts.token.expiration"; // in minutes | ||
|
||
private static final int DEFAULT_STS_TOKEN_EXPIRATION_MIN = 5; | ||
|
||
@Inject | ||
private StsClientStore clientStore; | ||
|
||
@Inject | ||
private TransactionContext transactionContext; | ||
|
||
@Inject | ||
private Vault vault; | ||
|
||
@Inject | ||
private PrivateKeyResolver privateKeyResolver; | ||
|
||
@Inject | ||
private Clock clock; | ||
|
||
@Override | ||
public String name() { | ||
return NAME; | ||
} | ||
|
||
@Provider | ||
public StsClientTokenGeneratorService clientTokenService(ServiceExtensionContext context) { | ||
var tokenExpiration = context.getSetting(STS_TOKEN_EXPIRATION, DEFAULT_STS_TOKEN_EXPIRATION_MIN); | ||
return new StsClientTokenGeneratorServiceImpl( | ||
(client) -> new LazyTokenGenerationService(privateKeyResolver, client.getPrivateKeyAlias()), | ||
clock, | ||
TimeUnit.MINUTES.toSeconds(tokenExpiration)); | ||
} | ||
|
||
@Provider | ||
public StsClientService clientService() { | ||
return new StsClientServiceImpl(clientStore, vault, transactionContext); | ||
} | ||
} |
37 changes: 37 additions & 0 deletions
37
...e/src/main/java/org/eclipse/edc/iam/identitytrust/sts/core/StsDefaultStoresExtension.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
/* | ||
* Copyright (c) 2023 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.iam.identitytrust.sts.core; | ||
|
||
import org.eclipse.edc.iam.identitytrust.sts.core.defaults.store.InMemoryStsClientStore; | ||
import org.eclipse.edc.iam.identitytrust.sts.store.StsClientStore; | ||
import org.eclipse.edc.runtime.metamodel.annotation.Extension; | ||
import org.eclipse.edc.runtime.metamodel.annotation.Provider; | ||
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"; | ||
|
||
@Override | ||
public String name() { | ||
return NAME; | ||
} | ||
|
||
@Provider(isDefault = true) | ||
public StsClientStore clientStore() { | ||
return new InMemoryStsClientStore(); | ||
} | ||
} |
57 changes: 57 additions & 0 deletions
57
...ava/org/eclipse/edc/iam/identitytrust/sts/core/defaults/service/StsClientServiceImpl.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
/* | ||
* Copyright (c) 2023 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.iam.identitytrust.sts.core.defaults.service; | ||
|
||
import org.eclipse.edc.iam.identitytrust.sts.model.StsClient; | ||
import org.eclipse.edc.iam.identitytrust.sts.service.StsClientService; | ||
import org.eclipse.edc.iam.identitytrust.sts.store.StsClientStore; | ||
import org.eclipse.edc.service.spi.result.ServiceResult; | ||
import org.eclipse.edc.spi.security.Vault; | ||
import org.eclipse.edc.transaction.spi.TransactionContext; | ||
|
||
import java.util.Optional; | ||
|
||
import static java.lang.String.format; | ||
|
||
public class StsClientServiceImpl implements StsClientService { | ||
|
||
private final StsClientStore stsClientStore; | ||
private final TransactionContext transactionContext; | ||
private final Vault vault; | ||
|
||
public StsClientServiceImpl(StsClientStore stsClientStore, Vault vault, TransactionContext transactionContext) { | ||
this.stsClientStore = stsClientStore; | ||
this.vault = vault; | ||
this.transactionContext = transactionContext; | ||
} | ||
|
||
@Override | ||
public ServiceResult<StsClient> create(StsClient client) { | ||
return transactionContext.execute(() -> ServiceResult.from(stsClientStore.create(client))); | ||
} | ||
|
||
@Override | ||
public ServiceResult<StsClient> findById(String clientId) { | ||
return transactionContext.execute(() -> ServiceResult.from(stsClientStore.findById(clientId))); | ||
} | ||
|
||
@Override | ||
public ServiceResult<StsClient> authenticate(StsClient client, String secret) { | ||
return Optional.ofNullable(vault.resolveSecret(client.getSecretAlias())) | ||
.filter(vaultSecret -> vaultSecret.equals(secret)) | ||
.map(s -> ServiceResult.success(client)) | ||
.orElseGet(() -> ServiceResult.badRequest(format("Failed to authenticate client with id %s", client.getId()))); | ||
} | ||
} |
73 changes: 73 additions & 0 deletions
73
...e/edc/iam/identitytrust/sts/core/defaults/service/StsClientTokenGeneratorServiceImpl.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
/* | ||
* Copyright (c) 2023 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.iam.identitytrust.sts.core.defaults.service; | ||
|
||
import org.eclipse.edc.iam.identitytrust.sts.embedded.EmbeddedSecureTokenService; | ||
import org.eclipse.edc.iam.identitytrust.sts.model.StsClient; | ||
import org.eclipse.edc.iam.identitytrust.sts.model.StsClientTokenAdditionalParams; | ||
import org.eclipse.edc.iam.identitytrust.sts.service.StsClientTokenGeneratorService; | ||
import org.eclipse.edc.iam.identitytrust.sts.service.StsTokenGenerationProvider; | ||
import org.eclipse.edc.service.spi.result.ServiceResult; | ||
import org.eclipse.edc.spi.iam.TokenRepresentation; | ||
|
||
import java.time.Clock; | ||
import java.util.Collections; | ||
import java.util.LinkedHashMap; | ||
import java.util.Map; | ||
|
||
import static org.eclipse.edc.jwt.spi.JwtRegisteredClaimNames.AUDIENCE; | ||
import static org.eclipse.edc.jwt.spi.JwtRegisteredClaimNames.ISSUER; | ||
import static org.eclipse.edc.jwt.spi.JwtRegisteredClaimNames.SUBJECT; | ||
|
||
public class StsClientTokenGeneratorServiceImpl implements StsClientTokenGeneratorService { | ||
|
||
private final Map<String, EmbeddedSecureTokenService> tokenGenerations; | ||
// TODO configurable? | ||
private final Integer capacity = 100; | ||
private final long tokenExpiration; | ||
private final StsTokenGenerationProvider tokenGenerationProvider; | ||
private final Clock clock; | ||
|
||
public StsClientTokenGeneratorServiceImpl(StsTokenGenerationProvider tokenGenerationProvider, Clock clock, long tokenExpiration) { | ||
this.tokenGenerationProvider = tokenGenerationProvider; | ||
this.clock = clock; | ||
this.tokenExpiration = tokenExpiration; | ||
this.tokenGenerations = Collections.synchronizedMap(new LinkedHashMap<>(capacity, .75f, true) { | ||
@Override | ||
protected boolean removeEldestEntry(Map.Entry<String, EmbeddedSecureTokenService> eldest) { | ||
return size() > capacity; | ||
} | ||
}); | ||
} | ||
|
||
@Override | ||
public ServiceResult<TokenRepresentation> tokenFor(StsClient client, StsClientTokenAdditionalParams additionalParams) { | ||
var embeddedTokenGenerator = tokenGenerations.computeIfAbsent(client.getId(), (id) -> new EmbeddedSecureTokenService(tokenGenerationProvider.tokenGeneratorFor(client), clock, tokenExpiration)); | ||
|
||
var claims = Map.of( | ||
ISSUER, client.getId(), | ||
SUBJECT, client.getId(), | ||
AUDIENCE, additionalParams.getAudience(), | ||
"client_id", client.getClientId()); | ||
|
||
var tokenResult = embeddedTokenGenerator.createToken(claims, additionalParams.getBearerAccessScope()); | ||
|
||
if (tokenResult.failed()) { | ||
return ServiceResult.badRequest(tokenResult.getFailureDetail()); | ||
} | ||
return ServiceResult.success(tokenResult.getContent()); | ||
} | ||
|
||
} |
47 changes: 47 additions & 0 deletions
47
...ava/org/eclipse/edc/iam/identitytrust/sts/core/defaults/store/InMemoryStsClientStore.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
/* | ||
* Copyright (c) 2023 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.iam.identitytrust.sts.core.defaults.store; | ||
|
||
import org.eclipse.edc.iam.identitytrust.sts.model.StsClient; | ||
import org.eclipse.edc.iam.identitytrust.sts.store.StsClientStore; | ||
import org.eclipse.edc.spi.result.StoreResult; | ||
|
||
import java.util.Map; | ||
import java.util.Optional; | ||
import java.util.concurrent.ConcurrentHashMap; | ||
|
||
import static java.lang.String.format; | ||
|
||
/** | ||
* In memory implementation of {@link StsClientStore} | ||
*/ | ||
public class InMemoryStsClientStore implements StsClientStore { | ||
|
||
private final Map<String, StsClient> clients = new ConcurrentHashMap<>(); | ||
|
||
@Override | ||
public StoreResult<StsClient> create(StsClient client) { | ||
return Optional.ofNullable(clients.putIfAbsent(client.getId(), client)) | ||
.map(old -> StoreResult.<StsClient>alreadyExists(format("Client with id %s already exists", client.getId()))) | ||
.orElseGet(() -> StoreResult.success(client)); | ||
} | ||
|
||
@Override | ||
public StoreResult<StsClient> findById(String id) { | ||
return Optional.ofNullable(clients.get(id)) | ||
.map(StoreResult::success) | ||
.orElseGet(() -> StoreResult.notFound(format("Client with id %s not found.", id))); | ||
} | ||
} |
16 changes: 16 additions & 0 deletions
16
...sts-core/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
# | ||
# Copyright (c) 2023 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.iam.identitytrust.sts.core.StsDefaultServicesExtension | ||
org.eclipse.edc.iam.identitytrust.sts.core.StsDefaultStoresExtension |
Oops, something went wrong.