Skip to content

Commit

Permalink
fix: not required properties in DcpDefaultServicesExtension (#4646)
Browse files Browse the repository at this point in the history
* chore: switch properties for embedded STS as not required

* Update extensions/common/iam/identity-trust/identity-trust-core/src/main/java/org/eclipse/edc/iam/identitytrust/core/DcpDefaultServicesExtension.java

Co-authored-by: Paul Latzelsperger <[email protected]>

---------

Co-authored-by: Paul Latzelsperger <[email protected]>
  • Loading branch information
wolf4ood and paullatzelsperger authored Nov 26, 2024
1 parent 2732d4a commit 9cdf67b
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
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.EdcException;
import org.eclipse.edc.spi.iam.AudienceResolver;
import org.eclipse.edc.spi.iam.ClaimToken;
import org.eclipse.edc.spi.result.Result;
Expand All @@ -39,31 +40,30 @@
import org.eclipse.edc.token.JwtGenerationService;

import java.time.Clock;
import java.util.ArrayList;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;

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

@Extension("Identity And Trust Extension to register default services")
public class DcpDefaultServicesExtension implements ServiceExtension {

@Setting(description = "Alias of private key used for signing tokens, retrieved from private key resolver.", key = "edc.iam.sts.privatekey.alias")
private String privateKeyAlias;

@Setting(description = "Key Identifier used by the counterparty to resolve the public key for token validation, e.g. did:example:123#public-key-1.", key = "edc.iam.sts.publickey.id")
private String publicKeyId;

@Setting(description = "Self-issued ID Token expiration in minutes. By default is 5 minutes", defaultValue = "" + DEFAULT_STS_TOKEN_EXPIRATION_MIN, key = "edc.iam.sts.token.expiration")
private long stsTokenExpirationMin;

public static final String STS_PUBLIC_KEY_ID = "edc.iam.sts.publickey.id";
public static final String STS_PRIVATE_KEY_ALIAS = "edc.iam.sts.privatekey.alias";

public static final String CLAIMTOKEN_VC_KEY = "vc";
// not a setting, it's defined in Oauth2ServiceExtension
private static final String OAUTH_TOKENURL_PROPERTY = "edc.oauth.token.url";

private static final int DEFAULT_STS_TOKEN_EXPIRATION_MIN = 5;

@Setting(description = "Alias of private key used for signing tokens, retrieved from private key resolver. Required when using EmbeddedSTS", key = STS_PRIVATE_KEY_ALIAS, required = false)
private String privateKeyAlias;
@Setting(description = "Key Identifier used by the counterparty to resolve the public key for token validation, e.g. did:example:123#public-key-1. Required when using EmbeddedSTS", key = STS_PUBLIC_KEY_ID, required = false)
private String publicKeyId;
@Setting(description = "Self-issued ID Token expiration in minutes. By default is 5 minutes", defaultValue = "" + DEFAULT_STS_TOKEN_EXPIRATION_MIN, key = "edc.iam.sts.token.expiration")
private long stsTokenExpirationMin;
@Inject
private Clock clock;
@Inject
Expand All @@ -75,13 +75,21 @@ public class DcpDefaultServicesExtension implements ServiceExtension {
public SecureTokenService createDefaultTokenService(ServiceExtensionContext context) {
context.getMonitor().info("Using the Embedded STS client, as no other implementation was provided.");

var errors = new ArrayList<String>();

checkProperty(STS_PRIVATE_KEY_ALIAS, privateKeyAlias, errors::add);
checkProperty(STS_PUBLIC_KEY_ID, publicKeyId, errors::add);

if (!errors.isEmpty()) {
var msg = String.join(", ", errors);
throw new EdcException("The following errors were found in the configuration of the Embedded STS: [%s]".formatted(msg));
}

if (context.getSetting(OAUTH_TOKENURL_PROPERTY, null) != null) {
context.getMonitor().warning("The property '%s' was configured, but no remote SecureTokenService was found on the classpath. ".formatted(OAUTH_TOKENURL_PROPERTY) +
"This could be an indicator of a configuration problem.");
"This could be an indication of a configuration problem.");
}


return new EmbeddedSecureTokenService(new JwtGenerationService(externalSigner), () -> privateKeyAlias, () -> publicKeyId, clock, TimeUnit.MINUTES.toSeconds(stsTokenExpirationMin), jtiValidationStore);
}

Expand Down Expand Up @@ -124,4 +132,10 @@ public ClaimTokenCreatorFunction defaultClaimTokenFunction() {
};
}

private void checkProperty(String key, String value, Consumer<String> onMissing) {
if (value == null) {
onMissing.accept("No setting found for key '%s'.".formatted(key));
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import org.eclipse.edc.iam.identitytrust.sts.embedded.EmbeddedSecureTokenService;
import org.eclipse.edc.junit.extensions.DependencyInjectionExtension;
import org.eclipse.edc.keys.spi.PrivateKeyResolver;
import org.eclipse.edc.spi.EdcException;
import org.eclipse.edc.spi.monitor.Monitor;
import org.eclipse.edc.spi.result.Result;
import org.eclipse.edc.spi.system.ServiceExtensionContext;
Expand All @@ -37,6 +38,9 @@
import java.util.UUID;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.eclipse.edc.iam.identitytrust.core.DcpDefaultServicesExtension.STS_PRIVATE_KEY_ALIAS;
import static org.eclipse.edc.iam.identitytrust.core.DcpDefaultServicesExtension.STS_PUBLIC_KEY_ID;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
Expand Down Expand Up @@ -92,6 +96,17 @@ void verify_defaultServiceWithWarning(ServiceExtensionContext context, DcpDefaul
verify(mockedMonitor).warning(anyString());
}

@Test
void verify_defaultServiceWithMissingConfig(ServiceExtensionContext context) {
var ext = new DcpDefaultServicesExtension();

assertThatThrownBy(() -> ext.createDefaultTokenService(context))
.isInstanceOf(EdcException.class)
.hasMessageContaining(STS_PUBLIC_KEY_ID)
.hasMessageContaining(STS_PRIVATE_KEY_ALIAS);

}

@Test
void verify_defaultIssuerRegistry(ServiceExtensionContext context, ObjectFactory factory) {
Monitor mockedMonitor = mock();
Expand Down

0 comments on commit 9cdf67b

Please sign in to comment.